海思3559C实现OSD字符叠加的探索(二)最新版本SDL和SDL_ttf的从编译到使用支持透明背景,彩色字体

海思3559C实现OSD字符叠加的探索(一)详细介绍了编译的过程,本文适合快速上手,快速编译,如无特别说明,代码版本与上文保持一致。

经过上文的探索,发现可以不主动去编译FreeType这里就省略了。

交叉编译SDL

下载目前最新版本代码:

Release 2.26.5 · libsdl-org/SDL (github.com)

#解压代码
tar -zxvf SDL-release-2.26.5.tar.gz
#重命名 可以不操作该步骤
mv SDL-release-2.26.5/ libSDL
#进入目录 创建install目录
cd libSDL/
mkdir install
#配置交叉编译环境
./configure --prefix=$PWD/install CC=aarch64-himix100-linux-gcc --host=aarch64-linux --disable-alsa --disable-pulseaudio --enable-esd=no
#编译
make -j16
#安装
make install
  • --prefix=$PWD/install指定编译器的安装路径为当前目录下的install文件夹。
  • CC=aarch64-himix100-linux-gcc指定编译器为aarch64-himix100-linux-gcc。
  • --host=aarch64-linux指定目标平台为aarch64-linux。
  • --disable-alsa禁用ALSA音频驱动库。
  • --disable-pulseaudio禁用PulseAudio音频驱动库。
  • --enable-esd=no禁用ESD音频驱动库。

交叉编译SDL_ttf

下载目前最新版本代码:

Index of /projects/SDL_ttf/release (libsdl.org)

下载SDL2_ttf-2.20.2.tar.gz

#进入代码根目录创建install目录
mkdir install

#配置  
./configure --prefix=$PWD/install CC=aarch64-himix100-linux-gcc --host=aarch64-linux --with-sdl-prefix=$PWD/../libSDL/install

#编译
make -j 16

#安装
make install
  • --prefix=$PWD/install指定安装路径为当前目录下的install文件夹。
  • CC=aarch64-himix100-linux-gcc指定使用交叉编译器aarch64-himix100-linux-gcc进行编译。
  • --host=aarch64-linux指定目标机器的操作系统为aarch64-linux。
  • --with-sdl-prefix=$PWD/../libSDL/install指定SDL库的安装路径为上级目录下的libSDL/install文件夹。

测试程序和编译命令

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>

#include "SDL.h"
#include "SDL_ttf.h"
#include "time.h"

