RK35xx系列(Android11平台) OSD文字水印功能

目前OSD主流的实现方案 freetype2+SDL2+SDL2_ttf等开源库来生成位图进行填

各个库的链接:

freetype-2.10.4:https://mirror.yongbok.net/nongnu/freetype/freetype-2.10.4.tar.gz

SDL2-2.0.14:https://www.libsdl.org/release/SDL2-2.0.14.tar.gz

SDL2_ttf-2.0.15:https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.15.tar.gz

RK3568交叉编译器:

https://download.csdn.net/download/yinsui1839/87352165

自行配置好交叉编译器环境变量

freetype库: 
./configure --prefix=$PWD/.. CC=aarch64-linux-android-gcc CXX=aarch64-linux-android-g++ --host=arm-linux --without-zlib --enable-freetype-config
make -j16 && make install

SDL库: 
./configure --prefix=$PWD/.. CC=aarch64-linux-android-gcc CXX=aarch64-linux-android-g++ --host=arm-linux --disable-alsa --disable-pulseaudio --enable-esd=no

make -j16 && make install


SDL2_ttf库:
./configure --prefix=$PWD CC=aarch64-linux-android-gcc CXX=aarch64-linux-android-g++ --host=arm-linux --with-sdl-prefix=$PWD/.. --with-sdl-exec-prefix=$PWD/.. FT2_CONFIG=$PWD/../bin/freetype-config PKG_CONFIG_PATH=$PWD/../lib/pkgconfig

make -j16 && make install

编译好后会产生libfreetype.a libSDL.a libSDLmain.a libSDL_ttf.a

需要使用到库的CMakeLists.txt加上


include_directories(/xxxxx/freetype-2.4.10/include/freetype)
include_directories(/xxxxx/SDL-1.2.15/SDL/include/SDL)
include_directories(/xxxxx/SDL_ttf-2.0.11/SDLTtf/include/SDL)

//注意.a链接顺序,报错调整一下
target_link_libraries(
                      ...
                      z
                      ${PROJECT_SOURCE_DIR}/mpp/project/osd/so/libSDL_ttf.a 
                      ${PROJECT_SOURCE_DIR}/mpp/project/osd/so/libfreetype.a 
                      ${PROJECT_SOURCE_DIR}/mpp/project/osd/so/libSDL.a
                      ${PROJECT_SOURCE_DIR}/mpp/project/osd/so/libSDLmain.a)

//字体ttf路径
#define Font_Path "/sdcard/Download/1.ttf"
//osdBuf 输入OSD的图像 
//srcWidthOSD宽 
// srcHeight OSD高
//dst_buf 在打底图像 格式NV21 NV12
//打底图像 dstWidth 宽
//打底图像 dstHeight 高
//x y覆盖的起始坐标
void ImcompositeYuv(unsigned char *osdBuf, int srcWidth, int srcHeight,
                              unsigned char *dst_buf, int dstWidth, int dstHeight, int x, int y)
{
    int dstOffset = x + y * dstWidth;
    int nv_start = dstWidth * dstHeight;
    int len = dstWidth * dstHeight * 3 / 2;
    int nv_index;
    int yOffset;
    int uOffset;
    int vOffset;
    for (int h = 0; h < srcHeight; h++)
    {
        for (int w = 0; w < srcWidth; w++)
        {
            if (osdBuf[w + h * srcWidth] == 1)
            {
                nv_index = (h + y) / 2 * dstWidth + (w + x) - (w + x) % 2;
                
                if(nv_index > len) continue;
                yOffset = (dstOffset + (h * dstWidth) + w);
                uOffset = nv_start + nv_index;
                vOffset = uOffset + 1;
                dst_buf[yOffset] = 0xff;
                dst_buf[uOffset] = 128;
                dst_buf[vOffset] = 128;
            }
        }
    }
}
int SDL_OSDtoBMP(char *pstrShow)
     {
          static SDL_Surface *text = NULL;
          static TTF_Font *font = NULL;
          int x = 0, y = 0;
          int i = 0, n = 0;
          char *pTempPixels = NULL;
          char *l_ps8Bmp = NULL;

          if (NULL == pstrShow)
               return -1;
          if (strlen(pstrShow) <= 0)
               return -1;

          SDL_Color forecol = {(unsigned char)((0xffffffff >> 24) & 0xff),
                               (unsigned char)((0xffffffff  >> 16) & 0xff),
                               (unsigned char)((0xffffffff  >> 8) & 0xff),
                               (unsigned char)((0xffffffff  >> 0) & 0xff)};
          if (font == NULL)
          {
               if (font != NULL)
               {
                    TTF_CloseFont(font);
                    font = NULL;
               }
               font = TTF_OpenFont(Font_Path, 16);
          }
          
          if (font == NULL)
          {
               fprintf(stderr, "Couldn't load[%s] %s %d \n", Font_Path, "ptsize", 12);
               return -1;
          }

          if (pstrShow != NULL )
          {
               text = TTF_RenderUTF8_Solid(font, pstrShow, forecol);
               unsigned char *ImageBuf = NULL;
               
               ImcompositeYuv(text->pixels,text->pitch,text->h,/*图像buf*/ ImageBuf,
               1920,1080,300,300);
               SDL_FreeSurface(text);
               
          }
          return 0;
     }

