sdk-hwV1.3/external/eyesee-mpp/middleware/sun8iw21/media/videoIn/uvcInput.c

1290 lines
47 KiB
C
Executable File

/******************************************************************************
Copyright (C), 2001-2016, Allwinner Tech. Co., Ltd.
******************************************************************************
File Name : uvcInput.c
Version : Initial Draft
Author : Allwinner BU3-PD2 Team
Created : 2017/12/06
Last Modified :
Description : mpi_uvc functions implement
Function List :
History :
******************************************************************************/
//#define LOG_NDEBUG 0
#define LOG_TAG "videoInput"
#include <utils/plat_log.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <cdx_list.h>
#include <UvcVirVi_Component.h>
#include <mpi_videoformat_conversion.h>
#include <ion_memmanager.h>
#define SHOW_INFO_OF_UVC
static void *uvcInput_CapThread(void *pThreadData);
static void yuv422pa_yuv422sp(unsigned char *yuyv,
unsigned char * nv21_y, unsigned char *nv21_uv,
unsigned int width, unsigned int height)
{
int nSum = width * height * 2;
int i;
for(i = 0; i < nSum; i++)
{
if(0 == i % 2)
{
*nv21_y = yuyv[i];
nv21_y++;
}
else
{
*nv21_uv = yuyv[i];
nv21_uv++;
}
}
}
static UvcDevManager *gpUvcDevManager = NULL;
static ERRORTYPE uvc_query(int fd, int cmd_id, const char *cmd_name, struct v4l2_queryctrl *queryctrl)
{
ERRORTYPE bResult = FAILURE;
if(queryctrl)
{
queryctrl->id = cmd_id;
if(ioctl(fd, VIDIOC_QUERYCTRL, queryctrl) < 0)
{
aloge("failed query %s, %s", cmd_name, strerror(errno));
}
else
{
bResult = SUCCESS;
}
}
return bResult;
}
static ERRORTYPE uvcInput_SearchExitDev(UVC_DEV UvcDev, UvcChnManager ***pppUvcChnManager)
{
ERRORTYPE bResult = FAILURE;
int i = 0;
for(; i < UVC_MAX_DEV_NUM; i++)
{
if(gpUvcDevManager->mUvcChnManager[i] && 0 == strcmp(gpUvcDevManager->mUvcChnManager[i]->mUvcDevName, UvcDev))
{
bResult = SUCCESS;
if(pppUvcChnManager)
{
*pppUvcChnManager = &gpUvcDevManager->mUvcChnManager[i];
}
break;
}
}
return bResult;
}
ERRORTYPE uvcInput_SearchExitDevVirChn(UVC_DEV UvcDev, UVC_CHN UvcChn, UVC_CHN_MAP_S **ppChn)
{
ERRORTYPE bResult = FAILURE;
UvcChnManager **ppUvcChnManager = NULL;
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);
if(uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager) != SUCCESS)
{
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
UvcChnManager *pUvcChnManager = *ppUvcChnManager;
pthread_mutex_lock(&pUvcChnManager->mLock);
UVC_CHN_MAP_S *pEnty = NULL;
list_for_each_entry(pEnty, &pUvcChnManager->mChnList, mList)
{
if(pEnty->mUvcChn == UvcChn)
{
bResult = SUCCESS;
if(ppChn)
{
*ppChn = pEnty;
}
break;
}
}
pthread_mutex_unlock(&pUvcChnManager->mLock);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
MM_COMPONENTTYPE *uvcInput_GetChnComp(UVC_DEV UvcDev, UVC_CHN UvcChn)
{
UVC_CHN_MAP_S *pChn;
if(uvcInput_SearchExitDevVirChn(UvcDev, UvcChn, &pChn) != SUCCESS)
{
return NULL;
}
return pChn->mUvcComp;
}
ERRORTYPE uvcInput_Construct(UVC_DEV UvcDev, int fd)
{
ERRORTYPE bResult = FAILURE;
UvcChnManager **ppUvcChnManager = NULL;
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);
if(SUCCESS == uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager))
{
alogd("the UVC %s had open!", UvcDev);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
bResult = SUCCESS;
return bResult;
}
int i = 0;
for(; i < UVC_MAX_CHN_NUM; i++)
{
if(!gpUvcDevManager->mUvcChnManager[i])
{
break;
}
}
if(UVC_MAX_CHN_NUM == i)
{
aloge("the UVC Dev had enough, it had %d now", UVC_MAX_CHN_NUM);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
UvcChnManager *pUvcChnManager = (UvcChnManager *)malloc(sizeof *pUvcChnManager);
if(NULL == pUvcChnManager)
{
aloge("alloc %s UVC UvcChnManager error(%s)!", UvcDev, strerror(errno));
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
memset(pUvcChnManager, 0, sizeof *pUvcChnManager);
if(strlen(UvcDev) >= UVC_MAX_DEV_NAME)
{
aloge("the dev name %s had over %d", UvcDev, UVC_MAX_DEV_NAME);
goto error;
}
memcpy(pUvcChnManager->mUvcDevName, UvcDev, strlen(UvcDev)+1);
pUvcChnManager->mFd = fd;
pthread_mutex_init(&pUvcChnManager->mLock, NULL);
pthread_mutex_init(&pUvcChnManager->mRefsLock, NULL);
INIT_LIST_HEAD(&pUvcChnManager->mChnList);
gpUvcDevManager->mUvcChnManager[i] = pUvcChnManager;
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
bResult = SUCCESS;
return bResult;
error:
free(pUvcChnManager);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
ERRORTYPE uvcInput_Destruct(UVC_DEV UvcDev)
{
ERRORTYPE bResult = FAILURE;
int i = 0;
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);
UvcChnManager **ppUvcChnManager = NULL;
if(SUCCESS == uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager))
{
UvcChnManager *pUvcChnManager = NULL ;
pUvcChnManager = *ppUvcChnManager;
if(!list_empty(&pUvcChnManager->mChnList))
{
aloge("fatal error! the % UVC had some channel still running when destroy it!");
goto Label;
}
//ummap
int bufferlength = pUvcChnManager->mBufferLength;
if(bufferlength != 0)
{
for(i = 0 ; i < pUvcChnManager->mUvcAttr.mUvcVideo_BufCnt; i++)
{
if(pUvcChnManager->mpVideoBuffer[i])
{
if(munmap(pUvcChnManager->mpVideoBuffer[i], bufferlength) < 0)
{
aloge("the %s UVC munmap buffer[%d] fail, %s", UvcDev, i, strerror(errno));
}
}
}
}
close(pUvcChnManager->mFd);//close UVC fd;
pthread_mutex_destroy(&pUvcChnManager->mLock);
pthread_mutex_destroy(&pUvcChnManager->mRefsLock);
for(i = 0; i < pUvcChnManager->mUvcAttr.mUvcVideo_BufCnt; i++)
{
if(pUvcChnManager->mUvcCaptureFrame[i].VFrame.mpVirAddr[0])
{
ion_freeMem(pUvcChnManager->mUvcCaptureFrame[i].VFrame.mpVirAddr[0]);
}
}
free(pUvcChnManager);
*ppUvcChnManager = NULL;
}
bResult = SUCCESS;
Label:
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
ERRORTYPE UVC_Construct(void)
{
ERRORTYPE bResult = FAILURE;
if(gpUvcDevManager != NULL)
{
return SUCCESS;
}
gpUvcDevManager = (UvcDevManager *)malloc(sizeof(UvcDevManager));
if(NULL == gpUvcDevManager)
{
aloge("alloc gpUvcDevManager fail, %", strerror(errno));
return bResult;
}
memset(gpUvcDevManager, 0, sizeof *gpUvcDevManager);
pthread_mutex_init(&gpUvcDevManager->mUvcDevManagerLock, NULL);
return SUCCESS;
}
ERRORTYPE UVC_Destruct(void)
{
if(gpUvcDevManager)
{
int i = 0;
for(; i < UVC_MAX_DEV_NUM; i++)
{
if(gpUvcDevManager->mUvcChnManager[i])
{
if(uvcInput_Destruct(gpUvcDevManager->mUvcChnManager[i]->mUvcDevName) != SUCCESS)
{
aloge("can not destrcut % UVC", gpUvcDevManager->mUvcChnManager[i]->mUvcDevName);
return FAILURE;
}
}
}
pthread_mutex_destroy(&gpUvcDevManager->mUvcDevManagerLock);
free(gpUvcDevManager);
gpUvcDevManager = NULL;
}
return SUCCESS;
}
UVC_CHN_MAP_S *uvcInput_CHN_MAP_S_Construct()
{
UVC_CHN_MAP_S *pChnnel = (UVC_CHN_MAP_S *)malloc(sizeof(UVC_CHN_MAP_S));
if(NULL == pChnnel)
{
aloge("fatal error! malloc fail [%s]", strerror(errno));
return NULL;
}
memset(pChnnel, 0, sizeof *pChnnel);
cdx_sem_init(&pChnnel->mSemCompCmd, 0);
return pChnnel;
}
void uvcInput_CHN_MAP_S_Destruct(UVC_CHN_MAP_S *pChnnel)
{
if(pChnnel)
{
if(pChnnel->mUvcComp)
{
aloge("fatal error!, the %d channel componet need free before!", pChnnel->mUvcChn);
COMP_FreeHandle(pChnnel->mUvcComp);
pChnnel->mUvcComp = NULL;
}
cdx_sem_deinit(&pChnnel->mSemCompCmd);
free(pChnnel);
//pChnnel = NULL;//ignore
}
}
ERRORTYPE uvcInput_addChannel(UVC_DEV UvcDev, UVC_CHN_MAP_S *pChn)
{
ERRORTYPE bResult = FAILURE;
if(UvcDev && pChn)
{
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);
UvcChnManager **ppUvcChnManager = NULL;
if(uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager) != SUCCESS)
{
aloge("fatal error! can not found %s UVC", UvcDev);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
UvcChnManager *pUvcChnManager = *ppUvcChnManager;
pChn->mUvcComp->SetConfig(pChn->mUvcComp, COMP_IndexVendorUvcSetDevInfo, (void *) *ppUvcChnManager);
pthread_mutex_lock(&pUvcChnManager->mLock);
list_add_tail(&pChn->mList, &pUvcChnManager->mChnList);
pthread_mutex_unlock(&pUvcChnManager->mLock);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
bResult = SUCCESS;
}
return bResult;
}
ERRORTYPE uvcInput_removeChannel(UVC_DEV UvcDev, UVC_CHN_MAP_S *pChn)
{
ERRORTYPE bResult = FAILURE;
if(UvcDev && pChn)
{
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);
UvcChnManager **ppUvcChnManager = NULL;
if(uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager) != SUCCESS)
{
aloge("fatal error! can not found %s UVC", UvcDev);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
UvcChnManager *pUvcChnManager = *ppUvcChnManager;
pthread_mutex_lock(&pUvcChnManager->mLock);
list_del(&pChn->mList);
pthread_mutex_unlock(&pUvcChnManager->mLock);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
bResult = SUCCESS;
}
return bResult;
}
ERRORTYPE uvcInput_Open_Video(UVC_DEV UvcDev)
{
ERRORTYPE bResult = FAILURE;
if(UvcDev)
{
int fd = open(UvcDev, O_RDWR, 0);
if(fd < 0)
{
aloge("the open %d UVC Camera fail!", UvcDev);
return bResult;
}
if(uvcInput_Construct(UvcDev, fd) != SUCCESS)
{
aloge("the %s UVC do not construct!", UvcDev);
uvcInput_Destruct(UvcDev);
return bResult;
}
bResult = SUCCESS;
}
return bResult;
}
ERRORTYPE uvcInput_Close_Video(UVC_DEV UvcDev)
{
ERRORTYPE bResult = FAILURE;
if(UvcDev)
{
if(uvcInput_Destruct(UvcDev) != SUCCESS)
{
aloge("the %s UVC do not destruct, and it means can not close fd", UvcDev);
return bResult;
}
}
bResult = SUCCESS;
return bResult;
}
ERRORTYPE uvcInput_SetDevEnable(UVC_DEV UvcDev)
{
ERRORTYPE bResult = FAILURE;
if(UvcDev)
{
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);
UvcChnManager **ppUvcChnManager = NULL;
if(uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager) != SUCCESS)
{
aloge("fatal error! can not found %s UVC", UvcDev);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
UvcChnManager *pUvcChnManager = *ppUvcChnManager;
if(0 == pUvcChnManager->mUvcDevEnable)
{
int uvc_fd = pUvcChnManager->mFd;
int buffer_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(uvc_fd, VIDIOC_STREAMON, &buffer_type) < 0)
{
aloge("the %s UVC fail to start capture, %s", UvcDev, strerror(errno));
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
pUvcChnManager->mUvcDevEnable = 1;
if(0 == pUvcChnManager->mThread_uvc_capture)
{
pthread_create(&pUvcChnManager->mThread_uvc_capture, NULL, uvcInput_CapThread,(void *)pUvcChnManager);
}
bResult = SUCCESS;
}
else
{
alogd("Be careful! uvcDev[%s] already enable!", UvcDev);
bResult = SUCCESS;
}
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
}
return bResult;
}
ERRORTYPE uvcInput_SetDevDisable(UVC_DEV UvcDev)
{
ERRORTYPE bResult = FAILURE;
if(UvcDev)
{
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);
UvcChnManager **ppUvcChnManager = NULL;
if(uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager) != SUCCESS)
{
aloge("fatal error! can not found %s UVC", UvcDev);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
UvcChnManager *pUvcChnManager = *ppUvcChnManager;
if(pUvcChnManager->mUvcDevEnable)
{
int uvc_fd = pUvcChnManager->mFd;
int buffer_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(uvc_fd, VIDIOC_STREAMOFF, &buffer_type) < 0)
{
aloge("the %s fail to stop capture, %s", UvcDev, strerror(errno));
//pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
//return bResult;
}
pUvcChnManager->mUvcDevEnable = 0;
//pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
if(pUvcChnManager->mThread_uvc_capture)
{
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
void *status;
pthread_join(pUvcChnManager->mThread_uvc_capture, &status);
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);
pUvcChnManager->mThread_uvc_capture = 0;
}
}
else
{
alogd("Be careful! uvcDev[%s] already disable!", UvcDev);
}
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
bResult = SUCCESS;
}
return bResult;
}
ERRORTYPE uvcInput_GetDevAttr(UVC_DEV UvcDev, UVC_ATTR_S *pAttr)
{
ERRORTYPE bResult = FAILURE;
if(UvcDev && pAttr)
{
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);
UvcChnManager **ppUvcChnManager = NULL;
if(uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager) != SUCCESS)
{
aloge("fatal error! can not found %s UVC", UvcDev);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
UvcChnManager *pUvcChnManager = *ppUvcChnManager;
*pAttr = pUvcChnManager->mUvcAttr;
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
bResult = SUCCESS;
}
return bResult;
}
ERRORTYPE uvcInput_SetDevAttr(UVC_DEV UvcDev, UVC_ATTR_S *pAttr)
{
ERRORTYPE bResult = FAILURE;
if(!UvcDev || !pAttr)
{
//aloge("fatal error!!");
return bResult;
}
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);//1+
UvcChnManager **ppUvcChnManager = NULL;
if(uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager) != SUCCESS)
{
aloge("fatal error! can not found %s UVC", UvcDev);
goto error;
}
UvcChnManager *pUvcChnManager = *ppUvcChnManager;
//pUvcChnManager->mUvcAttr = *pAttr;
int uvc_fd = pUvcChnManager->mFd;
struct v4l2_capability cap;
unsigned int capabilities;
memset(&cap, 0, sizeof cap);
if(ioctl(uvc_fd, VIDIOC_QUERYCAP, &cap) < 0)
{
aloge(" the %s UVC fail to ioctl VIDIOC_QUERYCAP", UvcDev);
goto error;
}
capabilities = cap.device_caps ? : cap.capabilities;
if(capabilities & V4L2_CAP_VIDEO_CAPTURE)
{
alogd("the %s UVC support video capture!", UvcDev);
}
else
{
aloge("the %s UVC not support video capture!", UvcDev);
goto error;
}
#ifdef SHOW_INFO_OF_UVC
alogd("the %s UVC driver is %s", UvcDev, cap.driver);
alogd("the %s UVC card is %s", UvcDev, cap.card);
alogd("the %s UVC bus info is %s", UvcDev, cap.bus_info);
alogd("the version is %d", cap.version);
#endif
struct v4l2_fmtdesc fmt;
memset(&fmt, 0, sizeof fmt);
fmt.index = 0;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
int support_pixelformat = 0;
int nMatchFormatNum = 0;
while(ioctl(uvc_fd, VIDIOC_ENUM_FMT, &fmt) == 0)
{
fmt.index++;
alogd("the %s UVC device can support %s capture pixelformat[0x%x]", UvcDev, fmt.description, fmt.pixelformat); //UVC_NV12
if(fmt.pixelformat == pAttr->mPixelformat)
{
alogd("Congratulation: the %s UVC support %s capture pixelformat", UvcDev, fmt.description);
support_pixelformat = 1;
nMatchFormatNum++;
struct v4l2_format format;
memset(&format, 0, sizeof format);
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.pixelformat = pAttr->mPixelformat;
format.fmt.pix.width = pAttr->mUvcVideo_Width;
format.fmt.pix.height = pAttr->mUvcVideo_Height;
if(ioctl(uvc_fd, VIDIOC_TRY_FMT, &format) < 0)
{
aloge("the %s UVC unable to set type frame!", UvcDev);
goto error;
}
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(uvc_fd, VIDIOC_S_FMT, &format) < 0)
{
aloge("the %s UVC fail to set frame format!", UvcDev);
goto error;
}
if(ioctl(uvc_fd, VIDIOC_G_FMT, &format) < 0)
{
aloge("the %s UVC fail to get frame format!", UvcDev);
goto error;
}
if(format.fmt.pix.width != pAttr->mUvcVideo_Width || format.fmt.pix.height != pAttr->mUvcVideo_Height)
{
alogw("Be careful! you can not set %s UVC capture [%dx%d],and now they are [%dx%d]",
UvcDev, pAttr->mUvcVideo_Width, pAttr->mUvcVideo_Height,
format.fmt.pix.width, format.fmt.pix.height);
}
pUvcChnManager->mUvcAttr.mPixelformat = format.fmt.pix.pixelformat;
pUvcChnManager->mUvcAttr.mUvcVideo_Width = format.fmt.pix.width;
pUvcChnManager->mUvcAttr.mUvcVideo_Height = format.fmt.pix.height;
//break;
}
}
if(0 == support_pixelformat)
{
aloge("fatal error! Unfortunation: the %s UVC do not support 0x%x pixelformat", UvcDev, pAttr->mPixelformat);
goto error;
}
if(nMatchFormatNum > 1)
{
alogd("Be careful! format match count[%d] > 1", nMatchFormatNum);
}
struct v4l2_streamparm streamparm;
memset(&streamparm, 0, sizeof streamparm);
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(uvc_fd, VIDIOC_G_PARM, &streamparm) < 0)
{
aloge("the %s UVC failed to get v4l2_streamparm!", UvcDev);
goto error;
}
int fps = (streamparm.parm.capture.timeperframe.denominator) / (streamparm.parm.capture.timeperframe.numerator);
if(pAttr->mUvcVideo_Fps != 0 && pAttr->mUvcVideo_Fps != fps)
{
streamparm.parm.capture.timeperframe.denominator = pAttr->mUvcVideo_Fps;
streamparm.parm.capture.timeperframe.numerator = 1;
if(ioctl(uvc_fd, VIDIOC_S_PARM, &streamparm) < 0)
{
aloge("the %s UVC can not set fps as %d, and default as %d", UvcDev, pAttr->mUvcVideo_Fps, fps);
pUvcChnManager->mUvcAttr.mUvcVideo_Fps = fps;
}
else
{
memset(&streamparm, 0, sizeof streamparm);
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(uvc_fd, VIDIOC_G_PARM, &streamparm) < 0)
{
aloge("the %s UVC failed to get v4l2_streamparm!", UvcDev);
pUvcChnManager->mUvcAttr.mUvcVideo_Fps = fps;
}
else
{
int new_fps = (streamparm.parm.capture.timeperframe.denominator) / (streamparm.parm.capture.timeperframe.numerator);
if(new_fps == pAttr->mUvcVideo_Fps)
{
pUvcChnManager->mUvcAttr.mUvcVideo_Fps = pAttr->mUvcVideo_Fps;
}
else
{
aloge("why not can set %s UVC capturerate from %d to %d fps? maybe the device can not support,and now the rate is %d fps!", UvcDev, fps, pAttr->mUvcVideo_Fps, new_fps);
pUvcChnManager->mUvcAttr.mUvcVideo_Fps = new_fps;
}
}
//pUvcChnManager->mUvcAttr.mUvcVideo_Fps = pAttr->mUvcVideo_Fps;
}
}
else
{
pUvcChnManager->mUvcAttr.mUvcVideo_Fps = fps;
}
struct v4l2_requestbuffers req;
memset(&req, 0, sizeof req);
if(pAttr->mUvcVideo_BufCnt <= BUFFER_COUNT)
{
pUvcChnManager->mUvcAttr.mUvcVideo_BufCnt = pAttr->mUvcVideo_BufCnt;
}
else
{
alogd("Be careful! user set bufCnt[%d] > max[%d], set to max!", pAttr->mUvcVideo_BufCnt, BUFFER_COUNT);
pUvcChnManager->mUvcAttr.mUvcVideo_BufCnt = BUFFER_COUNT;
}
req.count = pUvcChnManager->mUvcAttr.mUvcVideo_BufCnt;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if(ioctl(uvc_fd, VIDIOC_REQBUFS, &req) < 0)
{
aloge("fatal error! the %s UVC reqbufs fail, %s", UvcDev, strerror(errno));
goto error;
}
struct v4l2_buffer buffer;
int bufferindex;
for(bufferindex = 0; bufferindex < pUvcChnManager->mUvcAttr.mUvcVideo_BufCnt; bufferindex++)
{
memset(&buffer, 0, sizeof buffer);
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buffer.memory = V4L2_MEMORY_MMAP;
buffer.index = bufferindex;
int bufferlength = 0;
if(ioctl(uvc_fd, VIDIOC_QUERYBUF, &buffer) < 0)
{
aloge("the %s UVC querybuf fail, %s", strerror(errno));
pUvcChnManager->mBufferLength = bufferlength;
goto error;
}
if(bufferindex != buffer.index)
{
aloge("fatal error! index is not same with appointment, [%d]!=[%d]", buffer.index, bufferindex);
}
pUvcChnManager->mUvcV4l2BufferInfo[buffer.index] = buffer;
bufferlength = buffer.length;
pUvcChnManager->mpVideoBuffer[bufferindex] = (unsigned char *)mmap(NULL, buffer.length, PROT_READ, MAP_SHARED,
uvc_fd, buffer.m.offset);
if(MAP_FAILED == pUvcChnManager->mpVideoBuffer[bufferindex])
{
aloge("the %s UVC mmap fail, %s", UvcDev, strerror(errno));
pUvcChnManager->mpVideoBuffer[bufferindex] = NULL;
pUvcChnManager->mBufferLength = buffer.length;
goto error;
}
if(ioctl(uvc_fd, VIDIOC_QBUF, &buffer) < 0)
{
aloge("the %s UVC qbuf fail, %s", UvcDev, strerror(errno));
pUvcChnManager->mBufferLength = buffer.length;
goto error;
}
}
pUvcChnManager->mBufferLength = buffer.length;
//because vo and venc need physical contiguous memory, so if uvc frame is raw type,
//we need create ion buffer to copy frames sent by uvc driver,
if(UVC_H264 != pUvcChnManager->mUvcAttr.mPixelformat && UVC_MJPEG != pUvcChnManager->mUvcAttr.mPixelformat)
{
#if 0
unsigned char *pIonMem = ion_allocMem(buffer.length * BUFFER_COUNT * 3);
if(!pIonMem)
{
aloge("error: ion_allocMem can not malloc %d bytes", pUvcChnManager->mBufferLength * BUFFER_COUNT);
goto error;
}
unsigned int pIonMemPhyAddr = ion_getMemPhyAddr(pIonMem);
for(bufferindex = 0; bufferindex < BUFFER_COUNT; bufferindex++)
{
pUvcChnManager->mUvcCaptureFrame[bufferindex].mId = bufferindex;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mpVirAddr[0] = pIonMem + 3 *bufferindex * pUvcChnManager->mBufferLength;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mpVirAddr[1] = pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mpVirAddr[0] + pUvcChnManager->mBufferLength;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mpVirAddr[2] = pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mpVirAddr[1] + pUvcChnManager->mBufferLength;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mPhyAddr[0] = pIonMemPhyAddr + 3 * bufferindex * pUvcChnManager->mBufferLength;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mPhyAddr[1] = pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mPhyAddr[0] + pUvcChnManager->mBufferLength;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mPhyAddr[2] = pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mPhyAddr[1] + pUvcChnManager->mBufferLength;
}
#else
for(bufferindex = 0; bufferindex < pUvcChnManager->mUvcAttr.mUvcVideo_BufCnt; bufferindex++)
{
unsigned int alignLength = AWALIGN(buffer.length, 1024) + 3*1024;
IonAllocAttr stAllocAttr;
memset(&stAllocAttr, 0, sizeof(IonAllocAttr));
stAllocAttr.mLen = alignLength;
stAllocAttr.mAlign = 0;
stAllocAttr.mIonHeapType = IonHeapType_IOMMU;
stAllocAttr.mbSupportCache = 0;
unsigned char *pIonMem = ion_allocMem_extend(&stAllocAttr);
if(!pIonMem)
{
aloge("error: ion_allocMem_extend can not malloc %d bytes", alignLength);
goto error;
}
unsigned int pIonMemPhyAddr = ion_getMemPhyAddr(pIonMem);
pUvcChnManager->mUvcCaptureFrame[bufferindex].mId = bufferindex;
if(UVC_NV12 == pUvcChnManager->mUvcAttr.mPixelformat)
{
unsigned int yAlignLength = AWALIGN(pUvcChnManager->mUvcAttr.mUvcVideo_Width*pUvcChnManager->mUvcAttr.mUvcVideo_Height, 1024);
unsigned int uAlignLength = AWALIGN(pUvcChnManager->mUvcAttr.mUvcVideo_Width*pUvcChnManager->mUvcAttr.mUvcVideo_Height/2, 8);
unsigned int uLength = pUvcChnManager->mUvcAttr.mUvcVideo_Width*pUvcChnManager->mUvcAttr.mUvcVideo_Height/2;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mpVirAddr[0] = pIonMem;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mpVirAddr[1] = pIonMem + yAlignLength;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mpVirAddr[2] = pIonMem + yAlignLength + uAlignLength;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mPhyAddr[0] = pIonMemPhyAddr;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mPhyAddr[1] = pIonMemPhyAddr + yAlignLength;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mPhyAddr[2] = pIonMemPhyAddr + yAlignLength + uAlignLength;
}
else if(UVC_YUY2 == pUvcChnManager->mUvcAttr.mPixelformat)
{
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mpVirAddr[0] = pIonMem;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mPhyAddr[0] = pIonMemPhyAddr;
}
else
{
aloge("fatal error! unknown pixel format[0x%x]", pUvcChnManager->mUvcAttr.mPixelformat);
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mpVirAddr[0] = pIonMem;
pUvcChnManager->mUvcCaptureFrame[bufferindex].VFrame.mPhyAddr[0] = pIonMemPhyAddr;
}
}
#endif
}
#ifdef SHOW_INFO_OF_UVC
alogd("the %s UVC capture fixformat is %x", UvcDev, pUvcChnManager->mUvcAttr.mPixelformat);
alogd("the %s UVC capture width is %d", UvcDev, pUvcChnManager->mUvcAttr.mUvcVideo_Width);
alogd("the %s UVC capture height is %d", UvcDev, pUvcChnManager->mUvcAttr.mUvcVideo_Height);
alogd("the %s UVC capture fps is %d", UvcDev, pUvcChnManager->mUvcAttr.mUvcVideo_Fps);
alogd("the %s UVC capture bufCount is %d", UvcDev, pUvcChnManager->mUvcAttr.mUvcVideo_BufCnt);
#endif
alogw("the %s UVC had init!", UvcDev);
bResult = SUCCESS;
error:
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
static ERRORTYPE uvcInput_WaiteBuffer(UVC_DEV UvcDev, int fd, int nMilliSec)
{
ERRORTYPE bResult = FAILURE;
fd_set fds;
struct timeval tv;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = nMilliSec / 1000;
tv.tv_usec = (nMilliSec % 1000) * 1000;
int ret = select(fd + 1, &fds, NULL, NULL, &tv);
if(-1 == ret )
{
aloge("the %s UVC select error!", UvcDev);
return bResult;
}
else if(0 == ret)
{
aloge("the %s UVC select timeout!", UvcDev);
return bResult;
}
bResult = SUCCESS;
return bResult;
}
static ERRORTYPE uvcInput_GetData(UVC_DEV UvcDev, VIDEO_FRAME_INFO_S *pstFrameInfo, int nMilliSec)
{
ERRORTYPE bResult = FAILURE;
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);
UvcChnManager **ppUvcChnManager = NULL;
if(uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager) != SUCCESS)
{
aloge("fatal error! can not found %s UVC", UvcDev);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
UvcChnManager *pUvcChnManager = *ppUvcChnManager;
int uvc_fd = pUvcChnManager->mFd;
if(uvcInput_WaiteBuffer(UvcDev, uvc_fd, nMilliSec) != SUCCESS)
{
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
struct v4l2_buffer buffer;
memset(&buffer, 0, sizeof buffer);
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buffer.memory = V4L2_MEMORY_MMAP;
buffer.index = BUFFER_COUNT;
if(ioctl(uvc_fd, VIDIOC_DQBUF, &buffer) < 0)
{
aloge("the %s UVC get frame fail, %s", UvcDev, strerror(errno));
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
//if(buffer.index < 0 || buffer.index >= BUFFER_COUNT)
//{
// aloge("the %s UVC invalid buffer index: %d", UvcDev, buffer.index);
// pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
// return bResult;
//}
pstFrameInfo->mId = buffer.index;
pstFrameInfo->VFrame.mpts = (int64_t)buffer.timestamp.tv_sec * 1000000LL + buffer.timestamp.tv_usec;
pstFrameInfo->VFrame.mPixelFormat = MM_PIXEL_FORMAT_SINGLE;// single, mjpeg or h264 stream
pstFrameInfo->VFrame.mWidth = pUvcChnManager->mUvcAttr.mUvcVideo_Width;
pstFrameInfo->VFrame.mHeight= pUvcChnManager->mUvcAttr.mUvcVideo_Height;
pstFrameInfo->VFrame.mpVirAddr[0] = pUvcChnManager->mpVideoBuffer[buffer.index];
pstFrameInfo->VFrame.mStride[0] = buffer.bytesused;
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
bResult = SUCCESS;
return bResult;
}
static ERRORTYPE uvcInput_GetData2(UvcChnManager *pUvcChnManager, VIDEO_FRAME_INFO_S *pstFrameInfo, int nMilliSec)
{
ERRORTYPE bResult = FAILURE;
int uvc_fd = pUvcChnManager->mFd;
#if 1
if(uvcInput_WaiteBuffer(pUvcChnManager->mUvcDevName, uvc_fd, nMilliSec) != SUCCESS)
{
return bResult;
}
#endif
struct v4l2_buffer buffer;
memset(&buffer, 0, sizeof buffer);
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buffer.memory = V4L2_MEMORY_MMAP;
buffer.index = BUFFER_COUNT;
if(ioctl(uvc_fd, VIDIOC_DQBUF, &buffer) < 0)
{
if(pUvcChnManager->mUvcDevEnable) // check the uvc enable state,
{
aloge("the %s UVC get frame fail, %s", pUvcChnManager->mUvcDevName, strerror(errno));
usleep(200000);
}
return bResult;
}
#if 0
pstFrameInfo->mId = buffer.index;
pstFrameInfo->VFrame.mpts = (int64_t)buffer.timestamp.tv_sec * 1000000LL + buffer.timestamp.tv_usec;
pstFrameInfo->VFrame.mPixelFormat = MM_PIXEL_FORMAT_YUYV_PACKAGE_422;// note:
pstFrameInfo->VFrame.mWidth = pUvcChnManager->mUvcAttr.mUvcVideo_Width;
pstFrameInfo->VFrame.mHeight= pUvcChnManager->mUvcAttr.mUvcVideo_Height;
pstFrameInfo->VFrame.mpVirAddr[0] = pUvcChnManager->mpVideoBuffer[buffer.index];
pstFrameInfo->VFrame.mStride[0] = buffer.bytesused;
#endif
if(buffer.index < BUFFER_COUNT)
{
if(V4L2_PIX_FMT_MJPEG == pUvcChnManager->mUvcAttr.mPixelformat || V4L2_PIX_FMT_H264 == pUvcChnManager->mUvcAttr.mPixelformat)
{
#if 0
pUvcChnManager->mUvcCaptureFrame[buffer.index].mId = buffer.index;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mpts = (int64_t)buffer.timestamp.tv_sec * 1000000LL + buffer.timestamp.tv_usec;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mPixelFormat = MM_PIXEL_FORMAT_BUTT;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mWidth = pUvcChnManager->mUvcAttr.mUvcVideo_Width;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mHeight = pUvcChnManager->mUvcAttr.mUvcVideo_Height;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mStride[0] = buffer.bytesused;
memcpy(pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mpVirAddr[0], pUvcChnManager->mpVideoBuffer[buffer.index], buffer.bytesused);
*pstFrameInfo = pUvcChnManager->mUvcCaptureFrame[buffer.index];
ion_flushCache(pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mpVirAddr[0], 3 * pUvcChnManager->mBufferLength);
#else
pstFrameInfo->mId = buffer.index;
pstFrameInfo->VFrame.mpts = (int64_t)buffer.timestamp.tv_sec * 1000000LL + buffer.timestamp.tv_usec;
pstFrameInfo->VFrame.mPixelFormat = MM_PIXEL_FORMAT_BUTT;
pstFrameInfo->VFrame.mWidth = pUvcChnManager->mUvcAttr.mUvcVideo_Width;
pstFrameInfo->VFrame.mHeight = pUvcChnManager->mUvcAttr.mUvcVideo_Height;
pstFrameInfo->VFrame.mStride[0] = buffer.bytesused;
pstFrameInfo->VFrame.mpVirAddr[0] = pUvcChnManager->mpVideoBuffer[buffer.index];
#endif
bResult = SUCCESS;
}
else if(V4L2_PIX_FMT_YUYV == pUvcChnManager->mUvcAttr.mPixelformat)
{
pUvcChnManager->mUvcCaptureFrame[buffer.index].mId = buffer.index;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mpts = (int64_t)buffer.timestamp.tv_sec * 1000000LL + buffer.timestamp.tv_usec;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mPixelFormat = map_V4L2_PIX_FMT_to_PIXEL_FORMAT_E(pUvcChnManager->mUvcAttr.mPixelformat); //MM_PIXEL_FORMAT_YUV_SEMIPLANAR_422;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mField = VIDEO_FIELD_FRAME;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mWidth = pUvcChnManager->mUvcAttr.mUvcVideo_Width;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mHeight = pUvcChnManager->mUvcAttr.mUvcVideo_Height;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mOffsetTop = 0;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mOffsetBottom = pUvcChnManager->mUvcAttr.mUvcVideo_Height;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mOffsetLeft = 0;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mOffsetRight = pUvcChnManager->mUvcAttr.mUvcVideo_Width;
/*yuv422pa_yuv422sp(pUvcChnManager->mpVideoBuffer[buffer.index],
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mpVirAddr[0],
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mpVirAddr[1],
pUvcChnManager->mUvcAttr.mUvcVideo_Width,
pUvcChnManager->mUvcAttr.mUvcVideo_Height);
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mStride[0] = pUvcChnManager->mUvcAttr.mUvcVideo_Width * pUvcChnManager->mUvcAttr.mUvcVideo_Height;
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mStride[1] = pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mStride[0];
*/
memcpy(pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mpVirAddr[0], pUvcChnManager->mpVideoBuffer[buffer.index], pUvcChnManager->mBufferLength);
pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mStride[0] = pUvcChnManager->mBufferLength;
ion_flushCache(pUvcChnManager->mUvcCaptureFrame[buffer.index].VFrame.mpVirAddr[0], pUvcChnManager->mBufferLength);
*pstFrameInfo = pUvcChnManager->mUvcCaptureFrame[buffer.index];
bResult = SUCCESS;
}
else if(V4L2_PIX_FMT_NV12 == pUvcChnManager->mUvcAttr.mPixelformat)
{
aloge("sorry, this version do not support the V4L2_PIX_FMT_NV12 for UVC!!!");
}
}
else
{
aloge("fatal error! why dqueue success, but index[%d] >=[%d]?", buffer.index, BUFFER_COUNT);
}
return bResult;
}
ERRORTYPE uvcInput_ReleaseData2(UvcChnManager *pUvcChnManager, int buffer_index)
{
ERRORTYPE bResult = FAILURE;
int uvc_fd = pUvcChnManager->mFd;
if(ioctl(uvc_fd, VIDIOC_QBUF, &pUvcChnManager->mUvcV4l2BufferInfo[buffer_index]) < 0)
{
aloge("the %s UVC can not query %d buffer, %s", pUvcChnManager->mUvcDevName, buffer_index, strerror(errno));
return bResult;
}
bResult = SUCCESS;
return bResult;
}
static ERRORTYPE uvcInput_ReleaseData(UVC_DEV UvcDev, VIDEO_FRAME_INFO_S *pstFrameInfo)
{
ERRORTYPE bResult = FAILURE;
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);
UvcChnManager **ppUvcChnManager = NULL;
if(uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager) != SUCCESS)
{
aloge("fatal error! can not found %s UVC", UvcDev);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
bResult = uvcInput_ReleaseData2(*ppUvcChnManager, pstFrameInfo->mId);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
ERRORTYPE uvcInput_RefsReduceAndRleaseData2(UvcChnManager *pUvcChnManager, VIDEO_FRAME_INFO_S *pstFrameInfo)
{
ERRORTYPE bResult = SUCCESS;
pthread_mutex_lock(&pUvcChnManager->mRefsLock);
if(pUvcChnManager->mRefs[pstFrameInfo->mId] <= 0)
{
aloge("fatal error! %s UVC, idx[%d]: ref=[%d] when reduce refs, check code!",
pUvcChnManager->mUvcDevName, pstFrameInfo->mId,
pUvcChnManager->mRefs[pstFrameInfo->mId] );
}
pUvcChnManager->mRefs[pstFrameInfo->mId]--;
int refs = pUvcChnManager->mRefs[pstFrameInfo->mId];
if(0 == refs)
{
bResult = uvcInput_ReleaseData2(pUvcChnManager, pstFrameInfo->mId);
}
pthread_mutex_unlock(&pUvcChnManager->mRefsLock);
return bResult;
}
ERRORTYPE uvcInput_RefsReduceAndRleaseData(UVC_DEV UvcDev, VIDEO_FRAME_INFO_S *pstFrameInfo)
{
ERRORTYPE bResult = FAILURE;
pthread_mutex_lock(&gpUvcDevManager->mUvcDevManagerLock);
UvcChnManager **ppUvcChnManager = NULL;
if(uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager) != SUCCESS)
{
aloge("fatal error! can not found %s UVC", UvcDev);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
bResult = uvcInput_RefsReduceAndRleaseData2(*ppUvcChnManager, pstFrameInfo);
pthread_mutex_unlock(&gpUvcDevManager->mUvcDevManagerLock);
return bResult;
}
static void *uvcInput_CapThread(void *pThreadData)
{
UvcChnManager *pUvcChnManager = (UvcChnManager *)pThreadData;
if(NULL == pUvcChnManager)
{
aloge("fatal error, the UvcChnManager is NULL");
return NULL;
}
VIDEO_FRAME_INFO_S pstFrameInfo;
int nMilliSec = 200;
int num_buf = pUvcChnManager->mUvcAttr.mUvcVideo_BufCnt;
int i, ret;
prctl(PR_SET_NAME, "UVCCaptureThread", 0, 0, 0);
alogw("loop uvcInput_CapThread the UVC name is %s , fd = %d", pUvcChnManager->mUvcDevName, pUvcChnManager->mFd);
while(1)
{
if(0 == pUvcChnManager->mUvcDevEnable) //disable the UVC
{
while(1)
{
if(list_empty(&pUvcChnManager->mChnList))
{
break;
}
usleep(100000);
alogd("Virvi Com not exit !!!");
}
for(i = 0; i < num_buf; i++)
{
if(0 != pUvcChnManager->mRefs[i])
{
alogd("fatal error! Virvi Com not return all yuv frame !!! ");
uvcInput_ReleaseData2(pUvcChnManager, i);
pUvcChnManager->mRefs[i] = 0;
}
}
break;
}
memset(&pstFrameInfo, 0, sizeof pstFrameInfo);
if(SUCCESS == uvcInput_GetData2(pUvcChnManager, &pstFrameInfo, nMilliSec))
{
//alogw("get one frame[%d]!", pstFrameInfo.mId);
UVC_CHN_MAP_S *pEntry;
pthread_mutex_lock(&pUvcChnManager->mLock);
if(0 == pUvcChnManager->mRefs[pstFrameInfo.mId])
{
if(list_empty(&pUvcChnManager->mChnList))
{
aloge("the %s UVC, No Virvi Component, drop this one yuv data.", pUvcChnManager->mUvcDevName);
uvcInput_ReleaseData2(pUvcChnManager, pstFrameInfo.mId);
pthread_mutex_unlock(&pUvcChnManager->mLock);
continue;
}
pthread_mutex_lock(&pUvcChnManager->mRefsLock);
pUvcChnManager->mRefs[pstFrameInfo.mId]++;
pthread_mutex_unlock(&pUvcChnManager->mRefsLock);
list_for_each_entry(pEntry, &pUvcChnManager->mChnList, mList)
{
COMP_BUFFERHEADERTYPE bufferHeader;
bufferHeader.nInputPortIndex = UVC_CHN_PORT_INDEX_NCOM_IN;
bufferHeader.pOutputPortPrivate = &pstFrameInfo;
pthread_mutex_lock(&pUvcChnManager->mRefsLock);
pUvcChnManager->mRefs[pstFrameInfo.mId]++;
pthread_mutex_unlock(&pUvcChnManager->mRefsLock);
ret =pEntry->mUvcComp->EmptyThisBuffer(pEntry->mUvcComp, &bufferHeader);
if(ret != SUCCESS)
{
pthread_mutex_lock(&pUvcChnManager->mRefsLock);
pUvcChnManager->mRefs[pstFrameInfo.mId]--;
pthread_mutex_unlock(&pUvcChnManager->mRefsLock);
}
}
//uvcInput_ReleaseData2(pUvcChnManager, pstFrameInfo.mId);
uvcInput_RefsReduceAndRleaseData2(pUvcChnManager, &pstFrameInfo);
}
else
{
aloge("fatal error! the %s UVC buf not return, refs id = %d,buffer index = %d, drop this yuv data",
pUvcChnManager->mUvcDevName, pUvcChnManager->mRefs[pstFrameInfo.mId],
pstFrameInfo.mId);
uvcInput_ReleaseData2(pUvcChnManager, pstFrameInfo.mId);
}
pthread_mutex_unlock(&pUvcChnManager->mLock);
}
else
{
//usleep(40000);
continue;
}
}
return NULL;
}
static ERRORTYPE set_uvc_control(int fd, int cmd_id, int set_value, const char *cmd_name)
{
ERRORTYPE bResult = FAILURE;
struct v4l2_queryctrl queryctrl;
memset(&queryctrl, 0, sizeof queryctrl);
if(uvc_query(fd, cmd_id, cmd_name, &queryctrl) != SUCCESS)
{
aloge("fatal error! the UVC maybe can not support %s set!", cmd_name);
return bResult;
}
if(set_value > queryctrl.maximum && set_value < queryctrl.minimum)
{
aloge("fatal error!, the set %s value %d had not in range[%d %d]", cmd_name, set_value, queryctrl.minimum, queryctrl.maximum);
return bResult;
}
struct v4l2_control control;
memset(&control, 0, sizeof control);
control.id = cmd_id;
control.value = set_value;
if(ioctl(fd, VIDIOC_S_CTRL, &control) < 0)
{
aloge("error! failed to set %s to %d, %s", cmd_name, set_value, strerror(errno));
return bResult;
}
return SUCCESS;
}
static ERRORTYPE get_uvc_control(int fd, int cmd_id, int *get_value, const char *cmd_name)
{
ERRORTYPE bResult = FAILURE;
struct v4l2_queryctrl queryctrl;
memset(&queryctrl, 0, sizeof queryctrl);
if(uvc_query(fd, cmd_id, cmd_name, &queryctrl) != SUCCESS)
{
aloge("fatal error! this UVC camera do not support %s ", cmd_name);
return bResult;
}
struct v4l2_control control;
memset(&control, 0, sizeof control);
control.id = cmd_id;
if(ioctl(fd, VIDIOC_G_CTRL, &control) < 0)
{
aloge("error! failed to get %s, %s", cmd_name, strerror(errno));
return bResult;
}
*get_value = control.value;
return SUCCESS;
}
ERRORTYPE uvcInput_SetControl(UVC_DEV UvcDev, int cmd_id, int set_value, const char *cmd_name)
{
UvcChnManager **ppUvcChnManager = NULL;
if(uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager) != SUCCESS)
{
aloge("fatal error! can not found %s UVC", UvcDev);
return FAILURE;
}
UvcChnManager *pUvcChnManager = *ppUvcChnManager;
int uvc_fd = pUvcChnManager->mFd;
return set_uvc_control(uvc_fd, cmd_id, set_value, cmd_name);
}
ERRORTYPE uvcInput_GetControl(UVC_DEV UvcDev, int cmd_id, int *get_value, const char *cmd_name)
{
UvcChnManager **ppUvcChnManager = NULL;
if(uvcInput_SearchExitDev(UvcDev, &ppUvcChnManager) != SUCCESS)
{
aloge("fatal error! can not found %s UVC", UvcDev);
return FAILURE;
}
UvcChnManager *pUvcChnManager = *ppUvcChnManager;
int uvc_fd = pUvcChnManager->mFd;
return get_uvc_control(uvc_fd, cmd_id, get_value, cmd_name);
}