说到安防监控摄像头,时间戳添加显示是刚需功能。OSD进行时间戳添加就是通过硬件RGN(Region)高性能处理模式来实现,有效降低CPU占用率且直接从物理内存操作数据,实现内存零拷贝。

        拿到视频裸数据后,硬件RGN叠加时间戳具体流程如下:

         一,时间戳字符串渲染。将时间戳进行字符串处理,使用TTF库进行获取相应字体格式与大小,最后调用TTF_RenderText_Solid将时间戳字符串进行RGB格式上色,此时时间戳就是一个贴图。

       

    int ret;
    TTF_Font *ttf_font;
    char date_ptr[100];
    SDL_Surface *text_surface;
    SDL_Surface *convert_text_surface;

    ret = TTF_Init();
    if (ret < 0)
    {
        printf("TTF_Init Failed..........\n");
    }
    printf("TTF_Init Success...........\n");
    ttf_font = TTF_OpenFont("./fzlth.ttf", 48);
    if (ttf_font == NULL)
    {
        printf("TTF_OpenFont failed..........\n");
    }
    printf("TTF_OpenFont Success..........\n");
    SDL_Color sdl_color;
    sdl_color.r = 0;
    sdl_color.g = 0;
    sdl_color.b = 0;

    time_t g_time; // Init g_time
    tm *p;         // Init *p

        time(&g_time);       // get time for g_time, and change time by now..........
        p = gmtime(&g_time); // put g_time for *p
        sprintf(date_ptr, "%4d-%02d-%02d %02d:%02d:%02d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, 8 + p->tm_hour, p->tm_min, p->tm_sec);
        // char *pstr = date_ptr;
        text_surface = TTF_RenderText_Solid(ttf_font, date_ptr, sdl_color);

        二,图像格式转换。使用SDL库调用SDLConvertSurface将时间戳贴图转化成RGBA8888格式。

SDL_PixelFormat *pixel_format;
    pixel_format = (SDL_PixelFormat *)malloc(sizeof(SDL_PixelFormat));
    pixel_format->BitsPerPixel = 32;
    pixel_format->BytesPerPixel = 4;
    pixel_format->Amask = 0XFF000000;
    pixel_format->Rmask = 0X00FF0000;
    pixel_format->Gmask = 0X0000FF00;
    pixel_format->Bmask = 0X000000FF;
convert_text_surface = SDL_ConvertSurface(text_surface, pixel_format, 0); // by mask to convert the test
        if (convert_text_surface == NULL)
        {
            printf("convert text surface failed........\n");
        }

        三,Bitmap位图封装。将RGBA8888格式的时间戳贴图封装成Bitmap位图,其中需要注意位图宽高进行16字节对齐,不然容易导致位图出现渲染字符偏移。

BITMAP_S bitmap;
        bitmap.u32Width = convert_text_surface->w;
        bitmap.u32Height = convert_text_surface->h;
        bitmap.enPixelFormat = PIXEL_FORMAT_ARGB_8888;
        bitmap.pData = malloc((bitmap.u32Height) * (bitmap.u32Width) * (pixel_format->BytesPerPixel));
        memcpy(bitmap.pData, (convert_text_surface->pixels), (convert_text_surface->w) * (convert_text_surface->h) * (pixel_format->BytesPerPixel));

         四,配置rgn_info区域参数。就是OSD_REGION_INFO_S的设置,决定bitmap位图在视频上的显示属性(位置、尺寸、使能、层级)。

OSD_REGION_INFO_S rgn_info;
        rgn_info.enRegionId = REGION_ID_0;
        rgn_info.u32Width = get_align16_value(convert_text_surface->w, 16);
        rgn_info.u32Height = get_align16_value(convert_text_surface->h, 16);
        rgn_info.u32PosX = 144; // start POSE-x
        rgn_info.u32PosY = 64;  // start pose-Y
        rgn_info.u8Enable = 1;
        rgn_info.u8Inverse = 0;
  

        最后,硬件叠加并绑定VENC编码通道。调用RK_MPI_RGN_SetBitMap根据rgn_info的配置将Bitmap位图设置到VENC编码通道中。这样通过RGN就可将Bitmap时间戳贴图叠加到每一帧图像数据中再进行VENC编码。

 ret = RK_MPI_VENC_RGN_SetBitMap(0, &rgn_info, &bitmap);
        if (!ret)
        {
            printf("VENC_RGN SetBitMap Success........\n");
        }

       使用OSD硬件进行时间戳添加,几乎不耗CPU,适合安防场景。若想实现占用CPU移植性强轻便,跨平台,不依赖硬件进行时间戳添加的方案,则可采用OpenCV开源库,可通过cv::Mat矩阵进行处理采集的裸数据,通过cv::putText将string时间戳字符串进行添加到cv::Mat矩阵中,完成软件层字符串叠加。

//将其中的argv[1]改成视频流中的每一帧数据就可以展示了
Mat testImage = imread(argv[1]);
    if (testImage.empty())
    {
        printf("read testImg failed.........\n");
        return 0;
    }

    string str = argv[2]; // str
    Point bg;             // point position
    bg.x = 0;
    bg.y = 400;

    int fontFace = cv::FONT_HERSHEY_PLAIN; // font
    double fontScale = 4.0;
    int thickness = 4;

    putText(testImage, str, bg, fontFace, fontScale, Scalar(0, 0, 255), thickness, LINE_8); // LINE_8 is the type of the thick

    imwrite("putText.jpg", testImage);

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