Hi3531做多路图像拼接思路

前段时间研究了一下用Hi3531做多路图像拼接
主要问题是
1)多路图像拼接(有相互覆盖):HD的PIP各种限制,无法任意多画面拼接
2)视频同步:想让多个3531同步显示

对于问题(1),我找到两个办法
a)用虚拟VO
大概的思路是,使用虚拟VO,虚拟VO跟SD VO类似,多画面叠加没有太多限制,再将虚拟VO绑定到HD VO
这个是我做的实验
http://www.ebaina.com/bbs/forum.php?mod=redirect&goto=findpost&ptid=11048&pid=31257&fromuid=11974
b)用IVE
把要显示的图像通过IVE的DMA操作手动拼接成一幅大图像,再发送给HD VO

对于问题(2),实在是束手无策
用一个UDP server做时间服务器,发送广播包给两个3531,让它们SyncPts
这两个3531播放同一个RTSP live视频源,pts也一级一级保留发送给vdec->vpss->vo
但最终结果只能是大概同步,还是能明显的发现有先后差别(人眼能看到,最起码有2~3帧了吧)

接触Hi3531不久,有错误的地方,还请各位指正。
// virtual_vo_test.c

// {{{ headers

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include

include “hi_common.h”

include “hi_comm_sys.h”

include “hi_comm_vb.h”

include “hi_comm_vi.h”

include “hi_comm_vo.h”

include “hi_comm_venc.h”

include “hi_comm_vpss.h”

include “hi_comm_vdec.h”

include “hi_comm_vda.h”

include “hi_comm_region.h”

include “hi_comm_adec.h”

include “hi_comm_aenc.h”

include “hi_comm_ai.h”

include “hi_comm_ao.h”

include “hi_comm_aio.h”

include “hi_comm_hdmi.h”

include “hi_defines.h”

include “mpi_sys.h”

include “mpi_vb.h”

include “mpi_vi.h”

include “mpi_vo.h”

include “mpi_venc.h”

include “mpi_vpss.h”

include “mpi_vdec.h”

include “mpi_vda.h”

include “mpi_region.h”

include “mpi_adec.h”

include “mpi_aenc.h”

include “mpi_ai.h”

include “mpi_ao.h”

include “mpi_hdmi.h”

// }}} end of headers

define VO_DHD0 0

define VO_VIRT 10

define WIN_NUM 4

define SAMPLE_SYS_ALIGN_WIDTH 64

define SAMPLE_PIXEL_FORMAT PIXEL_FORMAT_YUV_SEMIPLANAR_420

define SAMPLE_PRT(fmt…) \

do { \
    printf("[%s]-%d: ", __FUNCTION__, __LINE__); \
    printf(fmt); \
} while(0)

ifdef __cplusplus

if __cplusplus