#define FONT_PATH "./SourceHanSansCN-Regular.ttf"
int string_to_bmp(char *pu8Str);
int cnt = 0;
int main()
{

    time_t now;
    struct tm *ptm;
    char timestr[100] = {0};
    struct timeval start_time, end_time;
    int elapsed_time;

    while (1)
    {
        sleep(1);
        time(&now);
        ptm = localtime(&now);
        snprintf(timestr, 100, "时间%d-%02d-%02d %02d:%02d:%02d", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
        gettimeofday(&start_time, NULL); // 记录程序开始时刻
        string_to_bmp(timestr);
        gettimeofday(&end_time, NULL); // 记录程序结束时刻

        elapsed_time = (int)(1000.0 * (end_time.tv_sec - start_time.tv_sec) + 0.001 * (end_time.tv_usec - start_time.tv_usec));
        printf("生成位图时间:%d 毫秒\n", elapsed_time);
        memset(timestr, 0, 100);
        if (cnt++ > 4)
        {
            break;
        }
    }
    return 0;
}

int string_to_bmp(char *pu8Str)
{
    SDL_PixelFormat *fmt;
    TTF_Font *font;
    SDL_Surface *text, *temp;

    if (TTF_Init() < 0)
    {
        fprintf(stderr, "Couldn't initialize TTF: %s\n", SDL_GetError());
        SDL_Quit();
    }

    font = TTF_OpenFont(FONT_PATH, 80);
    if (font == NULL)
    {
        fprintf(stderr, "Couldn't load %d pt font from %s: %s\n", 18, "ptsize", SDL_GetError());
    }

    SDL_Color forecol = {0xff, 0xff, 0xff, 0xff};
    text = TTF_RenderUTF8_Solid(font, pu8Str, forecol);

    fmt = (SDL_PixelFormat *)malloc(sizeof(SDL_PixelFormat));
    memset(fmt, 0, sizeof(SDL_PixelFormat));
    fmt->BitsPerPixel = 16;
    fmt->BytesPerPixel = 2;
    // fmt->colorkey = 0xffffffff;
    // fmt->alpha = 0xff;

    temp = SDL_ConvertSurface(text, fmt, 0);

    char savename[10] = {0};

    snprintf(savename, 10, "%d.bmp", cnt);
    printf("savename = %s\n", savename);
    SDL_SaveBMP(temp, savename);

    SDL_FreeSurface(text);
    SDL_FreeSurface(temp);
    TTF_CloseFont(font);
    TTF_Quit();
    free(fmt);
    fmt = NULL;

    return 0;
}


aarch64-himix100-linux-gcc test.c -o str2bmp -I../libSDL/install/include/SDL2  -I../libSDL2_ttf/install/include/SDL2   -L. -lSDL2 -lSDL2_ttf -lpthread
图片[1]-海思3559C实现OSD字符叠加的探索(二)最新版本SDL和SDL_ttf的从编译到使用支持透明背景,彩色字体-天煜博客

在Hi3559C上叠加时间戳

#ifdef __cplusplus
#if __cplusplus
extern "C"
{
#endif
#endif /* End of #ifdef __cplusplus */

#define LOG_TAG "VideoModuleMain"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/time.h>

#include "sample_comm.h"
#include "elog.h"
#include "str2bmp.h"

#define FONT_PATH "/mnt/appfs/app/SourceHanSansSC-Normal.ttf"
#define FONT_SIZE 36

    int StopStat = 0;

    /******************************************************************************
     * function : to process abnormal case
     ******************************************************************************/
    void SAMPLE_VIO_HandleSig(HI_S32 signo)
    {
        if (SIGINT == signo || SIGTERM == signo)
        {
            StopStat = 1;
            SAMPLE_COMM_All_ISP_Stop();
            SAMPLE_COMM_SYS_Exit();
            printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
        }
        exit(-1);
    }

    int dump_row(const char *pFileName, int size, char *buffer)
    {
        FILE *pFile = NULL;
        int fileLen;

        pFile = fopen(pFileName, "wb");
        if (pFile == NULL)
        {
            printf("error opening file %s\n", pFileName);
            return -1;
        }

        fileLen = fwrite(buffer, 1, size, pFile);
        if (fileLen != size)
            printf("write file %s\n", pFileName);

        fclose(pFile);
        return 0;
    }
    OSD_SDL_ATTR_S stOsdAttr = {0};
    HI_S32 SampleVpssChnCreateRegion()
    {
        HI_S32 s32Ret;
        MPP_CHN_S stChn;
        RGN_ATTR_S stRgnAttr;
        RGN_CHN_ATTR_S stChnAttr;
        BITMAP_S stBitmap;
        VPSS_CHN VpssChn = 0;
        char osdStr[128] = {0};

        /* load bitmap*/
        memset(&stOsdAttr, 0, sizeof(OSD_SDL_ATTR_S));
        snprintf(osdStr, sizeof(osdStr), "测试北京dHKhAi!@#$132ou9");
        stOsdAttr.pcStr = osdStr;
        stOsdAttr.u32FontSize = 88;
        stOsdAttr.u32FgColor = 0xfff08f72;
        stOsdAttr.u32BgColor = 0;
        s32Ret = OSD_SDL_Str2Bmp32(&stOsdAttr);
        if (s32Ret)
        {
            log_e("failed!");
        }
        else
        {
            log_i("osd bitmap success width:%d height:%d stOsdAttr.u32BgColor:%#x\n", stOsdAttr.u32Width, stOsdAttr.u32Height, stOsdAttr.u32BgColor);
        }
        stBitmap.enPixelFormat = PIXEL_FORMAT_ARGB_8888;
        stBitmap.u32Height = stOsdAttr.u32Height;
        stBitmap.u32Width = stOsdAttr.u32Width;
        stBitmap.pData = stOsdAttr.pData;

        /* creat region*/
        stRgnAttr.enType = OVERLAYEX_RGN;
        stRgnAttr.unAttr.stOverlayEx.enPixelFmt = PIXEL_FORMAT_ARGB_8888;
        stRgnAttr.unAttr.stOverlayEx.stSize.u32Width = 2000;
        stRgnAttr.unAttr.stOverlayEx.stSize.u32Height = 500;
        stRgnAttr.unAttr.stOverlayEx.u32BgColor = 0xfc;
        stRgnAttr.unAttr.stOverlayEx.u32CanvasNum = 2;

        s32Ret = HI_MPI_RGN_Create(VpssChn, &stRgnAttr);
        if (s32Ret != HI_SUCCESS)
        {
            printf("region of vpss chn %d create fail. value=0x%x.", VpssChn, s32Ret);
            return s32Ret;
        }

        /*attach region to chn*/
        stChn.enModId = HI_ID_VPSS;
        stChn.s32DevId = 0;
        stChn.s32ChnId = VpssChn;

        stChnAttr.bShow = HI_TRUE;
        stChnAttr.enType = OVERLAYEX_RGN;
        stChnAttr.unChnAttr.stOverlayExChn.stPoint.s32X = 128;
        stChnAttr.unChnAttr.stOverlayExChn.stPoint.s32Y = 128;
        stChnAttr.unChnAttr.stOverlayExChn.u32BgAlpha = 128;
        stChnAttr.unChnAttr.stOverlayExChn.u32FgAlpha = 128;
        stChnAttr.unChnAttr.stOverlayExChn.u32Layer = 0;

        s32Ret = HI_MPI_RGN_SetBitMap(VpssChn, &stBitmap);
        if (s32Ret != HI_SUCCESS)
        {
            printf("region set bitmap to  vpss chn %d fail. value=0x%x.", VpssChn, s32Ret);
            free(stBitmap.pData);
            return s32Ret;
        }

        s32Ret = HI_MPI_RGN_AttachToChn(VpssChn, &stChn, &stChnAttr);
        if (s32Ret != HI_SUCCESS)
        {
            printf("region attach to  vpss chn %d fail. value=0x%x.", VpssChn, s32Ret);
            return s32Ret;
        }

        return HI_SUCCESS;
    }

    HI_S32 SampleVpssChnDestroyRegion()
    {
        HI_S32 s32Ret;
        MPP_CHN_S stChn;
        VPSS_CHN VpssChn = 0;
        stChn.enModId = HI_ID_VPSS;
        stChn.s32DevId = 0;
        stChn.s32ChnId = VpssChn;
        /* detach region from chn */
        s32Ret = HI_MPI_RGN_DetachFromChn(VpssChn, &stChn);
        if (s32Ret != HI_SUCCESS)
        {
            printf("region attach to  vpss chn %d fail. value=0x%x.", VpssChn, s32Ret);
            return s32Ret;
        }

        /* destroy region */
        s32Ret = HI_MPI_RGN_Destroy(VpssChn);
        if (s32Ret != HI_SUCCESS)
        {
            printf("destroy  vpss chn %d region fail. value=0x%x.", VpssChn, s32Ret);
            return s32Ret;
        }

        free(stOsdAttr.pData);
        stOsdAttr.pData = NULL;
        return HI_SUCCESS;
    }

    static int get_cur_time_ms(void)
    {
        struct timeval tv;
        gettimeofday(&tv, NULL);                       // 使用gettimeofday获取当前系统时间
        return (tv.tv_sec * 1000 + tv.tv_usec / 1000); // 利用struct timeval结构体将时间转换为ms
    }

    void *thread_function(void *arg)
    {
        HI_S32 s32Ret = HI_SUCCESS;
        BITMAP_S stBitmap;
        VPSS_CHN VpssChn = 0;
        int t1;
        sleep(2);
        while (1)
        {
            t1 = get_cur_time_ms();
            // 获取当前时间
            time_t now = time(NULL);
            struct tm *tm_now = localtime(&now);

            // 格式化当前时间
            char time_str[30];
            sprintf(time_str, "%04d-%02d-%02d %02d:%02d:%02d",
                    tm_now->tm_year + 1900, tm_now->tm_mon + 1, tm_now->tm_mday,
                    tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);

            /* load bitmap*/
            // t1 = get_cur_time_ms();
            memset(&stOsdAttr, 0, sizeof(OSD_SDL_ATTR_S));
            stOsdAttr.pcStr = time_str;
            stOsdAttr.u32FontSize = 50;
            stOsdAttr.u32FgColor = 0xff18dcff;
            stOsdAttr.u32BgColor = 0;
            s32Ret = OSD_SDL_Str2Bmp32(&stOsdAttr);
            if (s32Ret)
                log_e("failed!");
            // log_d("Bitmap width:%d height:%d speed time %d \n", stOsdAttr.u32Width, stOsdAttr.u32Height, get_cur_time_ms() - t1);

            stBitmap.enPixelFormat = PIXEL_FORMAT_ARGB_8888;
            stBitmap.u32Height = stOsdAttr.u32Height;
            stBitmap.u32Width = stOsdAttr.u32Width;
            stBitmap.pData = stOsdAttr.pData;
            s32Ret = HI_MPI_RGN_SetBitMap(0, &stBitmap);
            if (s32Ret != HI_SUCCESS)
            {
                printf("region set bitmap to  vpss chn %d fail. value=0x%x.", VpssChn, s32Ret);
                free(stBitmap.pData);
            }
            printf("%d ", get_cur_time_ms() - t1);
            // 等待1秒钟
            usleep(900 * 1000);
        }
    }

    HI_S32 SAMPLE_VIO_1080P60_PARALLEL(VO_INTF_TYPE_E enVoIntfType)
    {
        HI_S32 s32Ret = HI_SUCCESS;
        VI_DEV ViDev0 = 0;
        VI_PIPE ViPipe0 = 0;
        VI_CHN ViChn = 0;
        HI_S32 s32ViCnt = 1;
        VPSS_GRP VpssGrp0 = 0;
        VPSS_CHN VpssChn[4] = {VPSS_CHN0, VPSS_CHN1, VPSS_CHN2, VPSS_CHN3};
        VPSS_GRP_ATTR_S stVpssGrpAttr = {0};
        VPSS_CHN_ATTR_S stVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];
        HI_BOOL abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {HI_TRUE};
        VO_DEV VoDev = SAMPLE_VO_DEV_DHD0;
        VO_CHN VoChn = 0;
        VO_INTF_SYNC_E g_enIntfSync = VO_OUTPUT_1080P60; // VO_OUTPUT_3840x2160_30;
        HI_U32 g_u32DisBufLen = 3;
        PIC_SIZE_E enPicSize = PIC_3840x2160;
        WDR_MODE_E enWDRMode = WDR_MODE_NONE;
        DYNAMIC_RANGE_E enDynamicRange = DYNAMIC_RANGE_SDR8;
        PIXEL_FORMAT_E enPixFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
        VIDEO_FORMAT_E enVideoFormat = VIDEO_FORMAT_LINEAR;
        COMPRESS_MODE_E enCompressMode = COMPRESS_MODE_NONE;
        VI_VPSS_MODE_E enMastPipeMode = VI_PARALLEL_VPSS_PARALLEL;
        SIZE_S stSize;
        HI_U32 u32BlkSize;
        VB_CONFIG_S stVbConf;
        SAMPLE_VI_CONFIG_S stViConfig;
        SAMPLE_VO_CONFIG_S stVoConfig;

        /************************************************
        step 1:  Get all sensors information, need one vi
            ,and need one mipi --
        *************************************************/
        SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);
        stViConfig.s32WorkingViNum = s32ViCnt;

        stViConfig.as32WorkingViId[0] = 0;
        stViConfig.astViInfo[0].stSnsInfo.MipiDev = SAMPLE_COMM_VI_GetComboDevBySensor(stViConfig.astViInfo[0].stSnsInfo.enSnsType, 0);
        stViConfig.astViInfo[0].stSnsInfo.s32BusId = 0;

        stViConfig.astViInfo[0].stDevInfo.ViDev = ViDev0;
        stViConfig.astViInfo[0].stDevInfo.enWDRMode = enWDRMode;

        stViConfig.astViInfo[0].stPipeInfo.enMastPipeMode = enMastPipeMode;
        stViConfig.astViInfo[0].stPipeInfo.aPipe[0] = ViPipe0;
        stViConfig.astViInfo[0].stPipeInfo.aPipe[1] = -1;
        stViConfig.astViInfo[0].stPipeInfo.aPipe[2] = -1;
        stViConfig.astViInfo[0].stPipeInfo.aPipe[3] = -1;

        stViConfig.astViInfo[0].stChnInfo.ViChn = ViChn;
        stViConfig.astViInfo[0].stChnInfo.enPixFormat = enPixFormat;
        stViConfig.astViInfo[0].stChnInfo.enDynamicRange = enDynamicRange;
        stViConfig.astViInfo[0].stChnInfo.enVideoFormat = enVideoFormat;
        stViConfig.astViInfo[0].stChnInfo.enCompressMode = enCompressMode;

        /************************************************
        step 2:  Get  input size
        *************************************************/
        s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[0].stSnsInfo.enSnsType, &enPicSize);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_GetSizeBySensor failed with %d!\n", s32Ret);
            return s32Ret;
        }

        s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed with %d!\n", s32Ret);
            return s32Ret;
        }

        /************************************************
        step3:  Init SYS and common VB
        *************************************************/
        memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
        stVbConf.u32MaxPoolCnt = 2;

        u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_10, COMPRESS_MODE_SEG, DEFAULT_ALIGN);
        stVbConf.astCommPool[0].u64BlkSize = u32BlkSize;
        stVbConf.astCommPool[0].u32BlkCnt = 10;

        u32BlkSize = VI_GetRawBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_RGB_BAYER_16BPP, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
        stVbConf.astCommPool[1].u64BlkSize = u32BlkSize;
        stVbConf.astCommPool[1].u32BlkCnt = 4;

        s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("system init failed with %d!\n", s32Ret);
            goto EXIT;
        }

        s32Ret = SAMPLE_COMM_VI_SetParam(&stViConfig);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_SetParam failed with %d!\n", s32Ret);
            goto EXIT;
        }

        /************************************************
        step 4: start VI
        *************************************************/
        s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_StartVi failed with %d!\n", s32Ret);
            goto EXIT3;
        }

        /************************************************
        step 5: start VPSS, need one grp
        *************************************************/
        stVpssGrpAttr.u32MaxW = stSize.u32Width;
        stVpssGrpAttr.u32MaxH = stSize.u32Height;
        stVpssGrpAttr.enPixelFormat = enPixFormat;
        stVpssGrpAttr.enDynamicRange = enDynamicRange;
        stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1;
        stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1;

        abChnEnable[0] = HI_TRUE;
        stVpssChnAttr[0].u32Width = stSize.u32Width;
        stVpssChnAttr[0].u32Height = stSize.u32Height;
        stVpssChnAttr[0].enChnMode = VPSS_CHN_MODE_USER;
        stVpssChnAttr[0].enCompressMode = enCompressMode;
        stVpssChnAttr[0].enDynamicRange = enDynamicRange;
        stVpssChnAttr[0].enPixelFormat = enPixFormat;
        stVpssChnAttr[0].enVideoFormat = enVideoFormat;
        stVpssChnAttr[0].stFrameRate.s32SrcFrameRate = -1;
        stVpssChnAttr[0].stFrameRate.s32DstFrameRate = -1;
        stVpssChnAttr[0].u32Depth = 1;
        stVpssChnAttr[0].bMirror = HI_FALSE;
        stVpssChnAttr[0].bFlip = HI_FALSE;
        stVpssChnAttr[0].stAspectRatio.enMode = ASPECT_RATIO_NONE;

        s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp0, abChnEnable, &stVpssGrpAttr, stVpssChnAttr);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VPSS_Start Grp0 failed with %d!\n", s32Ret);
            goto EXIT2;
        }

        /************************************************
        step 6:  VI bind VPSS, for total parallel, no need bind
        *************************************************/

        /************************************************
        step 7:  start V0
        *************************************************/
        SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
        stVoConfig.VoDev = VoDev;
        stVoConfig.enVoIntfType = enVoIntfType;
        stVoConfig.enIntfSync = g_enIntfSync;
        stVoConfig.enPicSize = enPicSize;
        stVoConfig.u32DisBufLen = g_u32DisBufLen;
        stVoConfig.enDstDynamicRange = enDynamicRange;
        stVoConfig.enVoMode = VO_MODE_1MUX;

        s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VO_StartVO failed with %d!\n", s32Ret);
            goto EXIT1;
        }
        /************************************************
        step 8:  VI bind VPSS bind VO
        *************************************************/
        s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe0, ViChn, VpssGrp0);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_Bind_VPSS failed with %d!\n", s32Ret);
            goto EXIT1;
        }

        SAMPLE_COMM_VENC_Onvif_Start();
        SAMPLE_COMM_VPSS_FrameProcStart();

        /*         s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp0, VpssChn[0], stVoConfig.VoDev, VoChn);

                if (HI_SUCCESS != s32Ret)
                {
                    SAMPLE_PRT("SAMPLE_COMM_VPSS_Bind_VO Grp0 failed with %d!\n", s32Ret);
                    goto EXIT0;
                } */
        SampleVpssChnCreateRegion();
        PAUSE();

        StopStat = 1;
        SampleVpssChnDestroyRegion();
        SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp0, VpssChn[0], stVoConfig.VoDev, VoChn);
        SAMPLE_COMM_VI_UnBind_VPSS(ViPipe0, ViChn, VpssGrp0);
    EXIT1:
        SAMPLE_COMM_VO_StopVO(&stVoConfig);
    EXIT2:
        SAMPLE_COMM_VPSS_Stop(VpssGrp0, abChnEnable);
    EXIT3:
        SAMPLE_COMM_VI_StopVi(&stViConfig);
    EXIT:
        SAMPLE_COMM_SYS_Exit();

        return s32Ret;
    }
