//#define LOG_NDEBUG 0 #define LOG_TAG "mpi_vo" #include //#include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "hwdisplay.h" #include #include //#include "..\..\middleware\include\media\mm_comm_vo.h" #include "mm_comm_vo.h" //#include "common/app_log.h" #include typedef struct VO_CHN_MAP_S { VO_LAYER mVoLayer; //video layer which video channel connect. VO_CHN mVoChn; // video output channel index, [0, VO_MAX_CHN_NUM), output to video layer. Our chip: one channel => one layer. MM_COMPONENTTYPE *mComp; // video render component instance cdx_sem_t mSemCompCmd; MPPCallbackInfo mCallbackInfo; struct list_head mList; }VO_CHN_MAP_S; typedef struct VOChnManager { struct list_head mList; //element type: VO_CHN_MAP_S pthread_mutex_t mLock; } VOChnManager; static VOChnManager *gpVOChnManager = NULL; static ERRORTYPE searchExistChannel_l(VO_LAYER VoLayer, VO_CHN VoChn, VO_CHN_MAP_S** ppChn) { ERRORTYPE ret = FAILURE; VO_CHN_MAP_S* pEntry; if (gpVOChnManager == NULL) { return FAILURE; } list_for_each_entry(pEntry, &gpVOChnManager->mList, mList) { if(pEntry->mVoChn == VoChn && pEntry->mVoLayer == VoLayer) { if(ppChn) { *ppChn = pEntry; } ret = SUCCESS; break; } } return ret; } static ERRORTYPE searchExistChannel(VO_LAYER VoLayer, VO_CHN VoChn, VO_CHN_MAP_S** ppChn) { ERRORTYPE ret = FAILURE; VO_CHN_MAP_S* pEntry; if (gpVOChnManager == NULL) { return FAILURE; } pthread_mutex_lock(&gpVOChnManager->mLock); ret = searchExistChannel_l(VoLayer, VoChn, ppChn); pthread_mutex_unlock(&gpVOChnManager->mLock); return ret; } static ERRORTYPE addChannel_l(VO_CHN_MAP_S *pChn) { if (gpVOChnManager == NULL) { return FAILURE; } list_add_tail(&pChn->mList, &gpVOChnManager->mList); return SUCCESS; } static ERRORTYPE addChannel(VO_CHN_MAP_S *pChn) { if (gpVOChnManager == NULL) { return FAILURE; } pthread_mutex_lock(&gpVOChnManager->mLock); ERRORTYPE ret = addChannel_l(pChn); pthread_mutex_unlock(&gpVOChnManager->mLock); return ret; } static ERRORTYPE removeChannel(VO_CHN_MAP_S *pChn) { if (gpVOChnManager == NULL) { return FAILURE; } pthread_mutex_lock(&gpVOChnManager->mLock); list_del(&pChn->mList); pthread_mutex_unlock(&gpVOChnManager->mLock); return SUCCESS; } static VO_CHN_MAP_S* VO_CHN_MAP_S_Construct() { VO_CHN_MAP_S *pChannel = (VO_CHN_MAP_S*)malloc(sizeof(VO_CHN_MAP_S)); if(NULL == pChannel) { aloge("fatal error! malloc fail[%s]!", strerror(errno)); return NULL; } memset(pChannel, 0, sizeof(VO_CHN_MAP_S)); cdx_sem_init(&pChannel->mSemCompCmd, 0); return pChannel; } static void VO_CHN_MAP_S_Destruct(VO_CHN_MAP_S *pChannel) { if(pChannel->mComp) { aloge("fatal error! VO component need free before!"); COMP_FreeHandle(pChannel->mComp); pChannel->mComp = NULL; } cdx_sem_deinit(&pChannel->mSemCompCmd); free(pChannel); } typedef struct VOLayerInfo { VO_LAYER mVoLayer; //video layer which has been enabled. VO_VIDEO_LAYER_ATTR_S mLayerAttr; unsigned int mPriority; //same to z-order VO_VIDEO_LAYER_ALPHA_S mAlpha; struct list_head mList; }VOLayerInfo; typedef struct VOLayerManager { struct list_head mVOLayerList; //element type: VOLayerInfo pthread_mutex_t mLock; } VOLayerManager; static VOLayerManager *gpVOLayerManager = NULL; static ERRORTYPE searchExistVOLayerInfo(VO_LAYER VoLayer, VOLayerInfo** ppVOLayerInfo) { ERRORTYPE ret = FAILURE; VOLayerInfo* pEntry; if (gpVOLayerManager == NULL) { return FAILURE; } pthread_mutex_lock(&gpVOLayerManager->mLock); list_for_each_entry(pEntry, &gpVOLayerManager->mVOLayerList, mList) { if(pEntry->mVoLayer == VoLayer) { if(ppVOLayerInfo) { *ppVOLayerInfo = pEntry; } ret = SUCCESS; break; } } pthread_mutex_unlock(&gpVOLayerManager->mLock); return ret; } static ERRORTYPE addVOLayerInfo(VOLayerInfo *pVOLayerInfo) { if (gpVOLayerManager == NULL) { return FAILURE; } pthread_mutex_lock(&gpVOLayerManager->mLock); list_add_tail(&pVOLayerInfo->mList, &gpVOLayerManager->mVOLayerList); pthread_mutex_unlock(&gpVOLayerManager->mLock); return SUCCESS; } static ERRORTYPE removeVOLayerInfo(VOLayerInfo *pVOLayerInfo) { if (gpVOLayerManager == NULL) { return FAILURE; } pthread_mutex_lock(&gpVOLayerManager->mLock); list_del(&pVOLayerInfo->mList); pthread_mutex_unlock(&gpVOLayerManager->mLock); return SUCCESS; } static VOLayerInfo* VOLayerInfo_Construct() { VOLayerInfo *pVOLayerInfo = (VOLayerInfo*)malloc(sizeof(VOLayerInfo)); if(NULL == pVOLayerInfo) { aloge("fatal error! malloc fail[%s]!", strerror(errno)); return NULL; } memset(pVOLayerInfo, 0, sizeof(VOLayerInfo)); return pVOLayerInfo; } static void VOLayerInfo_Destruct(VOLayerInfo *pVOLayerInfo) { free(pVOLayerInfo); } typedef struct VODevInfo { VO_DEV mVoDev; VO_PUB_ATTR_S mVoPubAttr; struct list_head mList; } VODevInfo; typedef struct VODevManager { struct list_head mVODevList; //element type: VODevInfo pthread_mutex_t mLock; } VODevManager; static VODevManager *gpVODevManager = NULL; static ERRORTYPE searchExistVODevInfo(VO_DEV VoDev, VODevInfo** ppVODevInfo) { ERRORTYPE ret = FAILURE; VODevInfo* pEntry; if (gpVODevManager == NULL) { return FAILURE; } pthread_mutex_lock(&gpVODevManager->mLock); list_for_each_entry(pEntry, &gpVODevManager->mVODevList, mList) { if(pEntry->mVoDev == VoDev) { if(ppVODevInfo) { *ppVODevInfo = pEntry; } ret = SUCCESS; break; } } pthread_mutex_unlock(&gpVODevManager->mLock); return ret; } static ERRORTYPE addVODevInfo(VODevInfo *pVODevInfo) { if (gpVODevManager == NULL) { return FAILURE; } pthread_mutex_lock(&gpVODevManager->mLock); list_add_tail(&pVODevInfo->mList, &gpVODevManager->mVODevList); pthread_mutex_unlock(&gpVODevManager->mLock); return SUCCESS; } static ERRORTYPE removeVODevInfo(VODevInfo *pVODevInfo) { if (gpVODevManager == NULL) { return FAILURE; } pthread_mutex_lock(&gpVODevManager->mLock); list_del(&pVODevInfo->mList); pthread_mutex_unlock(&gpVODevManager->mLock); return SUCCESS; } static VODevInfo* VODevInfo_Construct() { VODevInfo *pVODevInfo = (VODevInfo*)malloc(sizeof(VODevInfo)); if(NULL == pVODevInfo) { aloge("fatal error! malloc fail[%s]!", strerror(errno)); return NULL; } memset(pVODevInfo, 0, sizeof(VODevInfo)); return pVODevInfo; } static void VODevInfo_Destruct(VODevInfo *pVODevInfo) { free(pVODevInfo); } ERRORTYPE VO_Construct(void) { ERRORTYPE eError = SUCCESS; int ret; if (gpVODevManager != NULL) { alogd("already construct vo"); return SUCCESS; } gpVODevManager = (VODevManager*)malloc(sizeof(VODevManager)); if (NULL == gpVODevManager) { aloge("alloc VODevManager error(%s)!", strerror(errno)); return FAILURE; } ret = pthread_mutex_init(&gpVODevManager->mLock, NULL); if (ret != 0) { aloge("fatal error! mutex init fail"); } INIT_LIST_HEAD(&gpVODevManager->mVODevList); gpVOLayerManager = (VOLayerManager*)malloc(sizeof(VOLayerManager)); if (NULL == gpVOLayerManager) { aloge("alloc VOLayerManager error(%s)!", strerror(errno)); eError = ERR_VO_NO_MEM; goto VOLayer_fail; } ret = pthread_mutex_init(&gpVOLayerManager->mLock, NULL); if (ret != 0) { aloge("fatal error! mutex init fail"); } INIT_LIST_HEAD(&gpVOLayerManager->mVOLayerList); gpVOChnManager = (VOChnManager*)malloc(sizeof(VOChnManager)); if (NULL == gpVOChnManager) { aloge("alloc VOChnManager error(%s)!", strerror(errno)); eError = ERR_VO_NO_MEM; goto VOChn_fail; } ret = pthread_mutex_init(&gpVOChnManager->mLock, NULL); if (ret != 0) { aloge("fatal error! mutex init fail"); } INIT_LIST_HEAD(&gpVOChnManager->mList); if(hw_display_init()!=0) { aloge("fatal error! hw display init fail!"); eError = ERR_VO_SYS_NOTREADY; goto hw_display_init_fail; } return SUCCESS; hw_display_init_fail: pthread_mutex_destroy(&gpVOChnManager->mLock); free(gpVOChnManager); gpVOChnManager = NULL; VOChn_fail: pthread_mutex_destroy(&gpVOLayerManager->mLock); free(gpVOLayerManager); gpVOLayerManager = NULL; VOLayer_fail: pthread_mutex_destroy(&gpVODevManager->mLock); free(gpVODevManager); gpVODevManager = NULL; return eError; } ERRORTYPE VO_Destruct(void) { if(NULL == gpVODevManager) { alogd("already destruct vo"); return SUCCESS; } if (gpVOChnManager != NULL) { if (!list_empty(&gpVOChnManager->mList)) { aloge("fatal error! some vo channel still running when destroy vo device!"); } pthread_mutex_destroy(&gpVOChnManager->mLock); free(gpVOChnManager); gpVOChnManager = NULL; } if (gpVOLayerManager != NULL) { if (!list_empty(&gpVOLayerManager->mVOLayerList)) { aloge("fatal error! some vo layer still running when disable vo!"); VOLayerInfo *pEntry; list_for_each_entry(pEntry, &gpVOLayerManager->mVOLayerList, mList) { alogd("VOLayerInfo: layerId[%d], dispRect[%d,%d,%d,%d], Priority[%d], alphaMode[%d], alphaValue[%d]", pEntry->mVoLayer, pEntry->mLayerAttr.stDispRect.X, pEntry->mLayerAttr.stDispRect.Y, pEntry->mLayerAttr.stDispRect.Width, pEntry->mLayerAttr.stDispRect.Height, pEntry->mPriority, pEntry->mAlpha.mAlphaMode, pEntry->mAlpha.mAlphaValue); } } pthread_mutex_destroy(&gpVOLayerManager->mLock); free(gpVOLayerManager); gpVOLayerManager = NULL; } if (gpVODevManager != NULL) { if (!list_empty(&gpVODevManager->mVODevList)) { aloge("fatal error! some vo dev still running when disable vo!"); } pthread_mutex_destroy(&gpVODevManager->mLock); free(gpVODevManager); gpVODevManager = NULL; } hw_display_deinit(); return SUCCESS; } MM_COMPONENTTYPE *VO_GetChnComp(MPP_CHN_S *pMppChn) { VO_CHN_MAP_S* pChn; if (searchExistChannel(pMppChn->mDevId, pMppChn->mChnId, &pChn) != SUCCESS) { return NULL; } return pChn->mComp; } static ERRORTYPE VideoRenderEventHandler( PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN void* pAppData, PARAM_IN COMP_EVENTTYPE eEvent, PARAM_IN unsigned int nData1, PARAM_IN unsigned int nData2, PARAM_IN void* pEventData) { ERRORTYPE ret; // MPP_CHN_S VOChnInfo; // ret = COMP_GetConfig(hComponent, COMP_IndexVendorMPPChannelInfo, &VOChnInfo); // if(ret == SUCCESS) // { // alogv("video render event, MppChannel[%d][%d][%d]", VOChnInfo.mModId, VOChnInfo.mDevId, VOChnInfo.mChnId); // } VO_CHN_MAP_S *pChn = (VO_CHN_MAP_S*)pAppData; switch(eEvent) { case COMP_EventCmdComplete: { if(COMP_CommandStateSet == nData1) { alogv("vo EventCmdComplete, current StateSet[%d]", nData2); cdx_sem_up(&pChn->mSemCompCmd); break; } else if(COMP_CommandVendorChangeANativeWindow == nData1) { alogd("change video layer?"); break; } else { alogw("Low probability! what command[0x%x]?", nData1); break; } } case COMP_EventError: { if(ERR_VO_CHN_SAMESTATE == nData1) { alogv("set same state to vo!"); cdx_sem_up(&pChn->mSemCompCmd); break; } else if(ERR_VO_CHN_INVALIDSTATE == nData1) { aloge("why vo state turn to invalid?"); break; } else if(ERR_VO_CHN_INCORRECT_STATE_TRANSITION == nData1) { aloge("fatal error! vo state transition incorrect."); break; } else { aloge("fatal error! unknown error[0x%x]!", nData1); break; } } case COMP_EventBufferFlag: { MPP_CHN_S ChannelInfo; ChannelInfo.mModId = MOD_ID_VOU; ChannelInfo.mDevId = pChn->mVoLayer; ChannelInfo.mChnId = pChn->mVoChn; CHECK_MPP_CALLBACK(pChn->mCallbackInfo.callback); pChn->mCallbackInfo.callback(pChn->mCallbackInfo.cookie, &ChannelInfo, MPP_EVENT_NOTIFY_EOF, NULL); break; } case COMP_EventKeyFrameDecoded: { alogd("KeyFrameDecoded, pts[%lld]us", *(int64_t*)pEventData); break; } case COMP_EventVideoDisplaySize: { MPP_CHN_S ChannelInfo; ChannelInfo.mModId = MOD_ID_VOU; ChannelInfo.mDevId = pChn->mVoLayer; ChannelInfo.mChnId = pChn->mVoChn; SIZE_S displaySize; displaySize.Width = nData1; displaySize.Height = nData2; CHECK_MPP_CALLBACK(pChn->mCallbackInfo.callback); pChn->mCallbackInfo.callback(pChn->mCallbackInfo.cookie, &ChannelInfo, MPP_EVENT_SET_VIDEO_SIZE, &displaySize); break; } case COMP_EventRenderingStart: { MPP_CHN_S ChannelInfo; ChannelInfo.mModId = MOD_ID_VOU; ChannelInfo.mDevId = pChn->mVoLayer; ChannelInfo.mChnId = pChn->mVoChn; CHECK_MPP_CALLBACK(pChn->mCallbackInfo.callback); pChn->mCallbackInfo.callback(pChn->mCallbackInfo.cookie, &ChannelInfo, MPP_EVENT_RENDERING_START, NULL); break; } default: aloge("fatal error! unknown event[0x%x]", eEvent); break; } return SUCCESS; } static ERRORTYPE VideoRenderEmptyBufferDone( PARAM_IN COMP_HANDLETYPE hComponent, PARAM_IN void* pAppData, PARAM_IN COMP_BUFFERHEADERTYPE* pBuffer) { VO_CHN_MAP_S *pChn = (VO_CHN_MAP_S*)pAppData; VIDEO_FRAME_INFO_S *pFrameInfo = (VIDEO_FRAME_INFO_S*)pBuffer->pAppPrivate; MPP_CHN_S ChannelInfo; ChannelInfo.mModId = MOD_ID_VOU; ChannelInfo.mDevId = pChn->mVoLayer; ChannelInfo.mChnId = pChn->mVoChn; CHECK_MPP_CALLBACK(pChn->mCallbackInfo.callback); pChn->mCallbackInfo.callback(pChn->mCallbackInfo.cookie, &ChannelInfo, MPP_EVENT_RELEASE_VIDEO_BUFFER, (void*)pFrameInfo); return SUCCESS; } COMP_CALLBACKTYPE VideoRenderCallback = { .EventHandler = VideoRenderEventHandler, .EmptyBufferDone = VideoRenderEmptyBufferDone, .FillBufferDone = NULL, }; VO_INTF_TYPE_E map_disp_output_type_to_VO_INTF_TYPE_E(disp_output_type disp_type) { VO_INTF_TYPE_E eIntfType = 0; if(disp_type&DISP_OUTPUT_TYPE_LCD) { eIntfType |= VO_INTF_LCD; } if(disp_type&DISP_OUTPUT_TYPE_TV) { eIntfType |= VO_INTF_CVBS; } if(disp_type&DISP_OUTPUT_TYPE_HDMI) { eIntfType |= VO_INTF_HDMI; } if(disp_type&DISP_OUTPUT_TYPE_VGA) { eIntfType |= VO_INTF_VGA; } // if(DISP_OUTPUT_TYPE_NONE == disp_type) // { // eIntfType |= VO_INTF_LCD; // } return eIntfType; } disp_output_type map_VO_INTF_TYPE_E_to_disp_output_type(VO_INTF_TYPE_E eIntfType) { disp_output_type disp_type = 0; if(eIntfType&VO_INTF_LCD) { disp_type |= DISP_OUTPUT_TYPE_LCD; } if(eIntfType&VO_INTF_CVBS) { disp_type |= DISP_OUTPUT_TYPE_TV; } if(eIntfType&VO_INTF_HDMI) { disp_type |= DISP_OUTPUT_TYPE_HDMI; } if(eIntfType&VO_INTF_VGA) { disp_type |= DISP_OUTPUT_TYPE_VGA; } if(0 == eIntfType) { alogw("be careful! unknown intf_type:0x%x, return disp_output_type:0x%x", eIntfType, disp_type); } return disp_type; } VO_INTF_SYNC_E map_disp_tv_mode_to_VO_INTF_SYNC_E(disp_tv_mode tv_mode) { VO_INTF_SYNC_E eIntfSync; switch(tv_mode) { case DISP_TV_MOD_720P_50HZ: eIntfSync = VO_OUTPUT_720P50; break; case DISP_TV_MOD_720P_60HZ: eIntfSync = VO_OUTPUT_720P60; break; case DISP_TV_MOD_1080I_50HZ: eIntfSync = VO_OUTPUT_1080I50; break; case DISP_TV_MOD_1080I_60HZ: eIntfSync = VO_OUTPUT_1080I60; break; case DISP_TV_MOD_1080P_24HZ: eIntfSync = VO_OUTPUT_1080P24; break; case DISP_TV_MOD_1080P_50HZ: eIntfSync = VO_OUTPUT_1080P50; break; case DISP_TV_MOD_1080P_60HZ: eIntfSync = VO_OUTPUT_1080P60; break; case DISP_TV_MOD_1080P_25HZ: eIntfSync = VO_OUTPUT_1080P25; break; case DISP_TV_MOD_1080P_30HZ: eIntfSync = VO_OUTPUT_1080P30; break; case DISP_TV_MOD_576I: eIntfSync = VO_OUTPUT_PAL; break; case DISP_TV_MOD_480I: eIntfSync = VO_OUTPUT_NTSC; break; case DISP_TV_MOD_3840_2160P_30HZ: eIntfSync = VO_OUTPUT_3840x2160_30; break; case DISP_TV_MOD_3840_2160P_25HZ: eIntfSync = VO_OUTPUT_3840x2160_25; break; case DISP_TV_MOD_3840_2160P_24HZ: eIntfSync = VO_OUTPUT_3840x2160_24; break; case DISP_TV_MOD_480P: case DISP_TV_MOD_576P: case DISP_TV_MOD_1080P_24HZ_3D_FP: case DISP_TV_MOD_720P_50HZ_3D_FP: case DISP_TV_MOD_720P_60HZ_3D_FP: case DISP_TV_MOD_PAL_SVIDEO: case DISP_TV_MOD_NTSC_SVIDEO: case DISP_TV_MOD_PAL_M: case DISP_TV_MOD_PAL_M_SVIDEO: case DISP_TV_MOD_PAL_NC: case DISP_TV_MOD_PAL_NC_SVIDEO: default: aloge("fatal error! Unknown tv_mode 0x%x", tv_mode); eIntfSync = VO_OUTPUT_BUTT; break; } return eIntfSync; } disp_tv_mode map_VO_INTF_SYNC_E_to_disp_tv_mode(VO_INTF_SYNC_E eIntfSync) { disp_tv_mode tv_mode; switch(eIntfSync) { case VO_OUTPUT_PAL: tv_mode = DISP_TV_MOD_576I; break; case VO_OUTPUT_NTSC: tv_mode = DISP_TV_MOD_480I; break; case VO_OUTPUT_1080P24: tv_mode = DISP_TV_MOD_1080P_24HZ; break; case VO_OUTPUT_1080P25: tv_mode = DISP_TV_MOD_1080P_25HZ; break; case VO_OUTPUT_1080P30: tv_mode = DISP_TV_MOD_1080P_30HZ; break; case VO_OUTPUT_720P50: tv_mode = DISP_TV_MOD_720P_50HZ; break; case VO_OUTPUT_720P60: tv_mode = DISP_TV_MOD_720P_60HZ; break; case VO_OUTPUT_1080I50: tv_mode = DISP_TV_MOD_1080I_50HZ; break; case VO_OUTPUT_1080I60: tv_mode = DISP_TV_MOD_1080I_60HZ; break; case VO_OUTPUT_1080P50: tv_mode = DISP_TV_MOD_1080P_50HZ; break; case VO_OUTPUT_1080P60: tv_mode = DISP_TV_MOD_1080P_60HZ; break; case VO_OUTPUT_3840x2160_24: tv_mode = DISP_TV_MOD_3840_2160P_24HZ; break; case VO_OUTPUT_3840x2160_25: tv_mode = DISP_TV_MOD_3840_2160P_25HZ; break; case VO_OUTPUT_3840x2160_30: tv_mode = DISP_TV_MOD_3840_2160P_30HZ; break; case VO_OUTPUT_576P50: case VO_OUTPUT_480P60: case VO_OUTPUT_800x600_60: case VO_OUTPUT_1024x768_60: case VO_OUTPUT_1280x1024_60: case VO_OUTPUT_1366x768_60: case VO_OUTPUT_1440x900_60: case VO_OUTPUT_1280x800_60: case VO_OUTPUT_1600x1200_60: case VO_OUTPUT_1680x1050_60: case VO_OUTPUT_1920x1200_60: case VO_OUTPUT_640x480_60: case VO_OUTPUT_960H_PAL: case VO_OUTPUT_960H_NTSC: case VO_OUTPUT_320X240_30: case VO_OUTPUT_320X240_50: case VO_OUTPUT_240X320_50: case VO_OUTPUT_240X320_60: default: aloge("fatal error! Unknown vo interface sync 0x%x", eIntfSync); tv_mode = DISP_TV_MOD_576I; break; } return tv_mode; } ERRORTYPE AW_MPI_VO_Enable(VO_DEV VoDev) { ERRORTYPE eError = SUCCESS; int ret; if (NULL == gpVODevManager) { aloge("fatal error! VODevManager is not init!"); return ERR_VO_SYS_NOTREADY; } if(SUCCESS == searchExistVODevInfo(VoDev, NULL)) { return ERR_VO_DEV_HAS_ENABLED; } VODevInfo *pVODevInfo = VODevInfo_Construct(); pVODevInfo->mVoDev = VoDev; disp_output_type disp_type; disp_tv_mode tv_mode; if(0 == hwd_get_disp_type((int*)&disp_type, (int*)&tv_mode)) { pVODevInfo->mVoPubAttr.enIntfType = map_disp_output_type_to_VO_INTF_TYPE_E(disp_type); pVODevInfo->mVoPubAttr.enIntfSync = map_disp_tv_mode_to_VO_INTF_SYNC_E(tv_mode); } else { aloge("fatal error! get disp type fail!"); eError = ERR_VO_NOT_SUPPORT; goto get_disp_type_fail; } addVODevInfo(pVODevInfo); return eError; get_disp_type_fail: VODevInfo_Destruct(pVODevInfo); pVODevInfo = NULL; return eError; } ERRORTYPE AW_MPI_VO_Disable(VO_DEV VoDev) { ERRORTYPE eError = SUCCESS; VODevInfo *pVODevInfo = NULL; if(SUCCESS != searchExistVODevInfo(VoDev, &pVODevInfo)) { return ERR_VO_DEV_NOT_ENABLE; } removeVODevInfo(pVODevInfo); VODevInfo_Destruct(pVODevInfo); return eError; } ERRORTYPE AW_MPI_VO_SetPubAttr(VO_DEV VoDev, const VO_PUB_ATTR_S *pstPubAttr) { ERRORTYPE eError = SUCCESS; VODevInfo *pVODevInfo = NULL; if(SUCCESS != searchExistVODevInfo(VoDev, &pVODevInfo)) { return ERR_VO_DEV_NOT_ENABLE; } BOOL bUpdateFlag = FALSE; VO_PUB_ATTR_S *pCurPubAttr = &pVODevInfo->mVoPubAttr; if(pCurPubAttr->enIntfType != pstPubAttr->enIntfType) { bUpdateFlag = TRUE; } else { if(pCurPubAttr->enIntfType & VO_INTF_LCD) { bUpdateFlag = FALSE; } else if(pCurPubAttr->enIntfSync != pstPubAttr->enIntfSync) { bUpdateFlag = TRUE; } else { bUpdateFlag = FALSE; } } if(bUpdateFlag) { alogd("vo interface changed, [0x%x, 0x%x]->[0x%x, 0x%x]", pCurPubAttr->enIntfType, pCurPubAttr->enIntfSync, pstPubAttr->enIntfType, pstPubAttr->enIntfSync); disp_output_type disp_type = map_VO_INTF_TYPE_E_to_disp_output_type(pstPubAttr->enIntfType); disp_tv_mode tv_mode = map_VO_INTF_SYNC_E_to_disp_tv_mode(pstPubAttr->enIntfSync); int ret = hwd_switch_vo_device(disp_type, tv_mode); if(0 == ret) { *pCurPubAttr = *pstPubAttr; } else { aloge("fatal error! hwd switch_vo_device error! ret:%d", ret); eError = ERR_VO_NOT_SUPPORT; } } return eError; } ERRORTYPE AW_MPI_VO_GetPubAttr(VO_DEV VoDev, VO_PUB_ATTR_S *pstPubAttr) { ERRORTYPE eError = SUCCESS; VODevInfo *pVODevInfo = NULL; if(SUCCESS != searchExistVODevInfo(VoDev, &pVODevInfo)) { return ERR_VO_DEV_NOT_ENABLE; } *pstPubAttr = pVODevInfo->mVoPubAttr; return eError; } ERRORTYPE AW_MPI_VO_GetHdmiHwMode(VO_DEV VoDev, VO_INTF_SYNC_E *mode) { ERRORTYPE eError = SUCCESS; VODevInfo *pVODevInfo = NULL; if(SUCCESS != searchExistVODevInfo(VoDev, &pVODevInfo)) { return ERR_VO_DEV_NOT_ENABLE; } disp_tv_mode disp_mode; eError = hwd_get_hdmi_hw_mode(&disp_mode); if (eError == -1) { aloge("there has no hdmi device!!\n"); return ERR_VO_DEV_NOT_CONFIG; } else if (eError == 1) { aloge("there has no supported display mode for this hdmi device!!\n"); return ERR_VO_NOT_SUPPORT; } else if (eError == SUCCESS) { *mode = map_disp_tv_mode_to_VO_INTF_SYNC_E(disp_mode); } return SUCCESS; } ERRORTYPE AW_MPI_VO_EnableVideoLayer(VO_LAYER VoLayer) { ERRORTYPE eError = SUCCESS; if(SUCCESS == searchExistVOLayerInfo(VoLayer, NULL)) { return ERR_VO_VIDEO_NOT_DISABLE; } int ret = hwd_layer_request_hlay(VoLayer); if(0 == ret) { VOLayerInfo *pVOLayerInfo = VOLayerInfo_Construct(); pVOLayerInfo->mVoLayer = VoLayer; disp_layer_config config; memset(&config, 0, sizeof(disp_layer_config)); config.channel = HD2CHN(VoLayer); config.layer_id = HD2LYL(VoLayer); layer_get_para(&config); pVOLayerInfo->mLayerAttr.stDispRect.X = config.info.screen_win.x; pVOLayerInfo->mLayerAttr.stDispRect.Y = config.info.screen_win.y; pVOLayerInfo->mLayerAttr.stDispRect.Width = config.info.screen_win.width; pVOLayerInfo->mLayerAttr.stDispRect.Height = config.info.screen_win.height; pVOLayerInfo->mPriority = config.info.zorder; pVOLayerInfo->mAlpha.mAlphaMode = config.info.alpha_mode; pVOLayerInfo->mAlpha.mAlphaValue = config.info.alpha_value; addVOLayerInfo(pVOLayerInfo); } else { aloge("fatal error! why request hlay[%d] fail?", VoLayer); eError = ERR_VO_DEV_NOT_ENABLE; } return eError; } ERRORTYPE AW_MPI_VO_DisableVideoLayer(VO_LAYER VoLayer) { ERRORTYPE eError = SUCCESS; VOLayerInfo *pVOLayerInfo = NULL; if(SUCCESS != searchExistVOLayerInfo(VoLayer, &pVOLayerInfo)) { return ERR_VO_VIDEO_NOT_ENABLE; } int ret = hwd_layer_release(VoLayer); if(0 == ret) { removeVOLayerInfo(pVOLayerInfo); VOLayerInfo_Destruct(pVOLayerInfo); } else { eError = ERR_VO_BUSY; } return eError; } ERRORTYPE AW_MPI_VO_AddOutsideVideoLayer(VO_LAYER VoLayer) { ERRORTYPE eError = SUCCESS; if(SUCCESS == searchExistVOLayerInfo(VoLayer, NULL)) { return ERR_VO_VIDEO_NOT_DISABLE; } VOLayerInfo *pVOLayerInfo = VOLayerInfo_Construct(); pVOLayerInfo->mVoLayer = VoLayer; disp_layer_config config; memset(&config, 0, sizeof(disp_layer_config)); config.channel = HD2CHN(VoLayer); config.layer_id = HD2LYL(VoLayer); int getParaRet = layer_get_para(&config); if(RET_OK == getParaRet) { pVOLayerInfo->mLayerAttr.stDispRect.X = config.info.screen_win.x; pVOLayerInfo->mLayerAttr.stDispRect.Y = config.info.screen_win.y; pVOLayerInfo->mLayerAttr.stDispRect.Width = config.info.screen_win.width; pVOLayerInfo->mLayerAttr.stDispRect.Height = config.info.screen_win.height; pVOLayerInfo->mPriority = config.info.zorder; pVOLayerInfo->mAlpha.mAlphaMode = config.info.alpha_mode; pVOLayerInfo->mAlpha.mAlphaValue = config.info.alpha_value; } else { alogd("fatal error! why hlay[%d] is not request?", VoLayer); } addVOLayerInfo(pVOLayerInfo); return eError; } ERRORTYPE AW_MPI_VO_RemoveOutsideVideoLayer(VO_LAYER VoLayer) { ERRORTYPE eError = SUCCESS; VOLayerInfo *pVOLayerInfo = NULL; if(SUCCESS != searchExistVOLayerInfo(VoLayer, &pVOLayerInfo)) { return ERR_VO_VIDEO_NOT_ENABLE; } removeVOLayerInfo(pVOLayerInfo); VOLayerInfo_Destruct(pVOLayerInfo); return eError; } ERRORTYPE AW_MPI_VO_OpenVideoLayer (VO_LAYER VoLayer) { ERRORTYPE eError = SUCCESS; VOLayerInfo *pVOLayerInfo = NULL; if(SUCCESS != searchExistVOLayerInfo(VoLayer, &pVOLayerInfo)) { return ERR_VO_VIDEO_NOT_ENABLE; } int ret = hwd_layer_open(VoLayer); if(ret != RET_OK) { eError = ERR_VO_NOT_SUPPORT; } return eError; } ERRORTYPE AW_MPI_VO_CloseVideoLayer(VO_LAYER VoLayer) { ERRORTYPE eError = SUCCESS; VOLayerInfo *pVOLayerInfo = NULL; if(SUCCESS != searchExistVOLayerInfo(VoLayer, &pVOLayerInfo)) { return ERR_VO_VIDEO_NOT_ENABLE; } int ret = hwd_layer_close(VoLayer); if(ret != RET_OK) { eError = ERR_VO_NOT_SUPPORT; } return eError; } ERRORTYPE AW_MPI_VO_SetVideoLayerAttr(VO_LAYER VoLayer, const VO_VIDEO_LAYER_ATTR_S *pstLayerAttr) { ERRORTYPE eError = SUCCESS; VOLayerInfo *pVOLayerInfo = NULL; if(SUCCESS != searchExistVOLayerInfo(VoLayer, &pVOLayerInfo)) { return ERR_VO_VIDEO_NOT_ENABLE; } VO_VIDEO_LAYER_ATTR_S *pCurAttr = &pVOLayerInfo->mLayerAttr; if(pCurAttr->stDispRect.X != pstLayerAttr->stDispRect.X || pCurAttr->stDispRect.Y != pstLayerAttr->stDispRect.Y || pCurAttr->stDispRect.Width != pstLayerAttr->stDispRect.Width || pCurAttr->stDispRect.Height != pstLayerAttr->stDispRect.Height) { int channel = HD2CHN(VoLayer); int layer_id = HD2LYL(VoLayer); alogd("ch[%d]lyl[%d]:dispRect changed, [%d, %d, %dx%d]->[%d, %d, %dx%d]", channel, layer_id, pCurAttr->stDispRect.X, pCurAttr->stDispRect.Y, pCurAttr->stDispRect.Width, pCurAttr->stDispRect.Height, pstLayerAttr->stDispRect.X, pstLayerAttr->stDispRect.Y, pstLayerAttr->stDispRect.Width, pstLayerAttr->stDispRect.Height); struct view_info dispRect; dispRect.x = pstLayerAttr->stDispRect.X; dispRect.y = pstLayerAttr->stDispRect.Y; dispRect.w = pstLayerAttr->stDispRect.Width; dispRect.h = pstLayerAttr->stDispRect.Height; int ret = hwd_layer_set_rect(VoLayer, &dispRect); if(RET_OK == ret) { pCurAttr->stDispRect = pstLayerAttr->stDispRect; } else { eError = ERR_VO_NOT_SUPPORT; } } return eError; } ERRORTYPE AW_MPI_VO_GetVideoLayerAttr(VO_LAYER VoLayer, VO_VIDEO_LAYER_ATTR_S *pstLayerAttr) { ERRORTYPE eError = SUCCESS; VOLayerInfo *pVOLayerInfo = NULL; if(SUCCESS != searchExistVOLayerInfo(VoLayer, &pVOLayerInfo)) { return ERR_VO_VIDEO_NOT_ENABLE; } *pstLayerAttr = pVOLayerInfo->mLayerAttr; return eError; } ERRORTYPE AW_MPI_VO_SetVideoLayerPriority(VO_LAYER VoLayer, unsigned int uPriority) { ERRORTYPE eError = SUCCESS; VOLayerInfo *pVOLayerInfo = NULL; if(uPriority ZORDER_MAX) { alogw("video layer priority[%d] is invalid, valid scope[%d, %d]", uPriority, ZORDER_MIN, ZORDER_MAX); return ERR_VO_ILLEGAL_PARAM; } if(SUCCESS != searchExistVOLayerInfo(VoLayer, &pVOLayerInfo)) { return ERR_VO_VIDEO_NOT_ENABLE; } pthread_mutex_lock(&gpVOLayerManager->mLock); if(pVOLayerInfo->mPriority != uPriority) { alogd("layer[%d] priority changed [%d]->[%d]", pVOLayerInfo->mVoLayer, pVOLayerInfo->mPriority, uPriority); VOLayerInfo* pEntry; BOOL bFindFlag = FALSE; list_for_each_entry(pEntry, &gpVOLayerManager->mVOLayerList, mList) { if(pEntry->mPriority == uPriority) { alogd("layer[%d] take priority[%d], need exchange", pEntry->mVoLayer, uPriority); bFindFlag = TRUE; break; } } if(bFindFlag) { hwd_layer_exchange_zorder(pVOLayerInfo->mVoLayer, pEntry->mVoLayer); unsigned int tmp = pEntry->mPriority; pEntry->mPriority = pVOLayerInfo->mPriority; pVOLayerInfo->mPriority = tmp; } else { hwd_layer_set_zorder(pVOLayerInfo->mVoLayer, uPriority); pVOLayerInfo->mPriority = uPriority; } } pthread_mutex_unlock(&gpVOLayerManager->mLock); return eError; } ERRORTYPE AW_MPI_VO_GetVideoLayerPriority(VO_LAYER VoLayer, unsigned int *puPriority) { ERRORTYPE eError = SUCCESS; VOLayerInfo *pVOLayerInfo = NULL; if(SUCCESS != searchExistVOLayerInfo(VoLayer, &pVOLayerInfo)) { return ERR_VO_VIDEO_NOT_ENABLE; } *puPriority = pVOLayerInfo->mPriority; return eError; } ERRORTYPE AW_MPI_VO_SetVideoLayerAlpha(VO_LAYER VoLayer, VO_VIDEO_LAYER_ALPHA_S *pAlpha) { ERRORTYPE eError = SUCCESS; VOLayerInfo *pVOLayerInfo = NULL; if(SUCCESS != searchExistVOLayerInfo(VoLayer, &pVOLayerInfo)) { return ERR_VO_VIDEO_NOT_ENABLE; } VO_VIDEO_LAYER_ALPHA_S *pCurAlpha = &pVOLayerInfo->mAlpha; if(pCurAlpha->mAlphaMode!=pAlpha->mAlphaMode || pCurAlpha->mAlphaValue!=pAlpha->mAlphaValue) { alogd("video layer alpha changed, [%d, %d]->[%d, %d]", pCurAlpha->mAlphaMode, pCurAlpha->mAlphaValue, pAlpha->mAlphaMode, pAlpha->mAlphaValue); disp_layer_config config; memset(&config, 0, sizeof(disp_layer_config)); config.channel = HD2CHN(VoLayer); config.layer_id = HD2LYL(VoLayer); layer_get_para(&config); config.info.alpha_mode = pAlpha->mAlphaMode; config.info.alpha_value = pAlpha->mAlphaValue; int ret = layer_set_para(&config); if(RET_OK == ret) { *pCurAlpha = *pAlpha; } else { eError = ERR_VO_NOT_SUPPORT; } } return eError; } ERRORTYPE AW_MPI_VO_GetVideoLayerAlpha(VO_LAYER VoLayer, VO_VIDEO_LAYER_ALPHA_S *pAlpha) { ERRORTYPE eError = SUCCESS; VOLayerInfo *pVOLayerInfo = NULL; if(SUCCESS != searchExistVOLayerInfo(VoLayer, &pVOLayerInfo)) { return ERR_VO_VIDEO_NOT_ENABLE; } *pAlpha = pVOLayerInfo->mAlpha; return eError; } ERRORTYPE AW_MPI_VO_CreateChn(VO_LAYER VoLayer, VO_CHN VoChn) { if(!(VoChn>=0 && VoChnmLock); if(SUCCESS == searchExistChannel_l(VoLayer, VoChn, NULL)) { pthread_mutex_unlock(&gpVOChnManager->mLock); return ERR_VO_CHN_NOT_DISABLE; } VO_CHN_MAP_S *pNode = VO_CHN_MAP_S_Construct(); pNode->mVoLayer = VoLayer; pNode->mVoChn = VoChn; //create Venc Component here... ERRORTYPE eRet = SUCCESS; eRet = COMP_GetHandle((COMP_HANDLETYPE*)&pNode->mComp, CDX_ComponentNameVideoRender, (void*)pNode, &VideoRenderCallback); if(eRet != SUCCESS) { aloge("fatal error! get comp handle fail!"); } MPP_CHN_S ChannelInfo; ChannelInfo.mModId = MOD_ID_VOU; ChannelInfo.mDevId = pNode->mVoLayer; ChannelInfo.mChnId = pNode->mVoChn; eRet = pNode->mComp->SetConfig(pNode->mComp, COMP_IndexVendorMPPChannelInfo, (void*)&ChannelInfo); eRet = pNode->mComp->SetConfig(pNode->mComp, COMP_IndexVendorInitInstance, NULL); char avSyncFlag = 1; eRet = pNode->mComp->SetConfig(pNode->mComp, COMP_IndexVendorSetAVSync, &avSyncFlag); eRet = pNode->mComp->SendCommand(pNode->mComp, COMP_CommandStateSet, COMP_StateIdle, NULL); cdx_sem_down(&pNode->mSemCompCmd); //create VO Component done! addChannel_l(pNode); pthread_mutex_unlock(&gpVOChnManager->mLock); return SUCCESS; } ERRORTYPE AW_MPI_VO_DestroyChn(VO_LAYER VoLayer, VO_CHN VoChn) { ERRORTYPE ret; if(!(VoChn>=0 && VoChn mComp) { COMP_STATETYPE nCompState; if(SUCCESS == pChn->mComp->GetState(pChn->mComp, &nCompState)) { if(nCompState == COMP_StateIdle) { eRet = pChn->mComp->SendCommand(pChn->mComp, COMP_CommandStateSet, COMP_StateLoaded, NULL); cdx_sem_down(&pChn->mSemCompCmd); eRet = SUCCESS; } else if(nCompState == COMP_StateLoaded) { eRet = SUCCESS; } else if(nCompState == COMP_StateInvalid) { alogw("Low probability! Component StateInvalid?"); eRet = SUCCESS; } else { aloge("fatal error! invalid VoChn[%d] state[0x%x]!", VoChn, nCompState); eRet = FAILURE; } if(eRet == SUCCESS) { removeChannel(pChn); COMP_FreeHandle(pChn->mComp); pChn->mComp = NULL; VO_CHN_MAP_S_Destruct(pChn); ret = SUCCESS; } else { ret = ERR_VO_BUSY; } } else { aloge("fatal error! GetState fail!"); ret = ERR_VO_BUSY; } } else { aloge("fatal error! no VO component!"); list_del(&pChn->mList); VO_CHN_MAP_S_Destruct(pChn); ret = SUCCESS; } return ret; } /** * Register callback, mpp_vo use callback to notify caller. * * @return SUCCESS. * @param VoLayer vo channel number. * @param VoChn vo channel number. * @param pCallback callback struct. */ ERRORTYPE AW_MPI_VO_RegisterCallback(VO_LAYER VoLayer, VO_CHN VoChn, MPPCallbackInfo *pCallback) { if(!(VoChn>=0 && VoChn mCallbackInfo.callback = pCallback->callback; pChn->mCallbackInfo.cookie = pCallback->cookie; return SUCCESS; } ERRORTYPE AW_MPI_VO_SetChnAttr(VO_LAYER VoLayer, VO_CHN VoChn, const VO_CHN_ATTR_S *pstChnAttr) { if(!(VoChn>=0 && VoChnmComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState && COMP_StateIdle != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } ret = pChn->mComp->SetConfig(pChn->mComp, COMP_IndexVendorVOChnAttr, (void*)pstChnAttr); return ret; } ERRORTYPE AW_MPI_VO_GetChnAttr(VO_LAYER VoLayer, VO_CHN VoChn, VO_CHN_ATTR_S *pstChnAttr) { if(!(VoChn>=0 && VoChn mComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState && COMP_StateIdle != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } ret = pChn->mComp->GetConfig(pChn->mComp, COMP_IndexVendorVOChnAttr, (void*)pstChnAttr); return ret; } ERRORTYPE AW_MPI_VO_SetFrameDisplayRegion(VO_LAYER VoLayer, VO_CHN VoChn, const RECT_S *pRect) { if(!(VoChn>=0 && VoChnmComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState && COMP_StateIdle != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } ret = pChn->mComp->SetConfig(pChn->mComp, COMP_IndexVendorDisplayRegion, (void*)pRect); return ret; } ERRORTYPE AW_MPI_VO_GetFrameDisplayRegion(VO_LAYER VoLayer, VO_CHN VoChn, RECT_S *pRect) { if(!(VoChn>=0 && VoChn mComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState && COMP_StateIdle != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } ret = pChn->mComp->GetConfig(pChn->mComp, COMP_IndexVendorDisplayRegion, (void*)pRect); return ret; } ERRORTYPE AW_MPI_VO_SetChnField(VO_LAYER VoLayer, VO_CHN VoChn, const VO_DISPLAY_FIELD_E enField) { if(!(VoChn>=0 && VoChnmComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState && COMP_StateIdle != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } ret = pChn->mComp->SetConfig(pChn->mComp, COMP_IndexVendorVOChnDisplayField, (void*)&enField); return ret; } ERRORTYPE AW_MPI_VO_GetChnField(VO_LAYER VoLayer, VO_CHN VoChn, VO_DISPLAY_FIELD_E *pField) { if(!(VoChn>=0 && VoChnmComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState && COMP_StateIdle != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } ret = pChn->mComp->GetConfig(pChn->mComp, COMP_IndexVendorVOChnDisplayField, (void*)pField); return ret; } ERRORTYPE AW_MPI_VO_SetChnDispBufNum(VO_LAYER VoLayer, VO_CHN VoChn, unsigned int uBufNum) { if(!(VoChn>=0 && VoChnmComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState && COMP_StateIdle != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } ret = pChn->mComp->SetConfig(pChn->mComp, COMP_IndexVendorVODispBufNum, (void*)&uBufNum); return ret; } ERRORTYPE AW_MPI_VO_GetChnDispBufNum(VO_LAYER VoLayer, VO_CHN VoChn, unsigned int *puBufNum) { if(!(VoChn>=0 && VoChnmComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState && COMP_StateIdle != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } ret = pChn->mComp->GetConfig(pChn->mComp, COMP_IndexVendorVODispBufNum, (void*)puBufNum); return ret; } ERRORTYPE AW_MPI_VO_GetDisplaySize (VO_LAYER VoLayer, VO_CHN VoChn, SIZE_S *pDisplaySize) { if(!(VoChn>=0 && VoChnmComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState) { alogw("call in wrong state[0x%x], maybe display size is not right", nState); } ret = pChn->mComp->GetConfig(pChn->mComp, COMP_IndexVendorVOChnDisplaySize, (void*)pDisplaySize); return ret; } ERRORTYPE AW_MPI_VO_SetChnFrameRate(VO_LAYER VoLayer, VO_CHN VoChn, int nChnFrmRate) { if(!(VoChn>=0 && VoChnmComp, COMP_IndexVendorVOChnFrameRate, (void*)&nChnFrmRate); return ret; } ERRORTYPE AW_MPI_VO_GetChnFrameRate(VO_LAYER VoLayer, VO_CHN VoChn, int *pChnFrmRate) { if(!(VoChn>=0 && VoChnmComp, COMP_IndexVendorVOChnFrameRate, (void*)pChnFrmRate); return ret; } ERRORTYPE AW_MPI_VO_StartChn(VO_LAYER VoLayer, VO_CHN VoChn) { if(!(VoChn>=0 && VoChn mComp->GetState(pChn->mComp, &nCompState); if(COMP_StateIdle == nCompState || COMP_StatePause == nCompState) { eRet = pChn->mComp->SendCommand(pChn->mComp, COMP_CommandStateSet, COMP_StateExecuting, NULL); if(eRet != SUCCESS) { aloge("fatal error! Send command stateExecuting fail!"); } cdx_sem_down(&pChn->mSemCompCmd); ret = SUCCESS; } else if(COMP_StateExecuting == nCompState) { alogd("VOChannel[%d] already stateExecuting.", VoChn); ret = SUCCESS; } else { aloge("fatal error! check voChannel[%d]State[0x%x]!", VoChn, nCompState); ret = ERR_VO_CHN_INCORRECT_STATE_TRANSITION; } return ret; } ERRORTYPE AW_MPI_VO_StopChn(VO_LAYER VoLayer, VO_CHN VoChn) { if(!(VoChn>=0 && VoChn mComp->GetState(pChn->mComp, &nCompState); if(COMP_StateExecuting == nCompState || COMP_StatePause == nCompState) { eRet = pChn->mComp->SendCommand(pChn->mComp, COMP_CommandStateSet, COMP_StateIdle, NULL); if(eRet != SUCCESS) { aloge("fatal error! Send command stateIdle fail!"); } cdx_sem_down(&pChn->mSemCompCmd); ret = SUCCESS; } else if(COMP_StateIdle == nCompState) { alogd("VOChannel[%d] already stateIdle.", VoChn); ret = SUCCESS; } else { aloge("fatal error! check voLayer[%d] voChannel[%d]State[0x%x]!", VoLayer, VoChn, nCompState); ret = ERR_VO_CHN_INCORRECT_STATE_TRANSITION; } return ret; } ERRORTYPE AW_MPI_VO_PauseChn (VO_LAYER VoLayer, VO_CHN VoChn) { if(!(VoChn>=0 && VoChn mComp->GetState(pChn->mComp, &nCompState); if(COMP_StateExecuting == nCompState) { eRet = pChn->mComp->SendCommand(pChn->mComp, COMP_CommandStateSet, COMP_StatePause, NULL); if(eRet != SUCCESS) { aloge("fatal error! Send command statePause fail!"); } cdx_sem_down(&pChn->mSemCompCmd); ret = SUCCESS; } else if(COMP_StatePause == nCompState) { alogd("VOChannel[%d] already statePause.", VoChn); ret = SUCCESS; } else if(COMP_StateIdle == nCompState) { alogd("VOChannel[%d] stateIdle, can't turn to statePause!", VoChn); ret = ERR_VO_CHN_INCORRECT_STATE_TRANSITION; } else { aloge("fatal error! check voChannel[%d]State[0x%x]!", VoChn, nCompState); ret = ERR_VO_CHN_INCORRECT_STATE_TRANSITION; } return ret; } ERRORTYPE AW_MPI_VO_ResumeChn(VO_LAYER VoLayer, VO_CHN VoChn) { if(!(VoChn>=0 && VoChn mComp->GetState(pChn->mComp, &nCompState); if(COMP_StatePause == nCompState) { eRet = pChn->mComp->SendCommand(pChn->mComp, COMP_CommandStateSet, COMP_StateExecuting, NULL); if(eRet != SUCCESS) { aloge("fatal error! Send command statePause fail!"); } cdx_sem_down(&pChn->mSemCompCmd); ret = SUCCESS; } else if(COMP_StateExecuting == nCompState) { alogd("VOChannel[%d] already stateExecuting.", VoChn); ret = SUCCESS; } else if(COMP_StateIdle == nCompState) { alogd("VOChannel[%d] stateIdle, can't turn to stateExecuting!", VoChn); ret = ERR_VO_CHN_INCORRECT_STATE_TRANSITION; } else { aloge("fatal error! check voChannel[%d]State[0x%x]!", VoChn, nCompState); ret = ERR_VO_CHN_INCORRECT_STATE_TRANSITION; } return ret; } ERRORTYPE AW_MPI_VO_Seek(VO_LAYER VoLayer, VO_CHN VoChn) { if(!(VoChn>=0 && VoChn mComp->GetState(pChn->mComp, &nCompState); if(COMP_StateIdle == nCompState || COMP_StateExecuting == nCompState || COMP_StatePause == nCompState) { ret = pChn->mComp->SetConfig(pChn->mComp, COMP_IndexVendorSeekToPosition, NULL); } else { aloge("fatal error! can't seek in voChannel[%d]State[0x%x]!", VoChn, nCompState); ret = ERR_VO_CHN_INCORRECT_STATE_TRANSITION; } return ret; } /** * set or clear stream end of file, mpp_vo can send eof callback msg to upper when it be set eof. * * @return SUCCESS. * @param VoLayer vo layer number. * @param VoChn vo channel number. * @param bEofFlag indicate if eof. */ ERRORTYPE AW_MPI_VO_SetStreamEof(VO_LAYER VoLayer, VO_CHN VoChn, BOOL bEofFlag) { if(!(VoChn>=0 && VoChn mComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState && COMP_StateIdle != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } if(bEofFlag) { ret = pChn->mComp->SetConfig(pChn->mComp, COMP_IndexVendorSetStreamEof, NULL); } else { ret = pChn->mComp->SetConfig(pChn->mComp, COMP_IndexVendorClearStreamEof, NULL); } return ret; } ERRORTYPE AW_MPI_VO_ShowChn(VO_LAYER VoLayer, VO_CHN VoChn) { if(!(VoChn>=0 && VoChnmComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState && COMP_StateIdle != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } BOOL bShowFlag = TRUE; ret = pChn->mComp->SetConfig(pChn->mComp, COMP_IndexVendorShow, &bShowFlag); return ret; } ERRORTYPE AW_MPI_VO_HideChn(VO_LAYER VoLayer, VO_CHN VoChn) { if(!(VoChn>=0 && VoChnmComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState && COMP_StateIdle != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } BOOL bShowFlag = FALSE; ret = pChn->mComp->SetConfig(pChn->mComp, COMP_IndexVendorShow, &bShowFlag); return ret; } ERRORTYPE AW_MPI_VO_SetZoomInWindow(VO_LAYER VoLayer, VO_CHN VoChn, const VO_ZOOM_ATTR_S *pstZoomAttr) { aloge("need implement"); return ERR_VO_NOT_SUPPORT; } ERRORTYPE AW_MPI_VO_GetZoomInWindow(VO_LAYER VoLayer, VO_CHN VoChn, VO_ZOOM_ATTR_S *pstZoomAttr) { aloge("need implement"); return ERR_VO_NOT_SUPPORT; } ERRORTYPE AW_MPI_VO_SetVideoScalingMode(VO_LAYER VoLayer, VO_CHN VoChn, int mode) { aloge("unsupported temporary"); return ERR_VO_NOT_SUPPORT; } ERRORTYPE AW_MPI_VO_GetChnPts (VO_LAYER VoLayer, VO_CHN VoChn, uint64_t *pChnPts) { if(!(VoChn>=0 && VoChnmComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } COMP_TIME_CONFIG_TIMESTAMPTYPE timeStamp; ret = pChn->mComp->GetConfig(pChn->mComp, COMP_IndexConfigTimeCurrentMediaTime, (void*)&timeStamp); *pChnPts = timeStamp.nTimestamp; return ret; } ERRORTYPE AW_MPI_VO_SendFrame(VO_LAYER VoLayer, VO_CHN VoChn, VIDEO_FRAME_INFO_S *pstVFrame, int nMilliSec) { if(!(VoChn>=0 && VoChnmComp->GetState(pChn->mComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } COMP_BUFFERHEADERTYPE compBuffer; compBuffer.pAppPrivate = (void*)pstVFrame; ret = COMP_EmptyThisBuffer(pChn->mComp, &compBuffer); return ret; } ERRORTYPE AW_MPI_VO_Debug_StoreFrame(VO_LAYER VoLayer, VO_CHN VoChn, uint64_t framePts) { if(!(VoChn>=0 && VoChnmComp, &nState); if(COMP_StateExecuting != nState && COMP_StatePause != nState) { aloge("wrong state[0x%x], return!", nState); return ERR_VO_NOT_PERMIT; } ret = COMP_SetConfig(pChn->mComp, COMP_IndexVendorStoreFrame, (void*)&framePts); return ret; }