extern “C” {

endif

endif /* End of #ifdef __cplusplus */

typedef struct {
pthread_t pid;
HI_BOOL bRun;
} ThreadParam;

ThreadParam threadParam;

int sysInit();
int memConfig();
int startVoVirtual();
int startVo();
int bindVo();
int startVdec();
int bindVdec();
void decodeProcess();
void* decodeJpeg(void *pParam);
int stopVdec();
int unbindVdec();
int stopVirtualVo();
int stopVo();
int unbindVo();
void sysExit();

int main(int argc, char* argv[]) {/{{{/
if (HI_SUCCESS != sysInit()) {
return HI_FAILURE;
}

if (HI_SUCCESS != memConfig()) {
    return HI_FAILURE;
}

if (HI_SUCCESS != startVoVirtual()) {
    return HI_FAILURE;
}

if (HI_SUCCESS != startVo()) {
    return HI_FAILURE;
}

if (HI_SUCCESS != bindVo()) {
    return HI_FAILURE;
}

if (HI_SUCCESS != startVdec()) {
    return HI_FAILURE;
}

if (HI_SUCCESS != bindVdec()) {
    return HI_FAILURE;
}

decodeProcess();

if (HI_SUCCESS != stopVdec()) {
    return HI_FAILURE;
}

if (HI_SUCCESS != unbindVdec()) {
    return HI_FAILURE;
}

if (HI_SUCCESS != stopVirtualVo()) {
    return HI_FAILURE;
}

if (HI_SUCCESS != stopVo()) {
    return HI_FAILURE;
}

if (HI_SUCCESS != unbindVo()) {
    return HI_FAILURE;
}

sysExit();

return HI_SUCCESS;

}/}}}/

int sysInit() {/{{{/
HI_S32 s32Ret;
MPP_SYS_CONF_S stSysConf;
VB_CONF_S stVbConf;

HI_MPI_SYS_Exit();
HI_MPI_VB_Exit();

/******************************************
 * vb init
 *****************************************/
memset(&stVbConf,0,sizeof(VB_CONF_S));
stVbConf.u32MaxPoolCnt = 128;

s32Ret = HI_MPI_VB_SetConf(&stVbConf);
if (HI_SUCCESS != s32Ret) {
    SAMPLE_PRT("HI_MPI_VB_SetConf failed!\n");
    return HI_FAILURE;
}

s32Ret = HI_MPI_VB_Init();
if (HI_SUCCESS != s32Ret) {
    SAMPLE_PRT("HI_MPI_VB_Init failed!\n");
    return HI_FAILURE;
}

/******************************************
 * sys init
 *****************************************/
stSysConf.u32AlignWidth = SAMPLE_SYS_ALIGN_WIDTH;
s32Ret = HI_MPI_SYS_SetConf(&stSysConf);
if (HI_SUCCESS != s32Ret) {
    SAMPLE_PRT("HI_MPI_SYS_SetConf failed\n");
    return HI_FAILURE;
}

s32Ret = HI_MPI_SYS_Init();
if (HI_SUCCESS != s32Ret) {
    SAMPLE_PRT("HI_MPI_SYS_Init failed!\n");
    return HI_FAILURE;
}

return HI_SUCCESS;

}/}}}/

int memConfig() {/{{{/
HI_S32 s32Ret;
MPP_CHN_S stMppChn;
HI_CHAR* pcMmzName;
int i;

/******************************************
 * vdec mem config 
 *****************************************/
for (i = 0; i < WIN_NUM; i++) {
    stMppChn.enModId = HI_ID_VDEC;
    stMppChn.s32DevId = 0;
    stMppChn.s32ChnId = i;

    pcMmzName = (i%2)? "ddr1" : NULL;
    s32Ret = HI_MPI_SYS_SetMemConf(&stMppChn, pcMmzName);
    if (HI_SUCCESS != s32Ret) {
        SAMPLE_PRT("HI_MPI_SYS_SetMemConf failed!\n");
        return HI_FAILURE;
    }
}

/******************************************
 * virtual vo mem config 
 *****************************************/
stMppChn.enModId  = HI_ID_VOU;
stMppChn.s32DevId = VO_VIRT;
stMppChn.s32ChnId = 0;
s32Ret = HI_MPI_SYS_SetMemConf(&stMppChn, NULL);
if (HI_SUCCESS != s32Ret) {
    SAMPLE_PRT("HI_MPI_SYS_SetMemConf failed!\n");
    return HI_FAILURE;
}

/******************************************
 * vo mem config 
 *****************************************/
stMppChn.enModId  = HI_ID_VOU;
stMppChn.s32DevId = VO_DHD0;
stMppChn.s32ChnId = 0;
s32Ret = HI_MPI_SYS_SetMemConf(&stMppChn, NULL);
if (HI_SUCCESS != s32Ret) {
    SAMPLE_PRT("HI_MPI_SYS_SetMemConf failed!\n");
    return HI_FAILURE;
}

return HI_SUCCESS;

}/}}}/

int startVoVirtual() {/{{{/
HI_S32 s32Ret;
VO_DEV voDev = VO_VIRT;
VO_PUB_ATTR_S stVoPubAttr;
VO_VIDEO_LAYER_ATTR_S stLayerAttr;
VO_CHN_ATTR_S stChnAttr;
HI_U32 u32Width = 1920;
HI_U32 u32Height = 1080;
int i;
VO_CHN chn;

stVoPubAttr.u32BgColor = 0x000000ff;
stVoPubAttr.enIntfType = VO_INTF_BT1120;
stVoPubAttr.enIntfSync = VO_OUTPUT_1080P50;
stVoPubAttr.bDoubleFrame = HI_FALSE;
s32Ret = HI_MPI_VO_SetPubAttr(voDev, &stVoPubAttr);
if (s32Ret != HI_SUCCESS) {
    SAMPLE_PRT("HI_MPI_VO_SetPubAttr failed with 0x%#x!\n", s32Ret);
    return HI_FAILURE;
}

s32Ret = HI_MPI_VO_Enable(voDev);
if (s32Ret != HI_SUCCESS) {
    SAMPLE_PRT("HI_MPI_VO_Enable failed with 0x%#x!\n", s32Ret);
    return HI_FAILURE;
}

stLayerAttr.enPixFormat = SAMPLE_PIXEL_FORMAT;
stLayerAttr.u32DispFrmRt = 25;
stLayerAttr.stDispRect.s32X       = 0;
stLayerAttr.stDispRect.s32Y       = 0;
stLayerAttr.stDispRect.u32Width   = u32Width;
stLayerAttr.stDispRect.u32Height  = u32Height;
stLayerAttr.stImageSize.u32Width  = u32Width;
stLayerAttr.stImageSize.u32Height = u32Height;

s32Ret = HI_MPI_VO_SetVideoLayerAttr(voDev, &stLayerAttr);
if (s32Ret != HI_SUCCESS) {
    SAMPLE_PRT("HI_MPI_VO_SetVideoLayerAttr failed with 0x%#x!\n", s32Ret);
    return HI_FAILURE;
}

s32Ret = HI_MPI_VO_EnableVideoLayer(voDev);
if (s32Ret != HI_SUCCESS) {
    SAMPLE_PRT("HI_MPI_VO_EnableVideoLayer failed with 0x%#x!\n", s32Ret);
    return HI_FAILURE;
}

for (i = 0; i < WIN_NUM; i++) {
    chn = i;

    //stChnAttr.stRect.s32X       = (i % 2) * u32Width / 2;
    //stChnAttr.stRect.s32Y       = (i / 2) * u32Height / 2;
    stChnAttr.stRect.s32X       = (u32Width / 2 * i / WIN_NUM) / 2 * 2;
    stChnAttr.stRect.s32Y       = (u32Height / 2 * i / WIN_NUM) / 2 * 2;
    stChnAttr.stRect.u32Width   = u32Width / 2;
    stChnAttr.stRect.u32Height  = u32Height / 2;
    stChnAttr.u32Priority       = i;
    stChnAttr.bDeflicker        = HI_FALSE;

    s32Ret = HI_MPI_VO_SetChnAttr(voDev, chn, &stChnAttr);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VO_SetChnAttr failed with %#x!\n", s32Ret);
    }

    s32Ret = HI_MPI_VO_EnableChn(voDev, chn);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VO_EnableChn failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }
}

return HI_SUCCESS;

}/}}}/