/******************************************************************************
 * function    : main()
 * Description : main
 ******************************************************************************/
#ifdef __HuaweiLite__
    int app_main(int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
    {
        HI_S32 s32Ret = HI_FAILURE;
        VO_INTF_TYPE_E enVoIntfType = VO_INTF_HDMI;

#ifdef __HuaweiLite__
#else
    signal(SIGINT, SAMPLE_VIO_HandleSig);
    signal(SIGTERM, SAMPLE_VIO_HandleSig);
#endif

        /* close printf buffer */
        setbuf(stdout, NULL);
        /* initialize EasyLogger */
        elog_init();
        /* set EasyLogger log format */
        elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL);
        elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
        elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
        elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
        elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_ALL & ~ELOG_FMT_FUNC);
        elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_ALL & ~ELOG_FMT_FUNC);
#ifdef ELOG_COLOR_ENABLE
        elog_set_text_color_enabled(true);
#endif
        /* start EasyLogger */
        elog_start();

        s32Ret = OSD_SDL_Init(FONT_PATH, FONT_SIZE);
        if (HI_SUCCESS != s32Ret)
            log_e("fail");

        // 创建线程
        pthread_t tid;
        s32Ret = pthread_create(&tid, NULL, thread_function, NULL);
        if (s32Ret != 0)
        {
            printf("Create thread failed!\n");
            return s32Ret;
        }

