2374 lines
92 KiB
C
Executable File
2374 lines
92 KiB
C
Executable File
/******************************************************************************
|
|
Copyright (C), 2001-2016, Allwinner Tech. Co., Ltd.
|
|
******************************************************************************
|
|
File Name : VIPPDrawOsd_V5.c
|
|
Version : Initial Draft
|
|
Author : Allwinner BU3-PD2 Team
|
|
Created : 2017/07/31
|
|
Last Modified :
|
|
Description : V5 VIPP OSD chip design has some problems: overlay can't support
|
|
overlap, and cover will on top of overlay. But app can't obey this rule,
|
|
app wants cover below overlay, and overlay maybe overlap.
|
|
So we have to develop this function to regroup osd region that user set,
|
|
to guarantee overlays after regroup are not overlap.
|
|
Function List :
|
|
History :
|
|
******************************************************************************/
|
|
|
|
//#define LOG_NDEBUG 0
|
|
#define LOG_TAG "VIPPDrawOsd_V5"
|
|
#include <utils/plat_log.h>
|
|
|
|
#include <errno.h>
|
|
#include <memory.h>
|
|
#include <pthread.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/prctl.h>
|
|
|
|
#include <mpi_videoformat_conversion.h>
|
|
#include <ChannelRegionInfo.h>
|
|
#include <mm_comm_vi.h>
|
|
#include <videoInputHw.h>
|
|
#include <isp_dev.h>
|
|
#include <OsdGroups.h>
|
|
#include "VIPPDrawOSD_V5.h"
|
|
|
|
#include <cdx_list.h>
|
|
|
|
#define MAX_GLOBAL_ALPHA (16)
|
|
//ref to vipp_reg.h
|
|
#define MAX_OVERLAY_NUM 64
|
|
#define MAX_COVER_NUM 8
|
|
|
|
#define IF_MALLOC_FAIL(ptr) \
|
|
if(NULL == ptr) \
|
|
{ \
|
|
aloge("fatal error! malloc fail!"); \
|
|
return ERR_VI_NOMEM; \
|
|
}
|
|
|
|
extern VIDevManager *gpVIDevManager;
|
|
|
|
|
|
|
|
/**
|
|
* @param nPixelFormat V4L2_PIX_FMT_RGB32
|
|
*/
|
|
int calcBitmapSize(int nPixelFormat, RECT_S *pRect)
|
|
{
|
|
int size = 0;
|
|
switch(nPixelFormat)
|
|
{
|
|
case V4L2_PIX_FMT_RGB32:
|
|
size = pRect->Width*pRect->Height*4;
|
|
break;
|
|
case V4L2_PIX_FMT_RGB555:
|
|
size = pRect->Width*pRect->Height*2;
|
|
break;
|
|
default:
|
|
aloge("fatal error! unsupport pixel format[0x%x]?", nPixelFormat);
|
|
break;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
/**
|
|
* @param eV4L2PixFmt : V4L2_PIX_FMT_RGB32 or V4L2_PIX_FMT_RGB555.
|
|
*/
|
|
static ERRORTYPE mallocBmpBufForOsdRegion(OsdRegion *pRegion, int eV4L2PixFmt)
|
|
{
|
|
int nSize;
|
|
if(pRegion->mType != OVERLAY_RGN)
|
|
{
|
|
aloge("fatal error! rgnType[0x%x] is wrong!", pRegion->mType);
|
|
return ERR_VI_INVALID_PARA;
|
|
}
|
|
nSize = calcBitmapSize(eV4L2PixFmt, &pRegion->mRect);
|
|
if(nSize > 0)
|
|
{
|
|
pRegion->mInfo.mOverlay.mBitmap = malloc(nSize);
|
|
if(NULL == pRegion->mInfo.mOverlay.mBitmap)
|
|
{
|
|
aloge("fatal error! malloc [%d]bytes fail", nSize);
|
|
return ERR_VI_NOMEM;
|
|
}
|
|
memset(pRegion->mInfo.mOverlay.mBitmap, 0xFF, nSize);
|
|
return SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! rgn size[%dx%d]", pRegion->mRect.Width, pRegion->mRect.Height);
|
|
return ERR_VI_INVALID_PARA;
|
|
}
|
|
}
|
|
|
|
OsdGroup* OsdGroupConstruct()
|
|
{
|
|
OsdGroup *pGroup = (OsdGroup*)malloc(sizeof(OsdGroup));
|
|
if(pGroup)
|
|
{
|
|
memset(pGroup, 0, sizeof(OsdGroup));
|
|
INIT_LIST_HEAD(&pGroup->mOsdList);
|
|
INIT_LIST_HEAD(&pGroup->mRedrawOsdList);
|
|
INIT_LIST_HEAD(&pGroup->mList);
|
|
}
|
|
return pGroup;
|
|
}
|
|
|
|
void OsdGroupDestruct(OsdGroup *pGroup)
|
|
{
|
|
if(!list_empty(&pGroup->mOsdList))
|
|
{
|
|
OsdRegion *pRegionEntry, *pRegionTmp;
|
|
list_for_each_entry_safe(pRegionEntry, pRegionTmp, &pGroup->mOsdList, mList)
|
|
{
|
|
list_del(&pRegionEntry->mList);
|
|
free(pRegionEntry);
|
|
}
|
|
}
|
|
if(!list_empty(&pGroup->mRedrawOsdList))
|
|
{
|
|
OsdRegion *pRegionEntry, *pRegionTmp;
|
|
list_for_each_entry_safe(pRegionEntry, pRegionTmp, &pGroup->mRedrawOsdList, mList)
|
|
{
|
|
list_del(&pRegionEntry->mList);
|
|
if(OVERLAY_RGN == pRegionEntry->mType)
|
|
{
|
|
if(pRegionEntry->mInfo.mOverlay.mBitmap)
|
|
{
|
|
free(pRegionEntry->mInfo.mOverlay.mBitmap);
|
|
pRegionEntry->mInfo.mOverlay.mBitmap = NULL;
|
|
}
|
|
}
|
|
free(pRegionEntry);
|
|
}
|
|
}
|
|
free(pGroup);
|
|
}
|
|
|
|
OsdGroups* OsdGroupsConstruct()
|
|
{
|
|
OsdGroups *pGroups = (OsdGroups*)malloc(sizeof(OsdGroups));
|
|
if(NULL == pGroups)
|
|
{
|
|
aloge("fatal error! malloc fail!");
|
|
return NULL;
|
|
}
|
|
memset(pGroups, 0, sizeof(OsdGroups));
|
|
INIT_LIST_HEAD(&pGroups->mGroupList);
|
|
return pGroups;
|
|
}
|
|
|
|
void OsdGroupsDestruct(OsdGroups* pThiz)
|
|
{
|
|
OsdGroup *pGroupEntry, *pGroupTmp;
|
|
if(!list_empty(&pThiz->mGroupList))
|
|
{
|
|
list_for_each_entry_safe(pGroupEntry, pGroupTmp, &pThiz->mGroupList, mList)
|
|
{
|
|
list_del(&pGroupEntry->mList);
|
|
OsdGroupDestruct(pGroupEntry);
|
|
}
|
|
}
|
|
free(pThiz);
|
|
}
|
|
|
|
typedef enum
|
|
{
|
|
OsdOverlap_None = 0x00,
|
|
OsdOverlap_OnlyOverlay = 0x01,
|
|
OsdOverlap_OnlyCover = 0x02,
|
|
OsdOverlap_CoverOverlay = 0x03,
|
|
}OsdOverlapType;
|
|
typedef enum
|
|
{
|
|
OsdOverlapArea_None = 0x00,
|
|
OsdOverlapArea_Part = 0x01,
|
|
OsdOverlapArea_WholeInvolve = 0x02, //involve other entirely
|
|
OsdOverlapArea_WholeInvolved = 0x03, //be involved by other entirely.
|
|
}OsdOverlapAreaType;
|
|
|
|
/**
|
|
* @return int : -1: priority first < second, 0: first==second, 1:priority first > second
|
|
*/
|
|
static int compareOsdRegionPriority(const OsdRegion *pFirst, const OsdRegion *pSecond)
|
|
{
|
|
int ret = 0;
|
|
if(pFirst->mType != pSecond->mType)
|
|
{
|
|
if(OVERLAY_RGN ==pFirst->mType && COVER_RGN == pSecond->mType)
|
|
{
|
|
return 1;
|
|
}
|
|
else if(COVER_RGN ==pFirst->mType && OVERLAY_RGN == pSecond->mType)
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! unsupport rgnType[0x%x][0x%x]", pFirst->mType, pSecond->mType);
|
|
return 0;
|
|
}
|
|
}
|
|
if(OVERLAY_RGN == pFirst->mType)
|
|
{
|
|
ret = pFirst->mInfo.mOverlay.mPriority - pSecond->mInfo.mOverlay.mPriority;
|
|
if(ret < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
else if(0 == ret)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
else if(COVER_RGN == pFirst->mType)
|
|
{
|
|
ret = pFirst->mInfo.mCover.mPriority - pSecond->mInfo.mCover.mPriority;
|
|
if(ret < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
else if(0 == ret)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! unsupport rgnType[0x%x]", pFirst->mType);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* priority sequence: low -> high.
|
|
* struct list_head *pRegionList : OsdRegion
|
|
*/
|
|
ERRORTYPE ResortOsdRegionByPriority(struct list_head *pRegionList)
|
|
{
|
|
OsdRegion *pEntry, *pTmp;
|
|
pEntry = list_first_entry_or_null(pRegionList, OsdRegion, mList);
|
|
if(NULL == pEntry)
|
|
{
|
|
return SUCCESS;
|
|
}
|
|
int nPrioRet;
|
|
int nPrioRet2;
|
|
OsdRegion *pPrevEntry;
|
|
list_for_each_entry_safe_continue(pEntry, pTmp, pRegionList, mList)
|
|
{
|
|
pPrevEntry = list_prev_entry(pEntry, mList);
|
|
nPrioRet = compareOsdRegionPriority(pPrevEntry, pEntry);
|
|
if(nPrioRet > 0)
|
|
{
|
|
list_del(&pEntry->mList);
|
|
BOOL bInsert = FALSE;
|
|
list_for_each_entry_continue_reverse(pPrevEntry, pRegionList, mList)
|
|
{
|
|
nPrioRet2 = compareOsdRegionPriority(pPrevEntry, pEntry);
|
|
if(nPrioRet2 <= 0)
|
|
{
|
|
list_add(&pEntry->mList, &pPrevEntry->mList);
|
|
bInsert = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if(FALSE == bInsert)
|
|
{
|
|
list_add(&pEntry->mList, pRegionList);
|
|
}
|
|
}
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* elem type: OsdRegion
|
|
*/
|
|
static ERRORTYPE ShallowCopyOsdRegionList(struct list_head *pDstHead, struct list_head *pSrcHead)
|
|
{
|
|
if(!list_empty(pDstHead))
|
|
{
|
|
aloge("fatal error! dst list is not empty!");
|
|
}
|
|
OsdRegion *pNewEntry;
|
|
OsdRegion *pSrcEntry;
|
|
list_for_each_entry(pSrcEntry, pSrcHead, mList)
|
|
{
|
|
pNewEntry = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
if(NULL == pNewEntry)
|
|
{
|
|
aloge("fatal error! malloc fail!");
|
|
}
|
|
memcpy(pNewEntry, pSrcEntry, sizeof(OsdRegion));
|
|
list_add_tail(&pNewEntry->mList, pDstHead);
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
BOOL IfPointBelongToRect(POINT_S *pPt, RECT_S *pRect, /*out*/POINT_S *pRelativePos)
|
|
{
|
|
BOOL bBelong;
|
|
if(pPt->X >= pRect->X && pPt->X < pRect->X + pRect->Width && pPt->Y >= pRect->Y && pPt->Y < pRect->Y + pRect->Height)
|
|
{
|
|
bBelong = TRUE;
|
|
if(pRelativePos != NULL)
|
|
{
|
|
pRelativePos->X = pPt->X - pRect->X;
|
|
pRelativePos->Y = pPt->Y - pRect->Y;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bBelong = FALSE;
|
|
}
|
|
return bBelong;
|
|
}
|
|
/**
|
|
* bit31 ~ bit 0
|
|
* A R G B
|
|
*/
|
|
static unsigned short convertRGB32ToRGB1555(unsigned int nRGB32)
|
|
{
|
|
unsigned short nRGB1555 = 0;
|
|
unsigned int alpha = nRGB32 >> 24;
|
|
unsigned int nR = nRGB32 >> 16 & 0xFF;
|
|
unsigned int nG = nRGB32 >> 8 & 0xFF;
|
|
unsigned int nB = nRGB32 & 0xFF;
|
|
if(alpha >= 128)
|
|
{
|
|
nRGB1555 |= 0x8000;
|
|
}
|
|
nRGB1555 |= (nR*31/255 & 0x1F)<<10 | (nG*31/255 & 0x1F)<<5 | (nB*31/255 & 0x1F);
|
|
return nRGB1555;
|
|
}
|
|
|
|
/**
|
|
* origin list is sort by priority: low->high, OsdRegion, cover's priority must smaller than overlay.
|
|
* cover must take effect. overlay can get highest one to take effect.
|
|
* @param eV4L2PixFmt : V4L2_PIX_FMT_RGB32 or V4L2_PIX_FMT_RGB555.
|
|
*/
|
|
ERRORTYPE DrawRegionByOriginRegions(OsdRegion *pDstRegion, struct list_head *pOriginList, int eV4L2PixFmt)
|
|
{
|
|
if(pDstRegion->mType != OVERLAY_RGN)
|
|
{
|
|
aloge("fatal error! rgnType[0x%x] is wrong", pDstRegion->mType);
|
|
return ERR_VI_INVALID_PARA;
|
|
}
|
|
BOOL bCoverExist = FALSE;
|
|
OsdRegion *pRegionEntry;
|
|
list_for_each_entry(pRegionEntry, pOriginList, mList)
|
|
{
|
|
if(COVER_RGN == pRegionEntry->mType)
|
|
{
|
|
bCoverExist = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
//tranverse every point from left to right, from top to bottom.
|
|
unsigned int *pPtRgb32;
|
|
unsigned short *pPtRgb1555;
|
|
int nLineIndex = 0;
|
|
int nColumnIndex = 0;
|
|
for(nLineIndex = 0; nLineIndex < pDstRegion->mRect.Height; nLineIndex++)
|
|
{
|
|
for(nColumnIndex = 0; nColumnIndex < pDstRegion->mRect.Width; nColumnIndex++)
|
|
{
|
|
POINT_S pt = {pDstRegion->mRect.X + nColumnIndex, pDstRegion->mRect.Y + nLineIndex};
|
|
//decide address
|
|
switch(eV4L2PixFmt)
|
|
{
|
|
case V4L2_PIX_FMT_RGB32:
|
|
pPtRgb32 = (unsigned int*)pDstRegion->mInfo.mOverlay.mBitmap + pDstRegion->mRect.Width*nLineIndex + nColumnIndex;
|
|
break;
|
|
case V4L2_PIX_FMT_RGB555:
|
|
pPtRgb1555 = (unsigned short*)pDstRegion->mInfo.mOverlay.mBitmap + pDstRegion->mRect.Width*nLineIndex + nColumnIndex;
|
|
break;
|
|
default:
|
|
aloge("fatal error!");
|
|
break;
|
|
}
|
|
BOOL bFillDone = FALSE; //this point is filled by one region.
|
|
OsdRegion *pRegionEntry;
|
|
list_for_each_entry_reverse(pRegionEntry, pOriginList, mList)
|
|
{
|
|
if(OVERLAY_RGN == pRegionEntry->mType)
|
|
{
|
|
if(bFillDone)
|
|
{
|
|
continue;
|
|
}
|
|
POINT_S RelativePos;
|
|
if(IfPointBelongToRect(&pt, &pRegionEntry->mRect, &RelativePos))
|
|
{
|
|
switch(eV4L2PixFmt)
|
|
{
|
|
case V4L2_PIX_FMT_RGB32:
|
|
*pPtRgb32 = *((unsigned int*)pRegionEntry->mInfo.mOverlay.mBitmap + pRegionEntry->mRect.Width*RelativePos.Y + RelativePos.X);
|
|
break;
|
|
case V4L2_PIX_FMT_RGB555:
|
|
*pPtRgb1555 = *((unsigned short*)pRegionEntry->mInfo.mOverlay.mBitmap + pRegionEntry->mRect.Width*RelativePos.Y + RelativePos.X);
|
|
break;
|
|
default:
|
|
aloge("fatal error!");
|
|
break;
|
|
}
|
|
bFillDone = TRUE;
|
|
if(bCoverExist)
|
|
{
|
|
//need continue to detect.
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
//if cover is not exist, then we can break.
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
else if(COVER_RGN == pRegionEntry->mType)
|
|
{
|
|
if(IfPointBelongToRect(&pt, &pRegionEntry->mRect, NULL))
|
|
{
|
|
if(bFillDone)
|
|
{
|
|
//this point alpha must be 0xFF.
|
|
switch(eV4L2PixFmt)
|
|
{
|
|
case V4L2_PIX_FMT_RGB32:
|
|
*pPtRgb32 |= 0xFF000000;
|
|
break;
|
|
case V4L2_PIX_FMT_RGB555:
|
|
*pPtRgb1555 |= 0x8000;
|
|
break;
|
|
default:
|
|
aloge("fatal error!");
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//if cover is high priority at this poirt, use cover color.
|
|
switch(eV4L2PixFmt)
|
|
{
|
|
case V4L2_PIX_FMT_RGB32:
|
|
*pPtRgb32 = pRegionEntry->mInfo.mCover.mChromaKey | 0xFF000000;
|
|
break;
|
|
case V4L2_PIX_FMT_RGB555:
|
|
*pPtRgb1555 = convertRGB32ToRGB1555(pRegionEntry->mInfo.mCover.mChromaKey | 0xFF000000);
|
|
break;
|
|
default:
|
|
aloge("fatal error!");
|
|
break;
|
|
}
|
|
bFillDone = TRUE;
|
|
}
|
|
//now we can break.
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error!");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* pt1 pt2
|
|
* ------------
|
|
* | |
|
|
* |----------|
|
|
* pt3 pt4
|
|
* probe dstRect's points which in srcRect. result is stored in PointsArray.
|
|
*/
|
|
typedef enum
|
|
{
|
|
PointPos_LeftTop = 0,
|
|
PointPos_RightTop = 1,
|
|
PointPos_LeftBottom = 2,
|
|
PointPos_RightBottom = 3,
|
|
}PointPositionType;
|
|
typedef struct
|
|
{
|
|
int mNum;
|
|
POINT_S mPtArray[4];
|
|
PointPositionType mPointIndexArray[4]; //store point index, start from PointPos_LeftTop, to PointPos_RightBottom.
|
|
}PointsArray;
|
|
/**
|
|
* probe how many points of dstRect are in srcRect.
|
|
*/
|
|
void ProbePointsInRect(const RECT_S *pDst, const RECT_S *pSrc, PointsArray *pPoints)
|
|
{
|
|
memset(pPoints, 0, sizeof(PointsArray));
|
|
POINT_S ptDst[4] =
|
|
{
|
|
{pDst->X, pDst->Y},
|
|
{pDst->X+pDst->Width-1, pDst->Y},
|
|
{pDst->X, pDst->Y+pDst->Height-1},
|
|
{pDst->X+pDst->Width-1, pDst->Y+pDst->Height-1}
|
|
};
|
|
POINT_S ptSrc[4] =
|
|
{
|
|
{pSrc->X, pSrc->Y},
|
|
{pSrc->X+pSrc->Width-1, pSrc->Y},
|
|
{pSrc->X, pSrc->Y+pSrc->Height-1},
|
|
{pSrc->X+pSrc->Width-1, pSrc->Y+pSrc->Height-1}
|
|
};
|
|
int i;
|
|
for(i=0; i<4; i++)
|
|
{
|
|
if(ptDst[i].X >= ptSrc[PointPos_LeftTop].X && ptDst[i].X <= ptSrc[PointPos_RightBottom].X
|
|
&& ptDst[i].Y >= ptSrc[PointPos_LeftTop].Y && ptDst[i].Y <= ptSrc[PointPos_RightBottom].Y)
|
|
{
|
|
pPoints->mPtArray[pPoints->mNum].X = ptDst[i].X;
|
|
pPoints->mPtArray[pPoints->mNum].Y = ptDst[i].Y;
|
|
pPoints->mPointIndexArray[pPoints->mNum] = i;
|
|
pPoints->mNum++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function only process two cases:
|
|
* (1) cut to half
|
|
* _______
|
|
| ____|____
|
|
rect | |_______| region
|
|
|______|
|
|
* (2) base one point to cut.
|
|
________
|
|
| _____|___
|
|
rect | | | |
|
|
|__|____| | region
|
|
* |_______|
|
|
*
|
|
* (3)cut to more
|
|
* _______
|
|
| ____|____
|
|
region| |_______| rect
|
|
|______|
|
|
|
|
* (4) cross overlap
|
|
* _________
|
|
* ____|_______|___
|
|
* | | | |
|
|
* |___|_______|__|
|
|
* |_______|
|
|
*
|
|
* (5)involve
|
|
* _________
|
|
* | |
|
|
* | _ |
|
|
* | |_| |
|
|
* | |
|
|
* |_______|
|
|
*
|
|
* other cases is impossible to come here! involve relation is processed before, if meet here, fatal error!
|
|
*/
|
|
ERRORTYPE CutRegionByRect(const OsdRegion *pRegion, const RECT_S *pRect, struct list_head *pDividedList)
|
|
{
|
|
ERRORTYPE ret = SUCCESS;
|
|
if(!list_empty(pDividedList))
|
|
{
|
|
aloge("fatal error! why divided list is not empty?");
|
|
return ERR_VI_INVALID_PARA;
|
|
}
|
|
PointsArray stRectPoints;
|
|
ProbePointsInRect(pRect, &pRegion->mRect, &stRectPoints);
|
|
PointsArray stRegionPoints;
|
|
ProbePointsInRect(&pRegion->mRect, pRect, &stRegionPoints);
|
|
if((0 == stRectPoints.mNum && 2 == stRegionPoints.mNum) || (1 == stRectPoints.mNum && 2 == stRegionPoints.mNum) || (2 == stRectPoints.mNum && 2 == stRegionPoints.mNum))
|
|
{
|
|
//case (1), cut region half.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
//there are 4 cases in cut_region_half: top, bottom ,left, right.
|
|
if(PointPos_LeftBottom == stRegionPoints.mPointIndexArray[0] && PointPos_RightBottom == stRegionPoints.mPointIndexArray[1])
|
|
{
|
|
//case (1.1): region is on top of rect.
|
|
if(pRect->Y <= pRegion->mRect.Y)
|
|
{
|
|
aloge("fatal error! check rect [%d,%d, %dx%d],[%d,%d, %dx%d]",
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height,
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height);
|
|
}
|
|
pDivideRegion->mRect.Height = pRect->Y - pRegion->mRect.Y;
|
|
}
|
|
else if(PointPos_LeftTop == stRegionPoints.mPointIndexArray[0] && PointPos_RightTop == stRegionPoints.mPointIndexArray[1])
|
|
{
|
|
//case (1.2): region is under bottom of rect.
|
|
if(pRect->Y + pRect->Height <= pRegion->mRect.Y || pRect->Y + pRect->Height >= pRegion->mRect.Y + pRegion->mRect.Height)
|
|
{
|
|
aloge("fatal error! check rect [%d,%d, %dx%d],[%d,%d, %dx%d]",
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height,
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height);
|
|
}
|
|
pDivideRegion->mRect.Y = pRect->Y + pRect->Height;
|
|
pDivideRegion->mRect.Height = (pRegion->mRect.Y + pRegion->mRect.Height) - (pRect->Y + pRect->Height);
|
|
}
|
|
else if(PointPos_RightTop == stRegionPoints.mPointIndexArray[0] && PointPos_RightBottom == stRegionPoints.mPointIndexArray[1])
|
|
{
|
|
//case (1.3): region is at left of rect.
|
|
if(pRect->X <= pRegion->mRect.X)
|
|
{
|
|
aloge("fatal error! check rect [%d,%d, %dx%d],[%d,%d, %dx%d]",
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height,
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height);
|
|
}
|
|
pDivideRegion->mRect.Width = pRect->X - pRegion->mRect.X;
|
|
}
|
|
else if(PointPos_LeftTop == stRegionPoints.mPointIndexArray[0] && PointPos_LeftBottom == stRegionPoints.mPointIndexArray[1])
|
|
{
|
|
//case (1.4): region is at right of rect.
|
|
if(pRect->X + pRect->Width <= pRegion->mRect.X || pRect->X + pRect->Width >= pRegion->mRect.X + pRegion->mRect.Width)
|
|
{
|
|
aloge("fatal error! check rect [%d,%d, %dx%d],[%d,%d, %dx%d]",
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height,
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height);
|
|
}
|
|
pDivideRegion->mRect.X = pRect->X + pRect->Width;
|
|
pDivideRegion->mRect.Width = (pRegion->mRect.X + pRegion->mRect.Width) - (pRect->X + pRect->Width);
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! check rect [%d,%d, %dx%d],[%d,%d, %dx%d]",
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height,
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height);
|
|
}
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
return ret;
|
|
}
|
|
else if(1 == stRectPoints.mNum && 1 == stRegionPoints.mNum)
|
|
{
|
|
//case (2), base one point to cut
|
|
//there are 4 cases in base_one_point_cut: leftTop , rightTop , leftBottom, rightBottom.
|
|
BOOL bError = FALSE;
|
|
if(PointPos_LeftTop == stRectPoints.mPointIndexArray[0])
|
|
{
|
|
POINT_S PtLeftTop = stRectPoints.mPtArray[0];
|
|
if(!(PtLeftTop.X == pRect->X && PtLeftTop.Y == pRect->Y))
|
|
{
|
|
aloge("fatal error! point error [%d,%d]!=[%d,%d]", PtLeftTop.X, PtLeftTop.Y, pRect->X, pRect->Y);
|
|
}
|
|
//case (2.1) point is leftTop in Region
|
|
if(PtLeftTop.Y == pRegion->mRect.Y)
|
|
{
|
|
if(PtLeftTop.X > pRegion->mRect.X)
|
|
{
|
|
//cut one region is enough.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Width = PtLeftTop.X - pRegion->mRect.X;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! X");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else if(PtLeftTop.Y > pRegion->mRect.Y)
|
|
{
|
|
if(PtLeftTop.Y < pRegion->mRect.Y + pRegion->mRect.Height)
|
|
{
|
|
if(PtLeftTop.X == pRegion->mRect.X)
|
|
{
|
|
//cut one region is enough.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Height = PtLeftTop.Y - pRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else if(PtLeftTop.X > pRegion->mRect.X)
|
|
{
|
|
//cut two region.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Height = PtLeftTop.Y - pRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
|
|
pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = PtLeftTop.Y;
|
|
pDivideRegion->mRect.Width = PtLeftTop.X - pRegion->mRect.X;
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y + pRegion->mRect.Height - PtLeftTop.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! X");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! Height");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! Y");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else if(PointPos_RightTop == stRectPoints.mPointIndexArray[0])
|
|
{
|
|
//case (2.2) point is rightTop in Region
|
|
POINT_S PtRightTop = stRectPoints.mPtArray[0];
|
|
if(!(PtRightTop.X == pRect->X+pRect->Width-1 && PtRightTop.Y == pRect->Y))
|
|
{
|
|
aloge("fatal error! point error [%d,%d]!=[%d,%d, %dx%d]", PtRightTop.X, PtRightTop.Y, pRect->X, pRect->Y, pRect->Width, pRect->Height);
|
|
}
|
|
if(PtRightTop.Y == pRegion->mRect.Y)
|
|
{
|
|
if(PtRightTop.X >= pRegion->mRect.X + pRegion->mRect.Width - 1)
|
|
{
|
|
aloge("fatal error! X");
|
|
bError = TRUE;
|
|
}
|
|
//cut one region is enough.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.X = PtRightTop.X+1;
|
|
pDivideRegion->mRect.Width = pRegion->mRect.X + pRegion->mRect.Width - (PtRightTop.X + 1);
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else if(PtRightTop.Y > pRegion->mRect.Y)
|
|
{
|
|
if(PtRightTop.Y >= pRegion->mRect.Y + pRegion->mRect.Height)
|
|
{
|
|
aloge("fatal error! Height");
|
|
bError = TRUE;
|
|
}
|
|
if(PtRightTop.X == pRegion->mRect.X + pRegion->mRect.Width - 1)
|
|
{
|
|
//cut one region is enough.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Height = PtRightTop.Y - pRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else if(PtRightTop.X < pRegion->mRect.X + pRegion->mRect.Width - 1)
|
|
{
|
|
//cut two region.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Height = PtRightTop.Y - pRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
|
|
pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.X = PtRightTop.X+1;
|
|
pDivideRegion->mRect.Y = PtRightTop.Y;
|
|
pDivideRegion->mRect.Width = pRegion->mRect.X + pRegion->mRect.Width - (PtRightTop.X + 1);
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y + pRegion->mRect.Height - PtRightTop.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! X");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! Y");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else if(PointPos_LeftBottom == stRectPoints.mPointIndexArray[0])
|
|
{
|
|
//case (2.3) point is leftBottom in Region
|
|
POINT_S PtLeftBottom = stRectPoints.mPtArray[0];
|
|
if(!(PtLeftBottom.X == pRect->X && PtLeftBottom.Y == pRect->Y + pRect->Height - 1))
|
|
{
|
|
aloge("fatal error! point error [%d,%d]!=[%d,%d, %dx%d]", PtLeftBottom.X, PtLeftBottom.Y, pRect->X, pRect->Y, pRect->Width, pRect->Height);
|
|
}
|
|
if(PtLeftBottom.Y == pRegion->mRect.Y + pRegion->mRect.Height - 1)
|
|
{
|
|
if(PtLeftBottom.X <= pRegion->mRect.X)
|
|
{
|
|
aloge("fatal error! X");
|
|
bError = TRUE;
|
|
}
|
|
//cut one region is enough.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Width = PtLeftBottom.X - pRegion->mRect.X;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else if(PtLeftBottom.Y < pRegion->mRect.Y + pRegion->mRect.Height - 1)
|
|
{
|
|
if(PtLeftBottom.Y < pRegion->mRect.Y)
|
|
{
|
|
aloge("fatal error! Y");
|
|
bError = TRUE;
|
|
}
|
|
if(PtLeftBottom.X == pRegion->mRect.X)
|
|
{
|
|
//cut one region is enough.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = PtLeftBottom.Y + 1;
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y + pRegion->mRect.Height - (PtLeftBottom.Y + 1);
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else if(PtLeftBottom.X > pRegion->mRect.X)
|
|
{
|
|
//cut two region.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Width = PtLeftBottom.X - pRegion->mRect.X;
|
|
pDivideRegion->mRect.Height = PtLeftBottom.Y - pRegion->mRect.Y + 1;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
|
|
pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = PtLeftBottom.Y + 1;
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y + pRegion->mRect.Height - (PtLeftBottom.Y + 1);
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! X");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! Y");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else if(PointPos_RightBottom == stRectPoints.mPointIndexArray[0])
|
|
{
|
|
//case(2.4) point is rightBottom in Region
|
|
POINT_S PtRightBottom = stRectPoints.mPtArray[0];
|
|
if(!(PtRightBottom.X == pRect->X + pRect->Width - 1 && PtRightBottom.Y == pRect->Y + pRect->Height - 1))
|
|
{
|
|
aloge("fatal error! point error [%d,%d]!=[%d,%d, %dx%d]", PtRightBottom.X, PtRightBottom.Y, pRect->X, pRect->Y, pRect->Width, pRect->Height);
|
|
}
|
|
if(PtRightBottom.Y == pRegion->mRect.Y + pRegion->mRect.Height - 1)
|
|
{
|
|
if(PtRightBottom.X < pRegion->mRect.X || PtRightBottom.X >= pRegion->mRect.X + pRegion->mRect.Width - 1)
|
|
{
|
|
aloge("fatal error! X");
|
|
bError = TRUE;
|
|
}
|
|
//cut one region is enough.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.X = PtRightBottom.X + 1;
|
|
pDivideRegion->mRect.Width = pRegion->mRect.X + pRegion->mRect.Width - (PtRightBottom.X + 1);
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else if(PtRightBottom.Y < pRegion->mRect.Y + pRegion->mRect.Height - 1)
|
|
{
|
|
if(PtRightBottom.Y < pRegion->mRect.Y)
|
|
{
|
|
aloge("fatal error! Y");
|
|
bError = TRUE;
|
|
}
|
|
if(PtRightBottom.X == pRegion->mRect.X + pRegion->mRect.Width - 1)
|
|
{
|
|
//cut one region is enough.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = PtRightBottom.Y + 1;
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y + pRegion->mRect.Height - (PtRightBottom.Y + 1);
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else if(PtRightBottom.X < pRegion->mRect.X + pRegion->mRect.Width - 1)
|
|
{
|
|
if(PtRightBottom.X < pRegion->mRect.X)
|
|
{
|
|
aloge("fatal error! X");
|
|
bError = TRUE;
|
|
}
|
|
//cut two region.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.X = PtRightBottom.X+1;
|
|
pDivideRegion->mRect.Width = pRegion->mRect.X + pRegion->mRect.Width - (PtRightBottom.X+1);
|
|
pDivideRegion->mRect.Height = PtRightBottom.Y - pRegion->mRect.Y + 1;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
|
|
pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = PtRightBottom.Y + 1;
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y + pRegion->mRect.Height - (PtRightBottom.Y + 1);
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! X");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! Y");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! unknown point pos is[0x%x]?", stRectPoints.mPointIndexArray[0]);
|
|
}
|
|
|
|
if(bError)
|
|
{
|
|
aloge("fatal error! check rect [%d,%d, %dx%d],[%d,%d, %dx%d]",
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height,
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height);
|
|
ret = ERR_VI_INVALID_PARA;
|
|
}
|
|
return ret;
|
|
}
|
|
else if((2 == stRectPoints.mNum && 0 == stRegionPoints.mNum) || (2 == stRectPoints.mNum && 1 == stRegionPoints.mNum))
|
|
{
|
|
//case(3) cut more.
|
|
BOOL bError = FALSE;
|
|
//case(3.1) rect is at top of region.
|
|
if(PointPos_LeftBottom == stRectPoints.mPointIndexArray[0] && PointPos_RightBottom == stRectPoints.mPointIndexArray[1])
|
|
{
|
|
int rgnNum = 0;
|
|
POINT_S PtLeftBottom = stRectPoints.mPtArray[0];
|
|
POINT_S PtRightBottom = stRectPoints.mPtArray[1];
|
|
if(PtLeftBottom.X > pRegion->mRect.X)
|
|
{
|
|
//leftTop region is cutted out.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Width = PtLeftBottom.X - pRegion->mRect.X;
|
|
pDivideRegion->mRect.Height = PtLeftBottom.Y - pRegion->mRect.Y + 1;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
if(PtRightBottom.X < pRegion->mRect.X + pRegion->mRect.Width - 1)
|
|
{
|
|
//rightTop region is cutted out.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.X = PtRightBottom.X + 1;
|
|
pDivideRegion->mRect.Width = pRegion->mRect.X + pRegion->mRect.Width - pDivideRegion->mRect.X;
|
|
pDivideRegion->mRect.Height = PtRightBottom.Y - pRegion->mRect.Y + 1;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
if(PtLeftBottom.Y < pRegion->mRect.Y + pRegion->mRect.Height - 1)
|
|
{
|
|
//bottom region is cutted out
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = PtLeftBottom.Y + 1;
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y + pRegion->mRect.Height - pDivideRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
//judge if wrong.
|
|
if(0 == stRegionPoints.mNum && 2 == rgnNum)
|
|
{
|
|
if(PtLeftBottom.Y != pRegion->mRect.Y + pRegion->mRect.Height - 1)
|
|
{
|
|
aloge("fatal error! cut region exception!");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else if(1 == stRegionPoints.mNum)
|
|
{
|
|
if(rgnNum != 2)
|
|
{
|
|
aloge("fatal error! cut region exception2!");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
if(bError)
|
|
{
|
|
aloge("fatal error! region[%d,%d,%dx%d], rect[%d,%d,%dx%d], ptLeftBottom[%d,%d], ptRightBottom[%d,%d]",
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height,
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height,
|
|
PtLeftBottom.X, PtLeftBottom.Y, PtRightBottom.X, PtRightBottom.Y);
|
|
ret = ERR_VI_INVALID_PARA;
|
|
}
|
|
}
|
|
//case(3.2) rect is at bottom of region.
|
|
else if(PointPos_LeftTop == stRectPoints.mPointIndexArray[0] && PointPos_RightTop == stRectPoints.mPointIndexArray[1])
|
|
{
|
|
int rgnNum = 0;
|
|
POINT_S PtLeftTop = stRectPoints.mPtArray[0];
|
|
POINT_S PtRightTop = stRectPoints.mPtArray[1];
|
|
if(PtLeftTop.X > pRegion->mRect.X)
|
|
{
|
|
//leftbottom region is cutted out.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = PtLeftTop.Y;
|
|
pDivideRegion->mRect.Width = PtLeftTop.X - pRegion->mRect.X;
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y + pRegion->mRect.Height - pDivideRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
if(PtRightTop.X < pRegion->mRect.X + pRegion->mRect.Width - 1)
|
|
{
|
|
//rightBottom region is cutted out.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.X = PtRightTop.X + 1;
|
|
pDivideRegion->mRect.Y = PtRightTop.Y;
|
|
pDivideRegion->mRect.Width = pRegion->mRect.X + pRegion->mRect.Width - pDivideRegion->mRect.X;
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y + pRegion->mRect.Height - pDivideRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
if(PtLeftTop.Y > pRegion->mRect.Y)
|
|
{
|
|
//top region is cutted out
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Height = PtLeftTop.Y - pRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
//judge if wrong.
|
|
if(0 == stRegionPoints.mNum && 2 == rgnNum)
|
|
{
|
|
if(PtLeftTop.Y != pRegion->mRect.Y)
|
|
{
|
|
aloge("fatal error! cut region exception!");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else if(1 == stRegionPoints.mNum)
|
|
{
|
|
if(rgnNum != 2)
|
|
{
|
|
aloge("fatal error! cut region exception2!");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
if(bError)
|
|
{
|
|
aloge("fatal error! region[%d,%d,%dx%d], rect[%d,%d,%dx%d], ptLeftTop[%d,%d], ptRightTop[%d,%d]",
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height,
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height,
|
|
PtLeftTop.X, PtLeftTop.Y, PtRightTop.X, PtRightTop.Y);
|
|
ret = ERR_VI_INVALID_PARA;
|
|
}
|
|
}
|
|
//case(3.3) rect is at left of region.
|
|
else if(PointPos_RightTop == stRectPoints.mPointIndexArray[0] && PointPos_RightBottom == stRectPoints.mPointIndexArray[1])
|
|
{
|
|
int rgnNum = 0;
|
|
POINT_S PtRightTop = stRectPoints.mPtArray[0];
|
|
POINT_S PtRightBottom = stRectPoints.mPtArray[1];
|
|
if(PtRightTop.Y > pRegion->mRect.Y)
|
|
{
|
|
//top region is cutted out.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Height = PtRightTop.Y - pRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
if(PtRightBottom.Y < pRegion->mRect.Y + pRegion->mRect.Height - 1)
|
|
{
|
|
//bottom region is cutted out.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = PtRightBottom.Y + 1;
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y + pRegion->mRect.Height - pDivideRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
if(PtRightTop.X < pRegion->mRect.X + pRegion->mRect.Width - 1)
|
|
{
|
|
//middle region is cutted out
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.X = PtRightTop.X + 1;
|
|
pDivideRegion->mRect.Y = PtRightTop.Y;
|
|
pDivideRegion->mRect.Width = pRegion->mRect.X + pRegion->mRect.Width - pDivideRegion->mRect.X;
|
|
pDivideRegion->mRect.Height = PtRightBottom.Y - PtRightTop.Y + 1;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
//judge if wrong.
|
|
if(0 == stRegionPoints.mNum && 2 == rgnNum)
|
|
{
|
|
if(PtRightTop.X != pRegion->mRect.X + pRegion->mRect.Width - 1)
|
|
{
|
|
aloge("fatal error! cut region exception!");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else if(1 == stRegionPoints.mNum)
|
|
{
|
|
if(rgnNum != 2)
|
|
{
|
|
aloge("fatal error! cut region exception2!");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
if(bError)
|
|
{
|
|
aloge("fatal error! region[%d,%d,%dx%d], rect[%d,%d,%dx%d], ptRightTop[%d,%d], ptRightBottom[%d,%d]",
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height,
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height,
|
|
PtRightTop.X, PtRightTop.Y, PtRightBottom.X, PtRightBottom.Y);
|
|
ret = ERR_VI_INVALID_PARA;
|
|
}
|
|
}
|
|
//case(3.4) rect is at right of region.
|
|
else if(PointPos_LeftTop == stRectPoints.mPointIndexArray[0] && PointPos_LeftBottom == stRectPoints.mPointIndexArray[1])
|
|
{
|
|
int rgnNum = 0;
|
|
POINT_S PtLeftTop = stRectPoints.mPtArray[0];
|
|
POINT_S PtLeftBottom = stRectPoints.mPtArray[1];
|
|
if(PtLeftTop.Y > pRegion->mRect.Y)
|
|
{
|
|
//top region is cutted out.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Height = PtLeftTop.Y - pRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
if(PtLeftBottom.Y < pRegion->mRect.Y + pRegion->mRect.Height - 1)
|
|
{
|
|
//bottom region is cutted out.
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = PtLeftBottom.Y + 1;
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y + pRegion->mRect.Height - pDivideRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
if(PtLeftTop.X > pRegion->mRect.X)
|
|
{
|
|
//middle region is cutted out
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = PtLeftTop.Y;
|
|
pDivideRegion->mRect.Width = PtLeftTop.X - pRegion->mRect.X;
|
|
pDivideRegion->mRect.Height = PtLeftBottom.Y - PtLeftTop.Y + 1;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
//judge if wrong.
|
|
if(0 == stRegionPoints.mNum && 2 == rgnNum)
|
|
{
|
|
if(PtLeftTop.X != pRegion->mRect.X)
|
|
{
|
|
aloge("fatal error! cut region exception!");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else if(1 == stRegionPoints.mNum)
|
|
{
|
|
if(rgnNum != 2)
|
|
{
|
|
aloge("fatal error! cut region exception2!");
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
if(bError)
|
|
{
|
|
aloge("fatal error! region[%d,%d,%dx%d], rect[%d,%d,%dx%d], ptLeftTop[%d,%d], ptLeftBottom[%d,%d]",
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height,
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height,
|
|
PtLeftTop.X, PtLeftTop.Y, PtLeftBottom.X, PtLeftBottom.Y);
|
|
ret = ERR_VI_INVALID_PARA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! check region[%d,%d,%dx%d], rect[%d,%d,%dx%d]",
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height,
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height);
|
|
ret = ERR_VI_INVALID_PARA;
|
|
}
|
|
return ret;
|
|
}
|
|
else if(0 == stRectPoints.mNum && 0 == stRegionPoints.mNum)
|
|
{
|
|
//case(4) cross overlap.
|
|
POINT_S ptRegion[4] =
|
|
{
|
|
{pRegion->mRect.X, pRegion->mRect.Y},
|
|
{pRegion->mRect.X+pRegion->mRect.Width-1, pRegion->mRect.Y},
|
|
{pRegion->mRect.X, pRegion->mRect.Y+pRegion->mRect.Height-1},
|
|
{pRegion->mRect.X+pRegion->mRect.Width-1, pRegion->mRect.Y+pRegion->mRect.Height-1}
|
|
};
|
|
POINT_S ptRect[4] =
|
|
{
|
|
{pRect->X, pRect->Y},
|
|
{pRect->X+pRect->Width-1, pRect->Y},
|
|
{pRect->X, pRect->Y+pRect->Height-1},
|
|
{pRect->X+pRect->Width-1, pRect->Y+pRect->Height-1}
|
|
};
|
|
if( ptRegion[PointPos_LeftTop].X < ptRect[PointPos_LeftTop].X
|
|
&& ptRegion[PointPos_LeftTop].Y > ptRect[PointPos_LeftTop].Y
|
|
&& ptRegion[PointPos_RightBottom].X > ptRect[PointPos_RightBottom].X
|
|
&& ptRegion[PointPos_RightBottom].Y < ptRect[PointPos_RightBottom].Y )
|
|
{
|
|
//case(4.1) region is divided to left and right.
|
|
POINT_S PtLeftTop = ptRect[PointPos_LeftTop];
|
|
POINT_S PtRightBottom = ptRect[PointPos_RightBottom];
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Width = PtLeftTop.X - pRegion->mRect.X;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.X = PtRightBottom.X + 1;
|
|
pDivideRegion->mRect.Width = pRegion->mRect.X+pRegion->mRect.Width - pDivideRegion->mRect.X;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else if( ptRegion[PointPos_LeftTop].X > ptRect[PointPos_LeftTop].X
|
|
&& ptRegion[PointPos_LeftTop].Y < ptRect[PointPos_LeftTop].Y
|
|
&& ptRegion[PointPos_RightBottom].X < ptRect[PointPos_RightBottom].X
|
|
&& ptRegion[PointPos_RightBottom].Y > ptRect[PointPos_RightBottom].Y )
|
|
{
|
|
//case(4.2) region is divided to top and bottom.
|
|
POINT_S PtLeftTop = ptRect[PointPos_LeftTop];
|
|
POINT_S PtRightBottom = ptRect[PointPos_RightBottom];
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Height = PtLeftTop.Y - pRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = PtRightBottom.Y + 1;
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y+pRegion->mRect.Height - pDivideRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! region must overlap here!");
|
|
ret = ERR_VI_INVALID_PARA;
|
|
}
|
|
return ret;
|
|
}
|
|
else if(4 == stRectPoints.mNum)
|
|
{
|
|
BOOL bError = FALSE;
|
|
//case(5) involve.
|
|
if(!(stRegionPoints.mNum>=0 && stRegionPoints.mNum<=2))
|
|
{
|
|
aloge("fatal error! region points number[%d] wrong!", stRegionPoints.mNum);
|
|
return ERR_VI_INVALID_PARA;
|
|
}
|
|
int rgnNum = 0;
|
|
//divide to 4 region max, from top to bottom, left to right.
|
|
if(stRectPoints.mPtArray[PointPos_LeftTop].Y > pRegion->mRect.Y)
|
|
{
|
|
//top region can be divided
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Height = stRectPoints.mPtArray[PointPos_LeftTop].Y - pRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
if(stRectPoints.mPtArray[PointPos_LeftTop].X > pRegion->mRect.X)
|
|
{
|
|
//left region can be divided
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = stRectPoints.mPtArray[PointPos_LeftTop].Y;
|
|
pDivideRegion->mRect.Width = stRectPoints.mPtArray[PointPos_LeftTop].X - pRegion->mRect.X;
|
|
pDivideRegion->mRect.Height = stRectPoints.mPtArray[PointPos_RightBottom].Y - stRectPoints.mPtArray[PointPos_LeftTop].Y + 1;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
if(stRectPoints.mPtArray[PointPos_RightTop].X < pRegion->mRect.X + pRegion->mRect.Width - 1)
|
|
{
|
|
//right region can be divided
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.X = stRectPoints.mPtArray[PointPos_RightTop].X + 1;
|
|
pDivideRegion->mRect.Y = stRectPoints.mPtArray[PointPos_RightTop].Y;
|
|
pDivideRegion->mRect.Width = pRegion->mRect.X + pRegion->mRect.Width - pDivideRegion->mRect.X;
|
|
pDivideRegion->mRect.Height = stRectPoints.mPtArray[PointPos_RightBottom].Y - stRectPoints.mPtArray[PointPos_RightTop].Y + 1;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
if(stRectPoints.mPtArray[PointPos_LeftBottom].Y < pRegion->mRect.Y + pRegion->mRect.Height - 1)
|
|
{
|
|
//bottom region can be divided
|
|
OsdRegion *pDivideRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
memcpy(pDivideRegion, pRegion, sizeof(OsdRegion));
|
|
pDivideRegion->mRect.Y = stRectPoints.mPtArray[PointPos_LeftBottom].Y + 1;
|
|
pDivideRegion->mRect.Height = pRegion->mRect.Y + pRegion->mRect.Height - pDivideRegion->mRect.Y;
|
|
list_add_tail(&pDivideRegion->mList, pDividedList);
|
|
rgnNum++;
|
|
}
|
|
//judge if wrong.
|
|
int nSideNum = 0;
|
|
if(stRectPoints.mPtArray[PointPos_LeftTop].X == pRegion->mRect.X)
|
|
{
|
|
nSideNum++;
|
|
}
|
|
if(stRectPoints.mPtArray[PointPos_LeftTop].Y == pRegion->mRect.Y)
|
|
{
|
|
nSideNum++;
|
|
}
|
|
if(stRectPoints.mPtArray[PointPos_RightBottom].X == pRegion->mRect.X + pRegion->mRect.Width - 1)
|
|
{
|
|
nSideNum++;
|
|
}
|
|
if(stRectPoints.mPtArray[PointPos_RightBottom].Y == pRegion->mRect.Y + pRegion->mRect.Height - 1)
|
|
{
|
|
nSideNum++;
|
|
}
|
|
if(0 == nSideNum)
|
|
{
|
|
if(rgnNum != 4)
|
|
{
|
|
aloge("fatal error! sideNum[%d], rgnNum[%d]!=4", nSideNum, rgnNum);
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else if(1 == nSideNum)
|
|
{
|
|
if(rgnNum != 3)
|
|
{
|
|
aloge("fatal error! sideNum[%d], rgnNum[%d]!=3", nSideNum, rgnNum);
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else if(2 == nSideNum)
|
|
{
|
|
if(rgnNum != 2)
|
|
{
|
|
aloge("fatal error! sideNum[%d], rgnNum[%d]!=2", nSideNum, rgnNum);
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else if(3 == nSideNum)
|
|
{
|
|
if(rgnNum != 1)
|
|
{
|
|
aloge("fatal error! sideNum[%d], rgnNum[%d]!=1", nSideNum, rgnNum);
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! sideNum[%d], rgnNum[%d]!=1", nSideNum, rgnNum);
|
|
bError = TRUE;
|
|
}
|
|
if(bError)
|
|
{
|
|
aloge("fatal error! region[%d,%d,%dx%d], rect[%d,%d,%dx%d]",
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height,
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height);
|
|
ret = ERR_VI_INVALID_PARA;
|
|
}
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! stRectPoints[%d], stRegionPoints[%d], rect[%d,%d,%dx%d], regionRect[%d,%d,%dx%d]",
|
|
stRectPoints.mNum, stRegionPoints.mNum,
|
|
pRect->X, pRect->Y, pRect->Width, pRect->Height,
|
|
pRegion->mRect.X, pRegion->mRect.Y, pRegion->mRect.Width, pRegion->mRect.Height);
|
|
return ERR_VI_INVALID_PARA;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* pt1 pt2
|
|
* ------------
|
|
* | |
|
|
* |----------|
|
|
* pt3 pt4
|
|
* involve prior than involved!
|
|
* careful: OsdOverlapArea_Part has cases blow:
|
|
* dstPointsInSrc srcPointsInDst
|
|
* (1) 1 1
|
|
* (2) 1 2
|
|
* (3) 2 0
|
|
* (4) 2 1
|
|
* (5) 2 2
|
|
* (6) 0 2
|
|
* (7) 0 0
|
|
* If case(0, 0), it means:
|
|
* _________
|
|
* ____|_______|___
|
|
* | | | |
|
|
* |___|_______|__|
|
|
* |_______|
|
|
* @return
|
|
* OsdOverlapArea_WholeInvolve: pDst overlap pSrc entirely.
|
|
* OsdOverlapArea_WholeInvolved: pDst is overlaped by pSrc entirely.
|
|
*/
|
|
OsdOverlapAreaType IfOsdRegionOverlap(RECT_S *pDst, RECT_S *pSrc)
|
|
{
|
|
POINT_S ptDst[4] =
|
|
{
|
|
{pDst->X, pDst->Y},
|
|
{pDst->X+pDst->Width-1, pDst->Y},
|
|
{pDst->X, pDst->Y+pDst->Height-1},
|
|
{pDst->X+pDst->Width-1, pDst->Y+pDst->Height-1}
|
|
};
|
|
POINT_S ptSrc[4] =
|
|
{
|
|
{pSrc->X, pSrc->Y},
|
|
{pSrc->X+pSrc->Width-1, pSrc->Y},
|
|
{pSrc->X, pSrc->Y+pSrc->Height-1},
|
|
{pSrc->X+pSrc->Width-1, pSrc->Y+pSrc->Height-1}
|
|
};
|
|
int i;
|
|
BOOL bDstPtIn[4];
|
|
for(i=0; i<4; i++)
|
|
{
|
|
if(ptDst[i].X >= ptSrc[PointPos_LeftTop].X && ptDst[i].X <= ptSrc[PointPos_RightBottom].X
|
|
&& ptDst[i].Y >= ptSrc[PointPos_LeftTop].Y && ptDst[i].Y <= ptSrc[PointPos_RightBottom].Y)
|
|
{
|
|
bDstPtIn[i] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
bDstPtIn[i] = FALSE;
|
|
}
|
|
}
|
|
int nDstInNum = 0;
|
|
for(i=0; i<4; i++)
|
|
{
|
|
if(bDstPtIn[i])
|
|
{
|
|
nDstInNum++;
|
|
}
|
|
}
|
|
|
|
BOOL bSrcPtIn[4];
|
|
for(i=0; i<4; i++)
|
|
{
|
|
if(ptSrc[i].X >= ptDst[PointPos_LeftTop].X && ptSrc[i].X <= ptDst[PointPos_RightBottom].X
|
|
&& ptSrc[i].Y >= ptDst[PointPos_LeftTop].Y && ptSrc[i].Y <= ptDst[PointPos_RightBottom].Y)
|
|
{
|
|
bSrcPtIn[i] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
bSrcPtIn[i] = FALSE;
|
|
}
|
|
}
|
|
int nSrcInNum = 0;
|
|
for(i=0; i<4; i++)
|
|
{
|
|
if(bSrcPtIn[i])
|
|
{
|
|
nSrcInNum++;
|
|
}
|
|
}
|
|
|
|
if(4 == nSrcInNum)
|
|
{
|
|
return OsdOverlapArea_WholeInvolve;
|
|
}
|
|
if(4 == nDstInNum)
|
|
{
|
|
return OsdOverlapArea_WholeInvolved;
|
|
}
|
|
if(nDstInNum > 0 || nSrcInNum > 0)
|
|
{
|
|
return OsdOverlapArea_Part;
|
|
}
|
|
else if(0 == nDstInNum && 0 == nSrcInNum)
|
|
{
|
|
if( ( ptDst[PointPos_LeftTop].X < ptSrc[PointPos_LeftTop].X
|
|
&& ptDst[PointPos_LeftTop].Y > ptSrc[PointPos_LeftTop].Y
|
|
&& ptDst[PointPos_RightBottom].X > ptSrc[PointPos_RightBottom].X
|
|
&& ptDst[PointPos_RightBottom].Y < ptSrc[PointPos_RightBottom].Y)
|
|
||
|
|
( ptDst[PointPos_LeftTop].X > ptSrc[PointPos_LeftTop].X
|
|
&& ptDst[PointPos_LeftTop].Y < ptSrc[PointPos_LeftTop].Y
|
|
&& ptDst[PointPos_RightBottom].X < ptSrc[PointPos_RightBottom].X
|
|
&& ptDst[PointPos_RightBottom].Y > ptSrc[PointPos_RightBottom].Y) )
|
|
{
|
|
return OsdOverlapArea_Part;
|
|
}
|
|
else
|
|
{
|
|
return OsdOverlapArea_None;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! region overlap wrong. nDstInNum[%d], nSrcInNum[%d], dstRgn[%d,%d,%dx%d], srcRgn[%d,%d,%dx%d]",
|
|
nDstInNum, nSrcInNum, pDst->X, pDst->Y, pDst->Width, pDst->Height,
|
|
pSrc->X, pSrc->Y, pSrc->Width, pSrc->Height);
|
|
return OsdOverlapArea_None;
|
|
}
|
|
}
|
|
|
|
OsdOverlapType IfOverlayCoverOverlap(OsdGroup *pGroup)
|
|
{
|
|
BOOL bOverlayExist = FALSE;
|
|
BOOL bCoverExist = FALSE;
|
|
|
|
OsdRegion *pEntry;
|
|
list_for_each_entry(pEntry, &pGroup->mOsdList, mList)
|
|
{
|
|
if(OVERLAY_RGN == pEntry->mType)
|
|
{
|
|
bOverlayExist = TRUE;
|
|
}
|
|
else if(COVER_RGN == pEntry->mType)
|
|
{
|
|
bCoverExist = TRUE;
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error!");
|
|
}
|
|
}
|
|
if(bOverlayExist && bCoverExist)
|
|
{
|
|
return OsdOverlap_CoverOverlay;
|
|
}
|
|
else if(bOverlayExist)
|
|
{
|
|
return OsdOverlap_OnlyOverlay;
|
|
}
|
|
else if(bCoverExist)
|
|
{
|
|
return OsdOverlap_OnlyCover;
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error!");
|
|
return OsdOverlap_None;
|
|
}
|
|
}
|
|
/**
|
|
* pRegionList: type is OsdRegion.
|
|
* @return TRUE:involved, FALSE:not involved.
|
|
*/
|
|
BOOL IfOsdRegionInvolvedByOsdRegions(OsdRegion *pRegion, struct list_head *pRegionList)
|
|
{
|
|
if(!list_empty(pRegionList))
|
|
{
|
|
BOOL bInvolved = FALSE;
|
|
OsdRegion *pEntry;
|
|
OsdOverlapAreaType eOverlapAreaType;
|
|
list_for_each_entry(pEntry, pRegionList, mList)
|
|
{
|
|
eOverlapAreaType = IfOsdRegionOverlap(&pEntry->mRect, &pRegion->mRect);
|
|
if(OsdOverlapArea_WholeInvolve == eOverlapAreaType)
|
|
{
|
|
bInvolved = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
return bInvolved;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
/**
|
|
* According To OsdList to redraw new OsdList which don't overlap each other.
|
|
* We will malloc buffer for RedrawOsdList.
|
|
* divide region method: overloop from top and cut, tranverse node from bottom to top.
|
|
* resort cover in pure cover list.
|
|
*
|
|
* @param nPixelFormat pixel format of overlay, V4L2_PIX_FMT_RGB32
|
|
* @param pCoverGroup contain cover cutted, MAX_COVER_NUM is max.
|
|
*/
|
|
ERRORTYPE RedrawOsdGroup_V5(OsdGroup *pGroup, int nPixelFormat, OsdGroup *pCoverGroup)
|
|
{
|
|
INIT_LIST_HEAD(&pGroup->mRedrawOsdList);
|
|
OsdOverlapType eOverlapType = IfOverlayCoverOverlap(pGroup);
|
|
//(1) only covers
|
|
if(OsdOverlap_OnlyCover == eOverlapType)
|
|
{
|
|
//keep OsdList. let RedrawOsdList be empty.
|
|
ResortOsdRegionByPriority(&pGroup->mOsdList);
|
|
return SUCCESS;
|
|
}
|
|
else if(OsdOverlap_OnlyOverlay == eOverlapType || OsdOverlap_CoverOverlay == eOverlapType)
|
|
{
|
|
//if only one overlay, keep OsdList.
|
|
//if multi overlay, construct RedrawOsdList.
|
|
if(!list_is_singular(&pGroup->mOsdList))
|
|
{
|
|
ResortOsdRegionByPriority(&pGroup->mOsdList);
|
|
//copy OsdList to RedrawOsdList
|
|
LIST_HEAD(tmpOsdList);
|
|
ShallowCopyOsdRegionList(&tmpOsdList, &pGroup->mOsdList);
|
|
//divide method:
|
|
while(1)
|
|
{
|
|
OsdOverlapAreaType eOverlapAreaType;
|
|
OsdRegion *pEntry, *pTmp;
|
|
pEntry = list_first_entry_or_null(&tmpOsdList, OsdRegion, mList);
|
|
if(NULL == pEntry)
|
|
{
|
|
//all region has been processed, can break now
|
|
break;
|
|
}
|
|
LIST_HEAD(regionDividedList);
|
|
list_move_tail(&pEntry->mList, ®ionDividedList);
|
|
list_for_each_entry(pEntry, &tmpOsdList, mList)
|
|
{
|
|
//divide all entries of regionDividedList by every region of tmpOsdList, so need tranverse regionDividedList
|
|
LIST_HEAD(tmpRegionDividedList);
|
|
OsdRegion *pRegionDividedEntry, *pRegionDividedTmp;
|
|
list_for_each_entry_safe(pRegionDividedEntry, pRegionDividedTmp, ®ionDividedList, mList)
|
|
{
|
|
//(2.1)look if this entry is involved entirely.
|
|
if(IfOsdRegionInvolvedByOsdRegions(pRegionDividedEntry, &tmpOsdList))
|
|
{
|
|
list_del(&pRegionDividedEntry->mList);
|
|
free(pRegionDividedEntry);
|
|
continue;
|
|
}
|
|
//(2.2)divide dividedEntry to unoverlapped regions, add to tmpRegionDividedList tail. free it if divided.
|
|
eOverlapAreaType = IfOsdRegionOverlap(&pEntry->mRect, &pRegionDividedEntry->mRect);
|
|
if(OsdOverlapArea_None == eOverlapAreaType)
|
|
{
|
|
}
|
|
else if(OsdOverlapArea_Part == eOverlapAreaType)
|
|
{
|
|
//merge is prior, if dstRegion's zero point, one point is in srcRegion, divide srcRegion.
|
|
//if dstRegion's two points are in srcRegion, devide dstRegion.
|
|
//must divide dividedEntry.
|
|
//divide OsdRegion to several regions, put increased regions to tmpRegionDividedList tail.
|
|
PointsArray stPoints;
|
|
ProbePointsInRect(&pEntry->mRect, &pRegionDividedEntry->mRect, &stPoints);
|
|
if(0 == stPoints.mNum)
|
|
{
|
|
//only one case is possible: srcEntry has two points in DstEntry.
|
|
//cut srcEntry
|
|
PointsArray srcPoints;
|
|
ProbePointsInRect(&pRegionDividedEntry->mRect, &pEntry->mRect, &srcPoints);
|
|
if(2 == srcPoints.mNum || 0 == srcPoints.mNum)
|
|
{
|
|
LIST_HEAD(regionCuttedList);
|
|
if(SUCCESS!=CutRegionByRect(pRegionDividedEntry, &pEntry->mRect, ®ionCuttedList))
|
|
{
|
|
aloge("fatal error! why rect is not cut?cutRgn[%d,%d,%dx%d], refRgn[%d,%d,%dx%d]",
|
|
pRegionDividedEntry->mRect.X, pRegionDividedEntry->mRect.Y, pRegionDividedEntry->mRect.Width, pRegionDividedEntry->mRect.Height,
|
|
pEntry->mRect.X, pEntry->mRect.Y, pEntry->mRect.Width, pEntry->mRect.Height);
|
|
}
|
|
list_splice_tail_init(®ionCuttedList, &tmpRegionDividedList);
|
|
list_del(&pRegionDividedEntry->mList);
|
|
free(pRegionDividedEntry);
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! check code!");
|
|
}
|
|
}
|
|
else if(1 == stPoints.mNum)
|
|
{
|
|
LIST_HEAD(regionCuttedList);
|
|
if(SUCCESS!=CutRegionByRect(pRegionDividedEntry, &pEntry->mRect, ®ionCuttedList))
|
|
{
|
|
aloge("fatal error! why rect is not cut?cutRgn[%d,%d,%dx%d], refRgn[%d,%d,%dx%d]",
|
|
pRegionDividedEntry->mRect.X, pRegionDividedEntry->mRect.Y, pRegionDividedEntry->mRect.Width, pRegionDividedEntry->mRect.Height,
|
|
pEntry->mRect.X, pEntry->mRect.Y, pEntry->mRect.Width, pEntry->mRect.Height);
|
|
}
|
|
list_splice_tail_init(®ionCuttedList, &tmpRegionDividedList);
|
|
list_del(&pRegionDividedEntry->mList);
|
|
free(pRegionDividedEntry);
|
|
}
|
|
else if(2 == stPoints.mNum)
|
|
{
|
|
LIST_HEAD(regionCuttedList);
|
|
if(SUCCESS!=CutRegionByRect(pRegionDividedEntry, &pEntry->mRect, ®ionCuttedList))
|
|
{
|
|
aloge("fatal error! why rect is not cut?cutRgn[%d,%d,%dx%d], refRgn[%d,%d,%dx%d]",
|
|
pRegionDividedEntry->mRect.X, pRegionDividedEntry->mRect.Y, pRegionDividedEntry->mRect.Width, pRegionDividedEntry->mRect.Height,
|
|
pEntry->mRect.X, pEntry->mRect.Y, pEntry->mRect.Width, pEntry->mRect.Height);
|
|
}
|
|
list_splice_tail_init(®ionCuttedList, &tmpRegionDividedList);
|
|
list_del(&pRegionDividedEntry->mList);
|
|
free(pRegionDividedEntry);
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! overlay area type is part, check code!");
|
|
}
|
|
}
|
|
else if(OsdOverlapArea_WholeInvolved == eOverlapAreaType)
|
|
{
|
|
LIST_HEAD(regionCuttedList);
|
|
if(SUCCESS!=CutRegionByRect(pRegionDividedEntry, &pEntry->mRect, ®ionCuttedList))
|
|
{
|
|
aloge("fatal error! why rect is not cut? cutRgn[%d,%d,%dx%d], refRgn[%d,%d,%dx%d]",
|
|
pRegionDividedEntry->mRect.X, pRegionDividedEntry->mRect.Y, pRegionDividedEntry->mRect.Width, pRegionDividedEntry->mRect.Height,
|
|
pEntry->mRect.X, pEntry->mRect.Y, pEntry->mRect.Width, pEntry->mRect.Height);
|
|
}
|
|
list_splice_tail_init(®ionCuttedList, &tmpRegionDividedList);
|
|
list_del(&pRegionDividedEntry->mList);
|
|
free(pRegionDividedEntry);
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! overlapAreaType[0x%x]?", eOverlapAreaType);
|
|
}
|
|
}
|
|
//add new divided regions to regionDividedList
|
|
list_splice_tail_init(&tmpRegionDividedList, ®ionDividedList);
|
|
}
|
|
//add new region divided list to tmpDividedlist
|
|
list_splice_tail_init(®ionDividedList, &pGroup->mRedrawOsdList);
|
|
}
|
|
//redraw list is constructed now, then malloc for them.
|
|
int nLeftCoverNum = 0;
|
|
if(pCoverGroup)
|
|
{
|
|
int cnt = 0;
|
|
struct list_head *pList;
|
|
list_for_each(pList, &pCoverGroup->mOsdList) { cnt++; }
|
|
if(cnt <= MAX_COVER_NUM)
|
|
{
|
|
nLeftCoverNum = MAX_COVER_NUM - cnt;
|
|
alogd("left [%d]covers can use", nLeftCoverNum);
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! cover number[%d] is exceed!", cnt);
|
|
nLeftCoverNum = 0;
|
|
}
|
|
}
|
|
OsdRegion *pEntry, *pTmp;
|
|
list_for_each_entry_safe(pEntry, pTmp, &pGroup->mRedrawOsdList, mList)
|
|
{
|
|
if(OVERLAY_RGN == pEntry->mType)
|
|
{
|
|
mallocBmpBufForOsdRegion(pEntry, nPixelFormat);
|
|
}
|
|
else if(COVER_RGN == pEntry->mType)
|
|
{
|
|
if(nLeftCoverNum > 0)
|
|
{
|
|
list_move_tail(&pEntry->mList, &pCoverGroup->mOsdList);
|
|
nLeftCoverNum--;
|
|
}
|
|
else
|
|
{
|
|
alogd("Be careful! cover region will be translate to overlay region.");
|
|
pEntry->mType = OVERLAY_RGN;
|
|
pEntry->mInfo.mOverlay.mBitmap = NULL;
|
|
pEntry->mInfo.mOverlay.mbInvColEn = FALSE;
|
|
pEntry->mInfo.mOverlay.mPriority = 0; //cover all set lowest priority when transform to overlay.
|
|
mallocBmpBufForOsdRegion(pEntry, nPixelFormat);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! rgnType[0x%x] is wrong!", pEntry->mType);
|
|
}
|
|
//alogd("for debug: redraw rect[%d,%d, %dx%d]", pEntry->mRect.X, pEntry->mRect.Y, pEntry->mRect.Width, pEntry->mRect.Height);
|
|
}
|
|
//fill these bmpBufs of redrawList.
|
|
ERRORTYPE ret = SUCCESS;
|
|
list_for_each_entry(pEntry, &pGroup->mRedrawOsdList, mList)
|
|
{
|
|
ret = DrawRegionByOriginRegions(pEntry, &pGroup->mOsdList, nPixelFormat);
|
|
if(ret!=SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
return SUCCESS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error!");
|
|
return ERR_VI_INVALID_PARA;
|
|
}
|
|
}
|
|
|
|
ERRORTYPE AddRegionToOsdGroup_V5(OsdGroup *pGroup, ChannelRegionInfo *pRegion)
|
|
{
|
|
OsdRegion *pOsdRegion = (OsdRegion*)malloc(sizeof(OsdRegion));
|
|
IF_MALLOC_FAIL(pOsdRegion);
|
|
|
|
memset(pOsdRegion, 0, sizeof(OsdRegion));
|
|
pOsdRegion->mType = pRegion->mRgnAttr.enType;
|
|
if(OVERLAY_RGN == pRegion->mRgnAttr.enType)
|
|
{
|
|
pOsdRegion->mRect.X = pRegion->mRgnChnAttr.unChnAttr.stOverlayChn.stPoint.X;
|
|
pOsdRegion->mRect.Y = pRegion->mRgnChnAttr.unChnAttr.stOverlayChn.stPoint.Y;
|
|
pOsdRegion->mRect.Width = pRegion->mRgnAttr.unAttr.stOverlay.mSize.Width;
|
|
pOsdRegion->mRect.Height = pRegion->mRgnAttr.unAttr.stOverlay.mSize.Height;
|
|
}
|
|
else if(COVER_RGN == pRegion->mRgnAttr.enType)
|
|
{
|
|
if(AREA_RECT == pRegion->mRgnChnAttr.unChnAttr.stCoverChn.enCoverType)
|
|
{
|
|
pOsdRegion->mRect = pRegion->mRgnChnAttr.unChnAttr.stCoverChn.stRect;
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! cover type[0x%x] is not rect!", pRegion->mRgnChnAttr.unChnAttr.stCoverChn.enCoverType);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error!");
|
|
}
|
|
if(OVERLAY_RGN == pOsdRegion->mType)
|
|
{
|
|
pOsdRegion->mInfo.mOverlay.mBitmap = pRegion->mBmp.mpData;
|
|
pOsdRegion->mInfo.mOverlay.mbInvColEn = pRegion->mRgnChnAttr.unChnAttr.stOverlayChn.stInvertColor.bInvColEn;
|
|
pOsdRegion->mInfo.mOverlay.mPriority = pRegion->mRgnChnAttr.unChnAttr.stOverlayChn.mLayer;
|
|
}
|
|
else if(COVER_RGN == pOsdRegion->mType)
|
|
{
|
|
pOsdRegion->mInfo.mCover.mChromaKey = pRegion->mRgnChnAttr.unChnAttr.stCoverChn.mColor;
|
|
pOsdRegion->mInfo.mCover.mPriority = pRegion->mRgnChnAttr.unChnAttr.stCoverChn.mLayer;
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! unknown osd type[0x%x]", pOsdRegion->mType);
|
|
}
|
|
list_add_tail(&pOsdRegion->mList, &pGroup->mOsdList);
|
|
return SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* pt1 pt2
|
|
* ------------
|
|
* | |
|
|
* |----------|
|
|
* pt3 pt4
|
|
*/
|
|
BOOL IfOsdRegionOverlapRegion_V5(OsdRegion *pDst, ChannelRegionInfo *pSrc)
|
|
{
|
|
BOOL bOverlap = FALSE;
|
|
POINT_S ptDst[4] =
|
|
{
|
|
{pDst->mRect.X, pDst->mRect.Y},
|
|
{pDst->mRect.X+pDst->mRect.Width-1, pDst->mRect.Y},
|
|
{pDst->mRect.X, pDst->mRect.Y+pDst->mRect.Height-1},
|
|
{pDst->mRect.X+pDst->mRect.Width-1, pDst->mRect.Y+pDst->mRect.Height-1}
|
|
};
|
|
RECT_S srcRect;
|
|
if(OVERLAY_RGN == pSrc->mRgnAttr.enType)
|
|
{
|
|
srcRect.X = pSrc->mRgnChnAttr.unChnAttr.stOverlayChn.stPoint.X;
|
|
srcRect.Y = pSrc->mRgnChnAttr.unChnAttr.stOverlayChn.stPoint.Y;
|
|
srcRect.Width = pSrc->mRgnAttr.unAttr.stOverlay.mSize.Width;
|
|
srcRect.Height = pSrc->mRgnAttr.unAttr.stOverlay.mSize.Height;
|
|
}
|
|
else if(COVER_RGN == pSrc->mRgnAttr.enType)
|
|
{
|
|
if(AREA_RECT == pSrc->mRgnChnAttr.unChnAttr.stCoverChn.enCoverType)
|
|
{
|
|
srcRect = pSrc->mRgnChnAttr.unChnAttr.stCoverChn.stRect;
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! cover type[0x%x] is not rect!", pSrc->mRgnChnAttr.unChnAttr.stCoverChn.enCoverType);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error!");
|
|
}
|
|
POINT_S ptSrc[4] =
|
|
{
|
|
{srcRect.X, srcRect.Y},
|
|
{srcRect.X+srcRect.Width-1, srcRect.Y},
|
|
{srcRect.X, srcRect.Y+srcRect.Height-1},
|
|
{srcRect.X+srcRect.Width-1, srcRect.Y+srcRect.Height-1}
|
|
};
|
|
for(int i=0; i<4; i++)
|
|
{
|
|
if(ptDst[i].X >= ptSrc[PointPos_LeftTop].X && ptDst[i].X <= ptSrc[PointPos_RightBottom].X
|
|
&& ptDst[i].Y >= ptSrc[PointPos_LeftTop].Y && ptDst[i].Y <= ptSrc[PointPos_RightBottom].Y)
|
|
{
|
|
bOverlap = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if(FALSE == bOverlap)
|
|
{
|
|
for(int i=0; i<4; i++)
|
|
{
|
|
if(ptSrc[i].X >= ptDst[PointPos_LeftTop].X && ptSrc[i].X <= ptDst[PointPos_RightBottom].X
|
|
&& ptSrc[i].Y >= ptDst[PointPos_LeftTop].Y && ptSrc[i].Y <= ptDst[PointPos_RightBottom].Y)
|
|
{
|
|
bOverlap = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(FALSE == bOverlap)
|
|
{
|
|
//anyone's point is not in other's rect. There is still one possible to overlap.
|
|
//ref to IfOsdRegionOverlap()
|
|
if( ( ptDst[PointPos_LeftTop].X < ptSrc[PointPos_LeftTop].X
|
|
&& ptDst[PointPos_LeftTop].Y > ptSrc[PointPos_LeftTop].Y
|
|
&& ptDst[PointPos_RightBottom].X > ptSrc[PointPos_RightBottom].X
|
|
&& ptDst[PointPos_RightBottom].Y < ptSrc[PointPos_RightBottom].Y)
|
|
||
|
|
( ptDst[PointPos_LeftTop].X > ptSrc[PointPos_LeftTop].X
|
|
&& ptDst[PointPos_LeftTop].Y < ptSrc[PointPos_LeftTop].Y
|
|
&& ptDst[PointPos_RightBottom].X < ptSrc[PointPos_RightBottom].X
|
|
&& ptDst[PointPos_RightBottom].Y > ptSrc[PointPos_RightBottom].Y) )
|
|
{
|
|
bOverlap = TRUE;
|
|
}
|
|
}
|
|
return bOverlap;
|
|
}
|
|
|
|
BOOL IfOsdGroupOverlapRegion_V5(OsdGroup *pGroup, ChannelRegionInfo *pRegion)
|
|
{
|
|
BOOL bOverlap = FALSE;
|
|
OsdRegion *pEntry;
|
|
list_for_each_entry(pEntry, &pGroup->mOsdList, mList)
|
|
{
|
|
if(IfOsdRegionOverlapRegion_V5(pEntry, pRegion))
|
|
{
|
|
bOverlap = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
return bOverlap;
|
|
}
|
|
|
|
/**
|
|
* reconstruct osd:
|
|
* (1)group
|
|
* (2)check if cover&overlay overlap
|
|
* (3)every group divide into unoverlapped regions
|
|
* (4)every region calculate color value.
|
|
* (5)all covers are put in one group, this group is at first node.
|
|
* we don't resort here.
|
|
*/
|
|
ERRORTYPE ConfigOsdGroups_V5(OsdGroups *pOsdGroups, viChnManager *pVipp)
|
|
{
|
|
memset(pOsdGroups, 0, sizeof(OsdGroups));
|
|
pOsdGroups->mPixFmt = V4L2_PIX_FMT_RGB32;
|
|
pOsdGroups->mGlobalAlpha = MAX_GLOBAL_ALPHA;
|
|
INIT_LIST_HEAD(&pOsdGroups->mGroupList);
|
|
|
|
//step 0: join list of draw
|
|
LIST_HEAD(DrawList); //ChannelRegionInfo
|
|
ChannelRegionInfo *pRegionEntry;
|
|
list_for_each_entry(pRegionEntry, &pVipp->mCoverList, mList)
|
|
{
|
|
if(pRegionEntry->mbDraw)
|
|
{
|
|
list_add_tail(&pRegionEntry->mTmpList, &DrawList);
|
|
}
|
|
}
|
|
BOOL bFlag = FALSE;
|
|
list_for_each_entry(pRegionEntry, &pVipp->mOverlayList, mList)
|
|
{
|
|
if(FALSE == bFlag)
|
|
{
|
|
pOsdGroups->mPixFmt = map_PIXEL_FORMAT_E_to_V4L2_PIX_FMT(pRegionEntry->mRgnAttr.unAttr.stOverlay.mPixelFmt);
|
|
if(V4L2_PIX_FMT_RGB32 == pOsdGroups->mPixFmt)
|
|
{
|
|
pOsdGroups->mGlobalAlpha = MAX_GLOBAL_ALPHA;
|
|
}
|
|
else if(V4L2_PIX_FMT_RGB555 == pOsdGroups->mPixFmt)
|
|
{
|
|
pOsdGroups->mGlobalAlpha = (unsigned int)pRegionEntry->mRgnChnAttr.unChnAttr.stOverlayChn.mFgAlpha * MAX_GLOBAL_ALPHA/128;
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! unkown pix fmt [0x%x]->[0x%x]", pRegionEntry->mRgnAttr.unAttr.stOverlay.mPixelFmt, pOsdGroups->mPixFmt);
|
|
}
|
|
bFlag = TRUE;
|
|
}
|
|
if(pRegionEntry->mbDraw)
|
|
{
|
|
list_add_tail(&pRegionEntry->mTmpList, &DrawList);
|
|
}
|
|
}
|
|
//step 1: group
|
|
list_for_each_entry(pRegionEntry, &DrawList, mTmpList)
|
|
{
|
|
//put every region to a osd group
|
|
int nOverlapGroupNum = 0;
|
|
OsdGroup *pGroupEntry, *pGroupTmp;
|
|
OsdGroup *pDstGroup;
|
|
list_for_each_entry_safe(pGroupEntry, pGroupTmp, &pOsdGroups->mGroupList, mList)
|
|
{
|
|
//find a group which overlap current region
|
|
if(IfOsdGroupOverlapRegion_V5(pGroupEntry, pRegionEntry))
|
|
{
|
|
if(0 == nOverlapGroupNum)
|
|
{
|
|
//put to this group
|
|
AddRegionToOsdGroup_V5(pGroupEntry, pRegionEntry);
|
|
pDstGroup = pGroupEntry;
|
|
}
|
|
else
|
|
{
|
|
//merge current group into dst group
|
|
list_splice_tail_init(&pGroupEntry->mOsdList, &pDstGroup->mOsdList);
|
|
list_del(&pGroupEntry->mList);
|
|
free(pGroupEntry);
|
|
}
|
|
nOverlapGroupNum++;
|
|
}
|
|
}
|
|
if(0 == nOverlapGroupNum)
|
|
{
|
|
//need add a group
|
|
OsdGroup *pGroup = OsdGroupConstruct();
|
|
IF_MALLOC_FAIL(pGroup);
|
|
AddRegionToOsdGroup_V5(pGroup, pRegionEntry);
|
|
list_add_tail(&pGroup->mList, &pOsdGroups->mGroupList);
|
|
}
|
|
}
|
|
// step 2: merge all cover groups to one, and check if cover&overlay overlap
|
|
int nCoverGroupNum = 0;
|
|
OsdGroup *pDstCoverGroup = NULL;
|
|
OsdGroup *pGroupEntry, *pGroupTmp;
|
|
list_for_each_entry_safe(pGroupEntry, pGroupTmp, &pOsdGroups->mGroupList, mList)
|
|
{
|
|
if(OsdOverlap_OnlyCover == IfOverlayCoverOverlap(pGroupEntry))
|
|
{
|
|
if(0 == nCoverGroupNum)
|
|
{
|
|
pDstCoverGroup = pGroupEntry;
|
|
}
|
|
else
|
|
{
|
|
//merge current group into dst group
|
|
list_splice_tail_init(&pGroupEntry->mOsdList, &pDstCoverGroup->mOsdList);
|
|
list_del(&pGroupEntry->mList);
|
|
free(pGroupEntry);
|
|
}
|
|
nCoverGroupNum++;
|
|
}
|
|
else if(OsdOverlap_CoverOverlay == IfOverlayCoverOverlap(pGroupEntry))
|
|
{
|
|
pOsdGroups->mGlobalAlpha = MAX_GLOBAL_ALPHA;
|
|
}
|
|
}
|
|
BOOL bCoverGroupExist = FALSE;
|
|
if(nCoverGroupNum > 0)
|
|
{
|
|
alogd("merge [%d] cover groups into one, and move it to first node", nCoverGroupNum);
|
|
list_move(&pDstCoverGroup->mList, &pOsdGroups->mGroupList);
|
|
bCoverGroupExist = TRUE;
|
|
}
|
|
OsdGroup *pTmpCoverGroup = NULL;
|
|
if(!bCoverGroupExist)
|
|
{
|
|
pTmpCoverGroup = OsdGroupConstruct();
|
|
}
|
|
//step 3: divide every group into unoverlapped regions
|
|
list_for_each_entry(pGroupEntry, &pOsdGroups->mGroupList, mList)
|
|
{
|
|
RedrawOsdGroup_V5(pGroupEntry, pOsdGroups->mPixFmt, bCoverGroupExist?pDstCoverGroup:pTmpCoverGroup);
|
|
}
|
|
if(!bCoverGroupExist)
|
|
{
|
|
if(!list_empty(&pTmpCoverGroup->mOsdList))
|
|
{
|
|
list_add(&pTmpCoverGroup->mList, &pOsdGroups->mGroupList);
|
|
}
|
|
else
|
|
{
|
|
OsdGroupDestruct(pTmpCoverGroup);
|
|
}
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
ERRORTYPE videoInputHw_DrawOSD_V5(VI_DEV vipp_id)
|
|
{
|
|
ERRORTYPE ret = SUCCESS;
|
|
viChnManager *pVipp = gpVIDevManager->gpVippManager[vipp_id];
|
|
struct isp_video_device *video = gpVIDevManager->media->video_dev[vipp_id];
|
|
//convert to OsdGroups *mpOsdGroups;
|
|
if(pVipp->mpOsdGroups)
|
|
{
|
|
aloge("fatal error! why OsdGroups not destruct?");
|
|
OsdGroupsDestruct(pVipp->mpOsdGroups);
|
|
pVipp->mpOsdGroups = NULL;
|
|
}
|
|
pVipp->mpOsdGroups = OsdGroupsConstruct();
|
|
ConfigOsdGroups_V5(pVipp->mpOsdGroups, pVipp);
|
|
//now all overlays are not overlap. all covers may be overlap.
|
|
//draw cover
|
|
OsdGroup *pFirstGroup = list_first_entry_or_null(&pVipp->mpOsdGroups->mGroupList, OsdGroup, mList);
|
|
BOOL bCoverExist = FALSE;
|
|
if(pFirstGroup)
|
|
{
|
|
if(list_empty(&pFirstGroup->mRedrawOsdList)) //when redraw, can't be cover
|
|
{
|
|
if(!list_empty(&pFirstGroup->mOsdList))
|
|
{
|
|
OsdRegion *pFirstRegion = list_first_entry(&pFirstGroup->mOsdList, OsdRegion, mList);
|
|
if(COVER_RGN == pFirstRegion->mType)
|
|
{
|
|
bCoverExist = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! osdList in OsdGroup can't be empty!");
|
|
}
|
|
}
|
|
}
|
|
if(bCoverExist)
|
|
{
|
|
struct osd_fmt stOsdFmt;
|
|
memset(&stOsdFmt, 0, sizeof(struct osd_fmt));
|
|
OsdRegion *pEntry;
|
|
list_for_each_entry(pEntry, &pFirstGroup->mOsdList, mList)
|
|
{
|
|
if(COVER_RGN == pEntry->mType)
|
|
{
|
|
stOsdFmt.global_alpha = pVipp->mpOsdGroups->mGlobalAlpha; //MAX_GLOBAL_ALPHA
|
|
stOsdFmt.rgb_cover[stOsdFmt.clipcount] = pEntry->mInfo.mCover.mChromaKey;
|
|
stOsdFmt.bitmap[stOsdFmt.clipcount] = NULL;
|
|
stOsdFmt.region[stOsdFmt.clipcount].left = pEntry->mRect.X;
|
|
stOsdFmt.region[stOsdFmt.clipcount].top = pEntry->mRect.Y;
|
|
stOsdFmt.region[stOsdFmt.clipcount].width = pEntry->mRect.Width;
|
|
stOsdFmt.region[stOsdFmt.clipcount].height = pEntry->mRect.Height;
|
|
stOsdFmt.clipcount++;
|
|
if(stOsdFmt.clipcount > MAX_COVER_NUM)
|
|
{
|
|
aloge("fatal error! clipcount[%d] exceed!", stOsdFmt.clipcount);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! region type[0x%x] is not cover!", pEntry->mType);
|
|
}
|
|
}
|
|
int ret1 = overlay_set_fmt(video, &stOsdFmt);
|
|
int ret2 = overlay_update(video, 1);
|
|
if(ret1 != 0)
|
|
{
|
|
aloge("fatal error! set cover fail[%d]", ret1);
|
|
ret = ERR_VI_NOT_SUPPORT;
|
|
}
|
|
if(ret2 != 0)
|
|
{
|
|
aloge("fatal error! cover update fail[%d]", ret2);
|
|
ret = ERR_VI_NOT_SUPPORT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
struct osd_fmt stOsdFmt;
|
|
memset(&stOsdFmt, 0, sizeof(struct osd_fmt));
|
|
stOsdFmt.clipcount = 0;
|
|
stOsdFmt.bitmap[0] = NULL;
|
|
int ret1 = overlay_set_fmt(video, &stOsdFmt);
|
|
int ret2 = overlay_update(video, 1);
|
|
if(ret1 != 0)
|
|
{
|
|
aloge("fatal error! set cover fail[%d]", ret1);
|
|
ret = ERR_VI_NOT_SUPPORT;
|
|
}
|
|
if(ret2 != 0)
|
|
{
|
|
aloge("fatal error! cover update fail[%d]", ret2);
|
|
ret = ERR_VI_NOT_SUPPORT;
|
|
}
|
|
}
|
|
//draw overlay
|
|
BOOL bOverlayExist = FALSE;
|
|
OsdGroup *pEntryGroup;
|
|
list_for_each_entry(pEntryGroup, &pVipp->mpOsdGroups->mGroupList, mList)
|
|
{
|
|
if(!list_empty(&pEntryGroup->mRedrawOsdList))
|
|
{
|
|
OsdRegion *pFirstRegion = list_first_entry(&pEntryGroup->mRedrawOsdList, OsdRegion, mList);
|
|
if(OVERLAY_RGN == pFirstRegion->mType)
|
|
{
|
|
bOverlayExist = TRUE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! redrawOsdList must be overlay!");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!list_empty(&pEntryGroup->mOsdList))
|
|
{
|
|
OsdRegion *pFirstRegion = list_first_entry(&pEntryGroup->mOsdList, OsdRegion, mList);
|
|
if(OVERLAY_RGN == pFirstRegion->mType)
|
|
{
|
|
if(list_is_singular(&pEntryGroup->mOsdList))
|
|
{
|
|
bOverlayExist = TRUE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! when not redraw, overlay in OsdList must be single!");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! osdList in OsdGroup can't be empty!");
|
|
}
|
|
}
|
|
}
|
|
if(bOverlayExist)
|
|
{
|
|
BOOL bCountExceed = FALSE;
|
|
struct osd_fmt stOsdFmt;
|
|
memset(&stOsdFmt, 0, sizeof(struct osd_fmt));
|
|
stOsdFmt.chromakey = pVipp->mpOsdGroups->mPixFmt;
|
|
stOsdFmt.global_alpha = pVipp->mpOsdGroups->mGlobalAlpha; //MAX_GLOBAL_ALPHA
|
|
list_for_each_entry_from(pEntryGroup, &pVipp->mpOsdGroups->mGroupList, mList)
|
|
{
|
|
if(!list_empty(&pEntryGroup->mRedrawOsdList))
|
|
{
|
|
OsdRegion *pEntryRegion;
|
|
list_for_each_entry(pEntryRegion, &pEntryGroup->mRedrawOsdList, mList)
|
|
{
|
|
if(pEntryRegion->mType != OVERLAY_RGN)
|
|
{
|
|
aloge("fatal error! region type[0x%x] is not overlay!", pEntryRegion->mType);
|
|
}
|
|
if(NULL == pEntryRegion->mInfo.mOverlay.mBitmap)
|
|
{
|
|
aloge("fatal error! bmpData is not set");
|
|
}
|
|
stOsdFmt.reverse_close[stOsdFmt.clipcount] = pEntryRegion->mInfo.mOverlay.mbInvColEn?0:1;
|
|
stOsdFmt.bitmap[stOsdFmt.clipcount] = pEntryRegion->mInfo.mOverlay.mBitmap;
|
|
stOsdFmt.region[stOsdFmt.clipcount].left = pEntryRegion->mRect.X;
|
|
stOsdFmt.region[stOsdFmt.clipcount].top = pEntryRegion->mRect.Y;
|
|
stOsdFmt.region[stOsdFmt.clipcount].width = pEntryRegion->mRect.Width;
|
|
stOsdFmt.region[stOsdFmt.clipcount].height = pEntryRegion->mRect.Height;
|
|
stOsdFmt.clipcount++;
|
|
if(stOsdFmt.clipcount > MAX_OVERLAY_NUM)
|
|
{
|
|
aloge("fatal error! clipcount[%d] exceed!", stOsdFmt.clipcount);
|
|
bCountExceed = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if(bCountExceed)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(list_is_singular(&pEntryGroup->mOsdList))
|
|
{
|
|
OsdRegion *pEntryRegion = list_first_entry(&pEntryGroup->mOsdList, OsdRegion, mList);
|
|
if(pEntryRegion->mType != OVERLAY_RGN)
|
|
{
|
|
aloge("fatal error! region type[0x%x] is not overlay!", pEntryRegion->mType);
|
|
}
|
|
if(NULL == pEntryRegion->mInfo.mOverlay.mBitmap)
|
|
{
|
|
aloge("fatal error! bmpData is not set");
|
|
}
|
|
stOsdFmt.reverse_close[stOsdFmt.clipcount] = pEntryRegion->mInfo.mOverlay.mbInvColEn?0:1;
|
|
stOsdFmt.bitmap[stOsdFmt.clipcount] = pEntryRegion->mInfo.mOverlay.mBitmap;
|
|
stOsdFmt.region[stOsdFmt.clipcount].left = pEntryRegion->mRect.X;
|
|
stOsdFmt.region[stOsdFmt.clipcount].top = pEntryRegion->mRect.Y;
|
|
stOsdFmt.region[stOsdFmt.clipcount].width = pEntryRegion->mRect.Width;
|
|
stOsdFmt.region[stOsdFmt.clipcount].height = pEntryRegion->mRect.Height;
|
|
stOsdFmt.clipcount++;
|
|
if(stOsdFmt.clipcount > MAX_OVERLAY_NUM)
|
|
{
|
|
aloge("fatal error! clipcount[%d] exceed!", stOsdFmt.clipcount);
|
|
bCountExceed = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aloge("fatal error! This overlay group must be single!");
|
|
}
|
|
}
|
|
}
|
|
char bitmap[100];
|
|
if(0 == stOsdFmt.clipcount)
|
|
{
|
|
bitmap[0] = 'c';
|
|
stOsdFmt.bitmap[0] = &bitmap[0];
|
|
}
|
|
int ret1 = overlay_set_fmt(video, &stOsdFmt);
|
|
int ret2 = overlay_update(video, 1);
|
|
if(ret1 != 0)
|
|
{
|
|
aloge("fatal error! set overlay fail[%d]", ret1);
|
|
ret = ERR_VI_NOT_SUPPORT;
|
|
}
|
|
if(ret2 != 0)
|
|
{
|
|
aloge("fatal error! overlay update fail[%d]", ret2);
|
|
ret = ERR_VI_NOT_SUPPORT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
struct osd_fmt stOsdFmt;
|
|
memset(&stOsdFmt, 0, sizeof(struct osd_fmt));
|
|
char bitmap[100];
|
|
bitmap[0] = 'c';
|
|
stOsdFmt.clipcount = 0;
|
|
stOsdFmt.bitmap[0] = &bitmap[0];
|
|
int ret1 = overlay_set_fmt(video, &stOsdFmt);
|
|
int ret2 = overlay_update(video, 1);
|
|
if(ret1 != 0)
|
|
{
|
|
aloge("fatal error! set overlay fail[%d]", ret1);
|
|
ret = ERR_VI_NOT_SUPPORT;
|
|
}
|
|
if(ret2 != 0)
|
|
{
|
|
aloge("fatal error! overlay update fail[%d]", ret2);
|
|
ret = ERR_VI_NOT_SUPPORT;
|
|
}
|
|
}
|
|
//after draw, we can destroy OsdGroups
|
|
if(pVipp->mpOsdGroups)
|
|
{
|
|
OsdGroupsDestruct(pVipp->mpOsdGroups);
|
|
pVipp->mpOsdGroups = NULL;
|
|
}
|
|
return ret;
|
|
}
|
|
|