int startVo() {/{{{/
HI_S32 s32Ret;
VO_DEV voDev = VO_DHD0;
VO_PUB_ATTR_S stVoPubAttr;
VO_VIDEO_LAYER_ATTR_S stLayerAttr;
VO_CHN_ATTR_S stChnAttr;
HI_U32 u32Width = 1920;
HI_U32 u32Height = 1080;

stVoPubAttr.u32BgColor = 0x000000ff;
stVoPubAttr.enIntfType = VO_INTF_BT1120;
stVoPubAttr.enIntfSync = VO_OUTPUT_1080P50;
stVoPubAttr.bDoubleFrame = HI_FALSE;
s32Ret = HI_MPI_VO_SetPubAttr(voDev, &stVoPubAttr);
if (s32Ret != HI_SUCCESS) {
    SAMPLE_PRT("HI_MPI_VO_SetPubAttr failed with 0x%#x!\n", s32Ret);
    return HI_FAILURE;
}

s32Ret = HI_MPI_VO_Enable(voDev);
if (s32Ret != HI_SUCCESS) {
    SAMPLE_PRT("HI_MPI_VO_Enable failed with 0x%#x!\n", s32Ret);
    return HI_FAILURE;
}

stLayerAttr.enPixFormat = SAMPLE_PIXEL_FORMAT;
stLayerAttr.u32DispFrmRt = 25;
stLayerAttr.stDispRect.s32X       = 0;
stLayerAttr.stDispRect.s32Y       = 0;
stLayerAttr.stDispRect.u32Width   = u32Width;
stLayerAttr.stDispRect.u32Height  = u32Height;
stLayerAttr.stImageSize.u32Width  = u32Width;
stLayerAttr.stImageSize.u32Height = u32Height;

s32Ret = HI_MPI_VO_SetVideoLayerAttr(voDev, &stLayerAttr);
if (s32Ret != HI_SUCCESS) {
    SAMPLE_PRT("HI_MPI_VO_SetVideoLayerAttr failed with 0x%#x!\n", s32Ret);
    return HI_FAILURE;
}

s32Ret = HI_MPI_VO_EnableVideoLayer(voDev);
if (s32Ret != HI_SUCCESS) {
    SAMPLE_PRT("HI_MPI_VO_EnableVideoLayer failed with 0x%#x!\n", s32Ret);
    return HI_FAILURE;
}

stChnAttr.stRect.s32X       = 0;
stChnAttr.stRect.s32Y       = 0;
stChnAttr.stRect.u32Width   = u32Width;
stChnAttr.stRect.u32Height  = u32Height;
stChnAttr.u32Priority       = 0;
stChnAttr.bDeflicker        = HI_FALSE;

s32Ret = HI_MPI_VO_SetChnAttr(voDev, 0, &stChnAttr);
if (s32Ret != HI_SUCCESS)
{
    SAMPLE_PRT("HI_MPI_VO_SetChnAttr failed with 0x%#x!\n", s32Ret);
}

s32Ret = HI_MPI_VO_EnableChn(voDev, 0);
if (s32Ret != HI_SUCCESS)
{
    SAMPLE_PRT("HI_MPI_VO_EnableChn failed with 0x%#x!\n", s32Ret);
    return HI_FAILURE;
}

return HI_SUCCESS;

}/}}}/