#if 1
        // imx477 hdmi vo sample
        SAMPLE_VIO_1080P60_PARALLEL(enVoIntfType);
#endif

        return s32Ret;
    }

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */

生成位图和叠加位图耗时(也就是thread_function中每个循环的耗时,生成位图宽度:451 高度:73 单位:毫秒):

6 6 9 7 5 6 5 5 5 6 6 5 6 10 5 5 5 5 5 10 5 5 9 6 5 6 7 6 11 5 5 7 5 5 5 5 5 5 10 5 5 6 4 5 5 7 5 5 10 5 5 5 5 5 9 5 6 5 8 5 6 5 7 5 5 9 5 5 5 5 5 5 5 5 5 5 5 5 5 11 5 5 7 5 5 10 7 5 5 5 6 5 6 5 5 9 6 5 5 7 5 5 5 6 5 5 7 4 5 4 6 5 6 5 7 4 6 11 5 5 7 4 6 9 5 5 5 7 5 5 5 6 4 5 9 5 5 6 12 5 5 5 5 5 5 5 5 4 10 5 4 6 5 5 10 5 5 5 5 5 5 5 5 5 6 4 5 5 6 5 4 5 5 5 5 5 5 5 5 7 5 5 5 5 5 5 10 5 5 6 5 7 9 5 4 4 5 4 5 4 5 5 5 5 5 5 5 5 5 5 5 5 5 4 5 5 5 4 5 5 5 5 5 4 5 10 5 5 8 6 5 7 5 5 5 5 4 5 5 5 5 4 5 5 5 4 5 5 4 7 4 5 5 5 5 5 4 5 5 4 5 4 5 5 6 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 4 4 5 5 5 4 5 5 5 6 4 5 4 5 4 5 4 5 5 5 5 4 4 4 5 4 5 4 5 5 5 6 5 4 5 5 5 5 4 5 5 5 5 4 5 5 5 4 5 5 5 5 4 4