int main(){
    SDL_OSDtoBMP("hello world");
    return 0;
}

可以使用RGA imblend(srcA, dst)进行叠加,输入的图像和OSD都要求RGB格式和宽高一致,灵活性不是很好,而且覆盖一张高达50ms,耗时较高所以弃用!

所以自己写了 ImcompositeYuv可以对YUV格式的图像进行OSD叠加,目前自测只有500微妙的耗时

附上另外两种覆盖函数:

//RGB
void ImcompositeRgb(unsigned char *osdBuf, int srcWidth, int srcHeight,
                              unsigned char *dst_buf, int dstWidth, int dstHeight, int x, int y)
{
    int dstOffset = x + y * dstWidth;
    for (int h = 0; h < srcHeight; h++)
    {
        for (int w = 0; w < srcWidth; w++)
        {
            if (osdBuf[w + h * srcWidth] & 0x8000)
            {
                int rOffset = (dstOffset + (h * dstWidth) + w);
                int gOffset = rOffset + 1;
                int bOffset = rOffset + 2;
                dst_buf[rOffset] = 0xff;
                dst_buf[gOffset] = 0xff;
                dst_buf[bOffset] = 0xff;
            }
        }
    }
}

//RK rgb覆盖 必须是RGB类型数据,宽高也必须保持与覆盖图像一致
void Imcomposite(char *srcdata, int srcWidth, int srcHeight, int srcFormat,
                               char *dst_buf, int dstWidth, int dstHeight, int dstFormat)
{
    TimeDelayLog time("Imcomposite",false);
    im_rect src_rect;
    im_rect dst_rect;
    rga_buffer_t srcA;
    rga_buffer_t dst;
    IM_STATUS STATUS;

    int ret = 0;

    memset(&src_rect, 0, sizeof(src_rect));
    memset(&dst_rect, 0, sizeof(dst_rect));
    memset(&srcA, 0, sizeof(srcA));
    memset(&dst, 0, sizeof(dst));
    srcA = wrapbuffer_virtualaddr(srcdata, srcWidth, srcHeight, srcFormat);
    dst = wrapbuffer_virtualaddr(dst_buf, dstWidth, dstHeight, dstFormat);
    if (srcA.width == 0 || dst.width == 0)
    {
        printf("%s, %s\n", __FUNCTION__, imStrError());
        return;
    }
    srcA.format = srcFormat;
    dst.format = dstFormat;
    EasyMutex Lock(&mMutex);
    ret = imcheck(srcA, dst, src_rect, dst_rect);
    if (IM_STATUS_NOERROR != ret)
    {
        printf("%d, check error! %s\n", __LINE__, imStrError((IM_STATUS)ret));
        return;
    }

    STATUS = imblend(srcA, dst);
}

本片完

你可能感兴趣的:(Rk开发(RK3568),c++)