int bindVo() {/{{{/
HI_S32 s32Ret;

// virtual vo -> vo
MPP_CHN_S stSrcChn;
MPP_CHN_S stDestChn;

stSrcChn.enModId = HI_ID_VOU;
stSrcChn.s32DevId = VO_VIRT;
stSrcChn.s32ChnId = 0;

stDestChn.enModId = HI_ID_VOU;
stDestChn.s32DevId = VO_DHD0;
stDestChn.s32ChnId = 0;

s32Ret = HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);
if (s32Ret != HI_SUCCESS) {
    SAMPLE_PRT("HI_MPI_SYS_Bind failed with 0x%#x!\n", s32Ret);
    return HI_FAILURE;
}

return HI_SUCCESS;

}/}}}/

int startVdec() {/{{{/
VDEC_CHN_ATTR_S stAttr;
VDEC_PRTCL_PARAM_S stPrtclParam;
HI_S32 s32Ret;
HI_U32 u32Width = 1920;
HI_U32 u32Height = 1080;
HI_S32 s32ChnID = 0;
int i;

memset(&stAttr, 0, sizeof(VDEC_CHN_ATTR_S));

stAttr.enType = PT_JPEG;
stAttr.u32BufSize = u32Width * u32Height;
stAttr.u32Priority = 1;//此处必须大于0
stAttr.u32PicWidth = u32Width;
stAttr.u32PicHeight = u32Height;
stAttr.stVdecJpegAttr.enMode = VIDEO_MODE_FRAME;

for (i = 0; i < WIN_NUM; i++) {
    s32ChnID = i;

    s32Ret = HI_MPI_VDEC_CreateChn(s32ChnID, &stAttr);
    if (HI_SUCCESS != s32Ret) {
        SAMPLE_PRT("HI_MPI_VDEC_CreateChn failed with 0x%#x \n", s32Ret);
        return s32Ret;
    }

    s32Ret = HI_MPI_VDEC_GetPrtclParam(s32ChnID, &stPrtclParam);
    if (HI_SUCCESS != s32Ret) {
        SAMPLE_PRT("HI_MPI_VDEC_GetPrtclParam failed errno 0x%#x \n", s32Ret);
        return s32Ret;
    }

    stPrtclParam.s32MaxSpsNum = 21;
    stPrtclParam.s32MaxPpsNum = 22;
    stPrtclParam.s32MaxSliceNum = 100;
    s32Ret = HI_MPI_VDEC_SetPrtclParam(s32ChnID, &stPrtclParam);
    if (HI_SUCCESS != s32Ret) {
        SAMPLE_PRT("HI_MPI_VDEC_SetPrtclParam failed errno 0x%#x \n", s32Ret);
        return s32Ret;
    }

    s32Ret = HI_MPI_VDEC_StartRecvStream(s32ChnID);
    if (HI_SUCCESS != s32Ret) {
        SAMPLE_PRT("HI_MPI_VDEC_StartRecvStream failed errno 0x%#x \n", s32Ret);
        return s32Ret;
    }
}

return HI_SUCCESS;

}/}}}/