str2bmp.c

#include <pthread.h>
#include "SDL_ttf.h"
#include "SDL.h"

#include "str2bmp.h"

#ifndef OSD_SDL_CHECK_RET_W
#define OSD_SDL_CHECK_RET_W(express)                                                          \
	do                                                                                        \
	{                                                                                         \
		s32Ret = express;                                                                     \
		if (EI_SUCCESS != s32Ret)                                                             \
		{                                                                                     \
			printf("Failed at %s: LINE: %d  (ret:0x%#x!)\n", __FUNCTION__, __LINE__, s32Ret); \
		}                                                                                     \
	} while (0)
#endif

#ifndef OSD_SDL_CHECK_RET_E
#define OSD_SDL_CHECK_RET_E(express)                                                          \
	do                                                                                        \
	{                                                                                         \
		s32Ret = express;                                                                     \
		if (EI_SUCCESS != s32Ret)                                                             \
		{                                                                                     \
			printf("Failed at %s: LINE: %d  (ret:0x%#x!)\n", __FUNCTION__, __LINE__, s32Ret); \
			goto exit;                                                                        \
		}                                                                                     \
	} while (0)
#endif

#define OSD_SDL_CHECK_NULL_PTR(pstPtr)                                              \
	do                                                                              \
	{                                                                               \
		if (NULL == (pstPtr))                                                       \
		{                                                                           \
			printf("Null pointer! FUNCTION %s,LINE %d!\n", __FUNCTION__, __LINE__); \
			s32Ret = -1;                                                            \
			goto exit;                                                              \
		}                                                                           \
	} while (0)