int bindVdec() {/{{{/
HI_S32 s32Ret;
int i;

// vdec -> virtual vo
MPP_CHN_S stSrcChn;
MPP_CHN_S stDestChn;

for (i = 0; i < WIN_NUM; i++) {
    stSrcChn.enModId = HI_ID_VDEC;
    stSrcChn.s32DevId = 0;
    stSrcChn.s32ChnId = i;

    stDestChn.enModId = HI_ID_VOU;
    stDestChn.s32DevId = VO_VIRT;
    stDestChn.s32ChnId = i;

    s32Ret = HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);
    if (s32Ret != HI_SUCCESS) {
        SAMPLE_PRT("HI_MPI_SYS_Bind failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }
}

return HI_SUCCESS;

}/}}}/

void decodeProcess() {/{{{/
threadParam.bRun = HI_FALSE;

// create thread
pthread_create(&threadParam.pid, NULL, decodeJpeg, &threadParam);

// join thread
pthread_join(threadParam.pid, NULL);

printf("press two enter to quit!\n");
getchar();
getchar();

}/}}}/

void* decodeJpeg(void pParam) {/{{{*/
//ThreadParam* pThreadParam = (ThreadParam*)pParam;
FILE* fp = NULL;
char szFile[] = “test.jpg”;
VDEC_STREAM_S stStream;
HI_U8 buf[1920*1080*2];
int readLen;
HI_S32 s32Ret;
int i;

fp = fopen(szFile, "rb");
if (NULL == fp) {
    SAMPLE_PRT("can't open file %s\n", szFile);
    return (void*)(HI_FAILURE);
}

readLen = fread(buf, 1, sizeof(buf), fp);
fclose(fp);

if (readLen <= 0) {
    SAMPLE_PRT("can't read file %s\n", szFile);
}

stStream.u64PTS  = 0;
stStream.pu8Addr = buf;
stStream.u32Len  = readLen;

for (i = 0; i < WIN_NUM; i++) {
    s32Ret = HI_MPI_VDEC_SendStream(i, &stStream, HI_IO_BLOCK);
    if (s32Ret != HI_SUCCESS) {
        SAMPLE_PRT("HI_MPI_VDEC_SendStream failed with %#x!\n", s32Ret);
        return (void*)(HI_FAILURE);
    }
}

    fflush(stdout);

return (void*)(HI_SUCCESS);

}/}}}/

int stopVdec() {/{{{/
HI_S32 s32Ret;
HI_S32 s32ChnID = 0;
int i;

for (i = 0; i < WIN_NUM; i++) {
    s32ChnID = i;
    s32Ret = HI_MPI_VDEC_StopRecvStream(s32ChnID);
    if (s32Ret != HI_SUCCESS) {
        SAMPLE_PRT("HI_MPI_VDEC_StopRecvStream failed errno 0x%x\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VDEC_DestroyChn(s32ChnID);
    if (HI_SUCCESS != s32Ret) {
        SAMPLE_PRT("HI_MPI_VDEC_DestroyChn failed errno 0x%x \n", s32Ret);
        return HI_FAILURE;
    }
}

return HI_SUCCESS;

}/}}}/

int unbindVdec() {/{{{/
HI_S32 s32Ret;
int i;

// vdec -> virtual vo
MPP_CHN_S stSrcChn;
MPP_CHN_S stDestChn;

for (i = 0; i < WIN_NUM; i++) {
    stSrcChn.enModId = HI_ID_VDEC;
    stSrcChn.s32DevId = 0;
    stSrcChn.s32ChnId = i;

    stDestChn.enModId = HI_ID_VOU;
    stDestChn.s32DevId = VO_VIRT;
    stDestChn.s32ChnId = i;

    s32Ret = HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn);
    if (s32Ret != HI_SUCCESS) {
        SAMPLE_PRT("HI_MPI_SYS_UnBind failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }
}

return HI_SUCCESS;

}/}}}/

int stopVirtualVo() {/{{{/
HI_S32 s32Ret;
int i;

for (i = 0; i < WIN_NUM; i++) {
    s32Ret = HI_MPI_VO_DisableChn(VO_VIRT, i);
    if (s32Ret != HI_SUCCESS) {
        SAMPLE_PRT("HI_MPI_VO_DisableChn failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }
}

return HI_SUCCESS;

}/}}}/

int stopVo() {/{{{/
HI_S32 s32Ret;

s32Ret = HI_MPI_VO_DisableChn(VO_DHD0, 0);
if (s32Ret != HI_SUCCESS) {
    SAMPLE_PRT("HI_MPI_VO_DisableChn failed with %#x!\n", s32Ret);
    return HI_FAILURE;
}

return HI_SUCCESS;

}/}}}/

int unbindVo() {/{{{/
HI_S32 s32Ret;
VO_DEV voDev = VO_VIRT;

// virtual vo -> vo
MPP_CHN_S stSrcChn;
MPP_CHN_S stDestChn;

stSrcChn.enModId = HI_ID_VOU;
stSrcChn.s32DevId = VO_VIRT;
stSrcChn.s32ChnId = 0;

stDestChn.enModId = HI_ID_VOU;
stDestChn.s32DevId = VO_DHD0;
stDestChn.s32ChnId = 0;

s32Ret = HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn);
if (s32Ret != HI_SUCCESS) {
    SAMPLE_PRT("HI_MPI_SYS_UnBind failed with 0x%#x!\n", s32Ret);
    return HI_FAILURE;
}

return HI_SUCCESS;

}/}}}/

void sysExit() {/{{{/
HI_MPI_SYS_Exit();
HI_MPI_VB_Exit();
return;
}/}}}/

ifdef __cplusplus

if __cplusplus

}

endif

endif /* End of #ifdef __cplusplus */

// vim:set ts=4 sw=4 et fenc=utf-8 fdm=marker:

猜你喜欢

转载自blog.csdn.net/icone007/article/details/81735921