/* sdl_ttf and freetype is not mutil-threading safe */
typedef pthread_mutex_t OSD_SDL_Mutex;
#define OSD_SDL_CreateMutex(m) pthread_mutex_init(&m, NULL)
#define OSD_SDL_DestroyMutex(m) pthread_mutex_destroy(&m)
#define OSD_SDL_LockMutex(m) pthread_mutex_lock(&(m))
#define OSD_SDL_UnLockMutex(m) pthread_mutex_unlock(&(m))
static OSD_SDL_Mutex osd_mutex;

#define ALIGN_UP(x, align) (((int)(x) + (align - 1)) & ~(align - 1))
#define ALIGN_DOWN(x, align) (((int)(x) & ~(align - 1)))

static TTF_Font *font;

int OSD_SDL_Init(const char *file, int ptsize)
{
	OSD_SDL_CreateMutex(osd_mutex);
	if (TTF_Init() < 0)
	{
		printf("Couldn't initialize TTF: %s\n", SDL_GetError());
		SDL_Quit();
		return -1;
	}

	font = TTF_OpenFont(file, ptsize);
	if (font == NULL)
	{
		printf("Couldn't load %d pt font from %s: %s\n",
			   ptsize, "ptsize", SDL_GetError());
		return -1;
	}

	return 0;
}

int OSD_SDL_DeInit()
{
	TTF_CloseFont(font);
	TTF_Quit();
	OSD_SDL_DestroyMutex(osd_mutex);
	return 0;
}

int OSD_SDL_Str2Bmp32(OSD_SDL_ATTR_S *pstOsdAttr)
{
	int s32Ret = 0;
	OSD_SDL_LockMutex(osd_mutex);

	SDL_PixelFormat fmt;
	SDL_Surface *text = NULL;
	SDL_Surface *temp = NULL;
	SDL_Color fg = {0};
	SDL_Color bg = {0};

	OSD_SDL_CHECK_NULL_PTR(font);
	if (pstOsdAttr->u32DataSzie)
		OSD_SDL_CHECK_NULL_PTR(pstOsdAttr->pData);

	memset(&fmt, 0, sizeof(SDL_PixelFormat));
	fmt.BitsPerPixel = 32;
	fmt.BytesPerPixel = 4;
	fmt.Rmask = 0x00ff0000;
	fmt.Gmask = 0x0000ff00;
	fmt.Bmask = 0x000000ff;
	fmt.Amask = 0xff000000;
	fmt.palette = NULL;

	fg.a = (pstOsdAttr->u32FgColor & fmt.Amask) >> 24;
	fg.r = (pstOsdAttr->u32FgColor & fmt.Rmask) >> 16;
	fg.g = (pstOsdAttr->u32FgColor & fmt.Gmask) >> 8;
	fg.b = (pstOsdAttr->u32FgColor & fmt.Bmask);

	bg.a = (pstOsdAttr->u32BgColor & fmt.Amask) >> 24;
	bg.r = (pstOsdAttr->u32BgColor & fmt.Rmask) >> 16;
	bg.g = (pstOsdAttr->u32BgColor & fmt.Gmask) >> 8;
	bg.b = (pstOsdAttr->u32BgColor & fmt.Bmask);

	TTF_SetFontSize(font, pstOsdAttr->u32FontSize);

	if (bg.a == 0x00)
		text = TTF_RenderUTF8_Solid(font, pstOsdAttr->pcStr, fg);
	else
		text = TTF_RenderUTF8(font, pstOsdAttr->pcStr, fg, bg);

	OSD_SDL_CHECK_NULL_PTR(text);

	temp = SDL_ConvertSurface(text, &fmt, 0);
	OSD_SDL_CHECK_NULL_PTR(temp);

	if (pstOsdAttr->u32DataSzie)
	{
		if ((temp->w) * (temp->h) * fmt.BytesPerPixel > pstOsdAttr->u32DataSzie)
		{
			printf("[%s %d] Bitmap is too large w:%d h:%d BytesPerPixel:%d u32DataSzie:%d",
				   __func__, __LINE__, temp->w, temp->h, fmt.BytesPerPixel, pstOsdAttr->u32DataSzie);
			s32Ret = -1;
			goto exit;
		}
	}
	else
	{
		pstOsdAttr->pData = calloc(1, temp->w * temp->h * fmt.BytesPerPixel);
	}

	memcpy(pstOsdAttr->pData, temp->pixels, (temp->w) * (temp->h) * fmt.BytesPerPixel);
	pstOsdAttr->u32Width = temp->w;
	pstOsdAttr->u32Height = temp->h;

exit:
	if (text)
		SDL_FreeSurface(text);
	if (temp)
		SDL_FreeSurface(temp);
	OSD_SDL_UnLockMutex(osd_mutex);
	return s32Ret;
}

f936a7f37cdb53d1e6c22165ca120e1a

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容