V4L2从摄像头取数据
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <linux/fb.h>
#include <linux/videodev.h>
#include "hi_unf_common.h"
#include "hi_unf_avplay.h"
#include "hi_unf_sound.h"
#include "hi_unf_disp.h"
#include "hi_unf_vo.h"
#include "hi_unf_vi.h"
#include "hi_unf_venc.h"
#include "hi_unf_demux.h"
#include "hi_unf_hdmi.h"
#include "hi_unf_ecs.h"
#include "hi_adp.h"
#include "hi_adp_audio.h"
#include "hi_adp_hdmi.h"
//#include "hi_adp_boardcfg.h"
//#include "hi_adp_mpi.h"
//#include "hi_adp_tuner.h"
#include "porting_camera.h"
#include "porting_debug.h"
#include "porting_vout.h"
/******************************************************************
********************** USB CAM ************************************
******************************************************************/
#define CAM_FPS 30
#define SAMPLE_USB_CAM_BUFFER_NUM 6
#define SAMPLE_VI_USB_CAM_WIDTH 640
#define SAMPLE_VI_USB_CAM_HEIGHT 480
typedef struct UsbCamBuffer
{
void *pAddr;
UINT32_T length;
}USB_CAM_Buffer_S;
typedef struct hiUSB_CAM_THREAD_ARG_S
{
UINT32_T hVi;
UINT32_T u32USBCamFmt;
int UsbCamFd;
}USB_CAM_THREAD_ARG_S;
typedef struct hiVENC_THREAD_ARG_S
{
UINT32_T hVenc;
UINT32_T hAvplayForVdec;
FILE *pFileToSave;
}VENC_THREAD_ARG_S;
USB_CAM_Buffer_S UsbCamBuff[SAMPLE_USB_CAM_BUFFER_NUM];
USB_CAM_THREAD_ARG_S g_stUSBCamArgs;
static char *UsbCamDev = "/dev/video0";
static char *TmpCamDev = "/dev/video1";
static pthread_t g_thCAMVi = 0;//VI线程标志符
static pthread_t g_thCAMVenc = 0;;//Venc线程标志符
static HI_BOOL g_whCAMVi, g_whCAMVenc;//控制线程函数的循环
static HI_HANDLE g_hCAMVi;//VI句柄
static HI_HANDLE g_hCAMVenc;//编码器句柄
static HI_BOOL CleanBuf = HI_FALSE;//请buffer标志
static HI_BOOL g_ReadStop = HI_FALSE, writing0=HI_FALSE, writing1=HI_FALSE;
static HI_HANDLE g_Winhdl=0;
//循环buffer用
#define LOOP_BUFF_SIZE (1024*128) //128KB
#define min(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; })
static struct loop_bufCAM {
pthread_mutex_t mutex;
unsigned char buffer[LOOP_BUFF_SIZE]; //数组,不用通过free()释放
unsigned int in;
unsigned int out;
}CAM_buf,*PCAM_buf=&CAM_buf;
/*local function*/
static void* VencRoutine(void* args);
int init_loop_bufCAM(struct loop_bufCAM *buf)
{
memset(buf->buffer, 0, LOOP_BUFF_SIZE);
buf->in = buf->out = 0;
pthread_mutex_init(&buf->mutex,NULL);
return 0;
}
UINT32_T UsbCamDeinit(USB_CAM_THREAD_ARG_S *pArgs);
HI_HANDLE camera_attach_window(HI_HANDLE vihandle);
void camera_detach_window(HI_HANDLE vihandle);
void porting_camera_set_location_by_rect(void *arg);
unsigned int put_loop_bufCAM(struct loop_bufCAM *buf, unsigned char *buffer, unsigned int len)
{
unsigned int l;
len = min(len, LOOP_BUFF_SIZE - buf->in + buf->out);
/* first put the data starting from buf->in to buffer end */
l = min(len, LOOP_BUFF_SIZE - (buf->in & (LOOP_BUFF_SIZE - 1)));
memcpy(buf->buffer + (buf->in & (LOOP_BUFF_SIZE - 1)), buffer, l);
/* then put the rest (if any) at the beginning of the buffer */
memcpy(buf->buffer, buffer + l, len - l);
buf->in += len;
// printf("len=%d, buf->in = %d, buf->out=%d \n",len, buf->in, buf->out);
if(buf->in == LOOP_BUFF_SIZE)
{
buf->in = 0;
}
return len;
}
unsigned int get_loop_bufCAM(struct loop_bufCAM *buf, unsigned char *buffer, unsigned int len)
{
unsigned int l;
len = min(len, buf->in - buf->out);
// printf("len=%d,buf->in=%d,buf->out=%d\n",len,buf->in,buf->out);
/* first get the data from buf->out until the end of the buffer */
l = min(len, LOOP_BUFF_SIZE - (buf->out & (LOOP_BUFF_SIZE - 1)));
memcpy(buffer, buf->buffer + (buf->out & (LOOP_BUFF_SIZE - 1)), l);
/* then get the rest (if any) from the beginning of the buffer */
memcpy(buffer + l, buf->buffer, len - l);
buf->out += len;
if (buf->out == buf->in )
buf->out=buf->in = 0;
return len;
}
void lock_bufCAM(struct loop_bufCAM *buf)
{
pthread_mutex_lock(&buf->mutex);
}
void unlock_bufCAM(struct loop_bufCAM *buf)
{
pthread_mutex_unlock(&buf->mutex);
}
void release_loop_bufCAM(struct loop_bufCAM *buf)
{
pthread_mutex_destroy(&buf->mutex);
}
//循环buffer用
int porting_camera_init(void)
{
// printf("#######porting_camera_init()in------------>######## \n");
HISI_INFO(MODULE_PRINT_CAM, "(in)");
CHECK_MODULE_INIT_STATUS(PORT_MODULE_CAM);
SET_MODULE_INIT_STATUS(PORT_MODULE_CAM);
HISI_INFO(MODULE_PRINT_CAM,"(out)");
return IPANEL_OK;
}
int porting_camera_exit(void)
{
HISI_INFO(MODULE_PRINT_CAM, "(in)");
CHECK_MODULE_EXIT_STATUS(PORT_MODULE_CAM);
SET_MODULE_EXIT_STATUS(PORT_MODULE_CAM);
HISI_INFO(MODULE_PRINT_CAM,"(out)");
return IPANEL_OK;
}
//打开摄像头采集数据
UINT32_T ipanel_porting_camera_open(IPANEL_VCODEC_TYPE_E type)
{
HISI_INFO(MODULE_PRINT_CAM, "(in)");
INT32_T ret;
INT32_T s32ViPort = HI_UNF_VI_PORT1;
HI_UNF_VCODEC_TYPE_E enVencFmt = HI_UNF_VCODEC_TYPE_H264;
HI_UNF_VI_INPUT_MODE_E enViMode = HI_UNF_VI_MODE_USB_CAM;
if(type != IPANEL_VCODEC_TYPE_H264)
{
HISI_INFO(PORT_MODULE_CAM, "open type is not h264");
}
/*启动视频采集与编码*/
HIAPI_RUN(VIVenc_Init(s32ViPort, enViMode, &g_hCAMVi, enVencFmt, &g_hCAMVenc), ret);
if(ret ==HI_FAILURE)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)VIVenc_Init failed!!!");
return IPANEL_NULL;
}
g_whCAMVenc=HI_TRUE;//控制线程读取数据的while循环
// pthread_create(&g_thCAMVenc, HI_NULL, VencRoutine, (void*)(&g_hCAMVenc));
if(g_thCAMVenc == 0)
{
g_thCAMVenc = ipanel_porting_task_create("venc", VencRoutine, (void*)(&g_hCAMVenc), 5, 0x4000);
if(g_thCAMVenc == 0)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)task create failed");
goto LAB_ERR;
}
}
else
{
HISI_ERR(MODULE_PRINT_CAM, "(err)task exist");
goto LAB_ERR;
}
init_loop_bufCAM(PCAM_buf);
HISI_INFO(MODULE_PRINT_CAM, "(out)");
return g_hCAMVi;
LAB_ERR:
return -1;
}
/*
功能:读取视频数据
参数:
handle:设备句柄
buf:用于读取数据的buffer
len:要读取的数据长度
返回值:
实际读取到的数据长度。
*/
INT32_T ipanel_porting_camera_read(UINT32_T handle,unsigned char *buf,INT32_T len)
{
UINT32_T length = 0;
if(handle != g_hCAMVi)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)invalid handle 0x%x", handle);
return IPANEL_ERR;
}
HISI_INFO(MODULE_PRINT_CAM, "(in)");
#if 1
if(writing0 || writing1)//当有数据往循环buffer中写的时候,不读数据
{
goto LAB_OK;
}
if(!g_ReadStop)//在ioctl中控制停止和开始读数据
{
lock_bufCAM(PCAM_buf);
length=get_loop_bufCAM(PCAM_buf, buf, len);
unlock_bufCAM(PCAM_buf);
}
#else
HI_S32 ret = HI_FAILURE;
HI_UNF_VENC_STREAM_S vencStream;
ret = HI_UNF_VENC_AcquireStream(g_hCAMVenc, &vencStream, 0);
if(HI_SUCCESS != ret)
{
goto LAB_OK;
}
if(vencStream.u32SlcLen[0] > 0)
{
memcpy(buf, vencStream.pu8Addr[0], vencStream.u32SlcLen[0]);
length += vencStream.u32SlcLen[0];
}
if (vencStream.u32SlcLen[1] > 0)
{
memcpy(buf+length, vencStream.pu8Addr[1], vencStream.u32SlcLen[1]);
length += vencStream.u32SlcLen[1];
}
ret = HI_UNF_VENC_ReleaseStream(g_hCAMVenc, &vencStream);
if(HI_SUCCESS!=ret)
{
HISI_ERR(MODULE_PRINT_CAM, "HI_UNF_VENC_ReleaseStream fail!!! ret=0x%x",ret);
}
#endif
LAB_OK:
HISI_INFO(MODULE_PRINT_CAM, "(out)len:%d", length);
return length;
}
/********************************************************************************************************
功能:对视频采集设备实例进行一个操作,或者用于设置和获取视频采集设备实例的参数和属性
原型:INT32_T ipanel_porting_camera_ioctl(UINT32_T handle, IPANEL_CAMERA_IOCTL_e op, VOID * arg)
参数说明:
输入参数:
handle -- 视频采集设备实例句柄
op -- 操作命令
typedef enum
{
IPANEL_CAMERA_START = 1,
IPANEL_CAMERA_STOP = 2,
IPANEL_CAMERA_CLEAR_BUFFER = 3,
IPANEL_CAMERA_SET_PARAM = 4,
IPANEL_CAMERA_2_GRAPHIC_BUFFER = 5,
IPANEL_GRAPHIC_BUFFER_2_CAMERA = 6
} IPANEL_CAMERA_IOCTL_e;
arg -- 操作命令所带的参数,当传递枚举型或32位整数值时,arg可强制转换成对应数据类型。
op, arg取值见下表:
+---------------------+-------------------------+-----------------------------+
| op | arg | 说明 |
+---------------------+-------------------------+-----------------------------+
| IPANEL_CAMERA_START |IPANEL_NULL |启动视频采集。 |
+---------------------+-------------------------+-----------------------------+
| IPANEL_CAMERA_STOP |IPANEL_NULL |停止视频采集。 |
+---------------------+-------------------------+-----------------------------+
| IPANEL_CAMERA_ |IPANEL_NULL |清空视频采集缓存 |
| CLEAR_BUFFER | | |
+---------------------+-------------------------+-----------------------------+
| IPANEL_CAMERA_ |指向 |设置视频采集参数 |
| SET_PARAM |IPANEL_CAMERA_PARAMS_s | |
| |结构的指针。 | |
| |typedef struct | |
| |{ | |
| |UINT32_T camera_flag; | |
| |UINT32_T width;//要求采集的视频源宽度 |
| |UINT32_T height;//要求采集的视频源高度 |
| |IPANEL_VIDEO_STREAM_TYPE_e streamType;//要求采集的视频编码格式
| |UINT32_T frameRate;//要求采集的视频帧率 |
| |} IPANEL_CAMERA_PARAMS_s;| |
+---------------------+-------------------------+-----------------------------+
输出参数:无
返 回:
IPANEL_OK:成功
IPANEL_ERR:失败
********************************************************************************************************/
INT32_T ipanel_porting_camera_ioctl(UINT32_T handle,IPANEL_CAMERA_IOCTL_e op, VOID *arg)
{
HISI_INFO(MODULE_PRINT_CAM, "(in)op=%d",op);
if(handle != g_hCAMVi)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)invalid handle 0x%x", handle);
return IPANEL_ERR;
}
switch(op)
{
case IPANEL_CAMERA_START:
PCAM_buf->in = PCAM_buf->out = 0;
g_ReadStop=0;
usleep(50);
HISI_INFO(MODULE_PRINT_CAM, "IPANEL_CAMERA_START");
break;
case IPANEL_CAMERA_STOP:
g_ReadStop=1;
memset(PCAM_buf->buffer, 0, LOOP_BUFF_SIZE);
PCAM_buf->in = PCAM_buf->out = 0;
usleep(200);
HISI_INFO(MODULE_PRINT_CAM, "IPANEL_CAMERA_STOP");
break;
case IPANEL_CAMERA_CLEAR_BUFFER:
CleanBuf = HI_TRUE;
usleep(200);
memset(PCAM_buf->buffer, 0, LOOP_BUFF_SIZE);
PCAM_buf->in = PCAM_buf->out = 0;
CleanBuf = HI_FALSE;
HISI_INFO(MODULE_PRINT_CAM, "IPANEL_CAMERA_CLEAR_BUFFER");
break;
case IPANEL_CAMERA_SET_DISPLAY_RECT:
//设置视频窗口位置
HISI_INFO(PORT_MODULE_CAM, "set location");
porting_camera_set_location_by_rect(arg);
break;
default:
HISI_INFO(MODULE_PRINT_CAM, "no suppose now ...");
break;
}
LAB_OK:
HISI_INFO(MODULE_PRINT_CAM, "(out)");
return IPANEL_OK;
}
//关闭摄像头采集数据。
INT32_T ipanel_porting_camera_close(UINT32_T handle)
{
HISI_INFO(MODULE_PRINT_CAM, "(in)");
int ret=-1;
if(handle != g_hCAMVi)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)invalid handle 0x%x", handle);
return IPANEL_ERR;
}
g_whCAMVenc = HI_FALSE;
g_whCAMVi = HI_FALSE;
if(g_thCAMVenc!=0)
{
ret = ipanel_porting_task_destroy(g_thCAMVenc);
if(ret==0)
{
g_thCAMVenc = 0;
}
else
{
goto LAB_ERR;
}
}
else
{
goto LAB_ERR;
}
UsbCamDeinit(&g_stUSBCamArgs);
release_loop_bufCAM(PCAM_buf);
HI_ADP_VIVENC_DeInit(g_hCAMVi,g_hCAMVenc);
HISI_INFO(MODULE_PRINT_CAM, "(out)");
return IPANEL_OK;
LAB_ERR:
HISI_INFO(MODULE_PRINT_CAM, "(err)");
return -1;
}
INT32_T ipanel_porting_camera_set_notify(UINT32_T handle, IPANEL_CAMERA_NOTIFY fuc)
{
return 0;
}
UINT32_T porting_getVIhandle()
{
return g_hCAMVi;
}
static void* VencRoutine(void* args)
{
HI_S32 ret = HI_FAILURE;
HI_UNF_VENC_STREAM_S vencStream;
HI_HANDLE hVenc = *(HI_HANDLE*)args;
while(g_whCAMVenc)
{
if(HI_TRUE == CleanBuf)
{
usleep(1000*10);
continue;
}
ret = HI_UNF_VENC_AcquireStream(hVenc, &vencStream, 0);
if(HI_SUCCESS != ret)
{
usleep(10*1000);//10*1000
continue;
}
if(!g_ReadStop)
{
if(vencStream.u32SlcLen[0] > 0)
{
writing0=1;
lock_bufCAM(PCAM_buf);
put_loop_bufCAM(PCAM_buf, vencStream.pu8Addr[0], vencStream.u32SlcLen[0]);
unlock_bufCAM(PCAM_buf);
writing0=0;
}
if (vencStream.u32SlcLen[1] > 0)
{
writing1=1;
lock_bufCAM(PCAM_buf);
put_loop_bufCAM(PCAM_buf, vencStream.pu8Addr[1], vencStream.u32SlcLen[1]);
unlock_bufCAM(PCAM_buf);
writing1=0;
}
}
else
{
usleep(300);
}
ret = HI_UNF_VENC_ReleaseStream(hVenc, &vencStream);
if(HI_SUCCESS!=ret)
{
HISI_ERR(MODULE_PRINT_CAM, "HI_UNF_VENC_ReleaseStream fail!!! ret=0x%x",ret);
}
}
HISI_INFO(MODULE_PRINT_CAM, "out of the while of g_whCAMVenc");
return NULL;
}
/*********************************************************************
******************************* USB cam *****************************
**********************************************************************/
UINT32_T UsbCamInit(USB_CAM_THREAD_ARG_S *pArgs)
{
INT32_T s32Ret,i;
struct v4l2_format fmt;
struct v4l2_buffer buf;
struct v4l2_capability cap;
struct v4l2_requestbuffers rb;
struct v4l2_streamparm *setfps;
enum v4l2_buf_type type;
INT32_T fps=CAM_FPS;
int fdUsbCam;
HI_UNF_VI_ATTR_S stViAttr;
HISI_INFO(MODULE_PRINT_CAM, "(in)");
//检查设备是否存在
s32Ret = access(UsbCamDev,F_OK);
if(IPANEL_OK != s32Ret)
{
s32Ret = access(TmpCamDev,F_OK);
if(IPANEL_OK != s32Ret)
{
HISI_INFO(PORT_MODULE_CAM, "(err)not found the device of video!!!");
return IPANEL_ERR;
}
}
fdUsbCam = open(UsbCamDev, O_RDWR | O_NONBLOCK, 0);//打开设备
if(-1 == fdUsbCam)
{
HISI_INFO(PORT_MODULE_CAM, "open %s failed!!!",UsbCamDev);
fdUsbCam = open(TmpCamDev,O_RDWR | O_NONBLOCK ,0);
if(HI_FAILURE == fdUsbCam)
{
HISI_ERR(PORT_MODULE_CAM, "open %s failed!!!",TmpCamDev);
return IPANEL_ERR;
}
HISI_INFO(PORT_MODULE_CAM, "open %s Ok.", TmpCamDev);
}
else
{
HISI_INFO(PORT_MODULE_CAM, "open %s Ok.", UsbCamDev);
}
s32Ret = ioctl(fdUsbCam, VIDIOC_QUERYCAP, &cap);
if (s32Ret < 0)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)Error opening device %s: unable to query device.",device_name);
return -1;
}
HISI_INFO(MODULE_PRINT_CAM, "usb cam cap:0x%x.", cap.capabilities);
if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0)
{
HISI_ERR(MODULE_PRINT_CAM,"(err)Error opening device %s: video capture not supported.",device_name);
return -1;
}
if (!(cap.capabilities & V4L2_CAP_STREAMING))
{
HISI_ERR(MODULE_PRINT_CAM, "(err)%s Not support streaming i/o", device_name);
return -1;
}
/* test format if it support */
memset(&fmt, 0, sizeof(struct v4l2_format));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fdUsbCam, VIDIOC_G_FMT, &fmt) < 0)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)get format failed\n");
return -1;
}
else
{
HISI_INFO(MODULE_PRINT_CAM, "USB CAM's orignal FMT:");
HISI_INFO(MODULE_PRINT_CAM, "Width = %d", fmt.fmt.pix.width);
HISI_INFO(MODULE_PRINT_CAM, "Height = %d", fmt.fmt.pix.height);
HISI_INFO(MODULE_PRINT_CAM, "Image size = %d", fmt.fmt.pix.sizeimage);
HISI_INFO(MODULE_PRINT_CAM, "pixelformat = %d", fmt.fmt.pix.pixelformat);
HISI_INFO(MODULE_PRINT_CAM, "field = %d", fmt.fmt.pix.field);
if(V4L2_PIX_FMT_MJPEG == fmt.fmt.pix.pixelformat)
{
HISI_INFO(MODULE_PRINT_CAM, "V4L2_PIX_FMT_MJPEG\r");
}
else if(V4L2_PIX_FMT_YUYV == fmt.fmt.pix.pixelformat)
{
HISI_INFO(MODULE_PRINT_CAM, "V4L2_PIX_FMT_YUYV\r");
}
else
{
HISI_INFO(MODULE_PRINT_CAM, "fmt unknown\r");
}
pArgs->u32USBCamFmt = fmt.fmt.pix.pixelformat;
}
#if 1
/* set format in */
fmt.fmt.pix.width = SAMPLE_VI_USB_CAM_WIDTH;
fmt.fmt.pix.height = SAMPLE_VI_USB_CAM_HEIGHT;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
s32Ret = ioctl(fdUsbCam, VIDIOC_S_FMT, &fmt);
if (s32Ret < 0)
{
printf("Unable to set format: %d, err:%d.\n",fmt.fmt.pix.pixelformat, errno);
return s32Ret;
}
if (ioctl(fdUsbCam, VIDIOC_G_FMT, &fmt) < 0)
{
printf("get format failed\n");
return -1;
}
else
{
HISI_INFO(MODULE_PRINT_CAM, "After set attr:");
HISI_INFO(MODULE_PRINT_CAM, "Width = %d", fmt.fmt.pix.width);
HISI_INFO(MODULE_PRINT_CAM, "Height = %d", fmt.fmt.pix.height);
HISI_INFO(MODULE_PRINT_CAM, "Image size = %d", fmt.fmt.pix.sizeimage);
HISI_INFO(MODULE_PRINT_CAM, "pixelformat = %d", fmt.fmt.pix.pixelformat);
if(V4L2_PIX_FMT_MJPEG == fmt.fmt.pix.pixelformat)
{
HISI_INFO(MODULE_PRINT_CAM, "V4L2_PIX_FMT_MJPEG\r");
}
else if(V4L2_PIX_FMT_YUYV == fmt.fmt.pix.pixelformat)
{
HISI_INFO(MODULE_PRINT_CAM, "V4L2_PIX_FMT_YUYV\r");
}
else
{
printf("fmt unknown\r\n");
}
}
#endif
setfps=(struct v4l2_streamparm *) calloc(1, sizeof(struct v4l2_streamparm));
memset(setfps, 0, sizeof(struct v4l2_streamparm));
setfps->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
s32Ret = ioctl(fdUsbCam, VIDIOC_G_PARM, setfps);
if(s32Ret == 0)
{
HISI_INFO(MODULE_PRINT_CAM,"Frame rate: %u/%u",
setfps->parm.capture.timeperframe.denominator, setfps->parm.capture.timeperframe.numerator);
}
else
{
HISI_ERR(MODULE_PRINT_CAM, "(err)Unable to read out current frame rate");
return -1;
}
if (setfps->parm.capture.timeperframe.numerator == 1
&& setfps->parm.capture.timeperframe.denominator == fps)
{
; /* OK ,fps is aready the value we want */
}
else
{
/* set framerate */
setfps->parm.capture.timeperframe.numerator=1;
setfps->parm.capture.timeperframe.denominator=fps; //
s32Ret = ioctl(fdUsbCam, VIDIOC_S_PARM, setfps);
if(s32Ret == -1)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)Unable to set frame rate");
return s32Ret;
}
s32Ret = ioctl(fdUsbCam, VIDIOC_G_PARM, setfps);
if(s32Ret == 0)
{
if (setfps->parm.capture.timeperframe.numerator != 1 ||setfps->parm.capture.timeperframe.denominator != fps)
{
HISI_INFO(MODULE_PRINT_CAM, "Frame rate: %u/%u fps (requested frame rate %u fps is not supported by device)",
setfps->parm.capture.timeperframe.denominator,
setfps->parm.capture.timeperframe.numerator, fps);
}
else
{
HISI_INFO(MODULE_PRINT_CAM, "Frame rate: %d fps", fps);
}
}
else
{
HISI_ERR(MODULE_PRINT_CAM, "(err)Unable to read out current frame rate");
return -1;
}
}
HISI_INFO(MODULE_PRINT_CAM, "USB CAM's output mode: %d", setfps->parm.output.outputmode);
/* request buffers */
memset(&rb, 0, sizeof(struct v4l2_requestbuffers));
rb.count = SAMPLE_USB_CAM_BUFFER_NUM;
rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
rb.memory = V4L2_MEMORY_MMAP;
s32Ret = ioctl(fdUsbCam, VIDIOC_REQBUFS, &rb);
if (s32Ret < 0)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)Unable to allocate buffers: %d.", errno);
return s32Ret;
}
/* map the buffers */
for (i = 0; i < SAMPLE_USB_CAM_BUFFER_NUM; i++)
{
memset(&buf, 0, sizeof(struct v4l2_buffer));
buf.index = i;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
s32Ret = ioctl(fdUsbCam, VIDIOC_QUERYBUF, &buf);
if (s32Ret < 0)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)Unable to query buffer (%d).", errno);
return s32Ret;
}
HISI_INFO(MODULE_PRINT_CAM, "USB CAM's buffer length: %u offset: %u", buf.length, buf.m.offset);
UsbCamBuff[i].length = buf.length;
UsbCamBuff[i].pAddr = mmap(NULL,buf.length, PROT_READ|PROT_WRITE, MAP_SHARED,fdUsbCam,buf.m.offset);
if (UsbCamBuff[i].pAddr == MAP_FAILED)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)Unable to map buffer (%d)", errno);
return -1;
}
HISI_INFO(MODULE_PRINT_CAM, "USB CAM Buffer %d mapped at address %p.", i, UsbCamBuff[i].pAddr);
}
HISI_INFO(MODULE_PRINT_CAM, "pArg->hVi %d",pArgs->hVi);
s32Ret = HI_UNF_VI_GetAttr(pArgs->hVi,&stViAttr);
if(HI_SUCCESS == s32Ret)
{
for(i=0;i<SAMPLE_USB_CAM_BUFFER_NUM;i++)
{
stViAttr.u32ViBufAddr = (HI_U32)UsbCamBuff[i].pAddr;
stViAttr.u32BufNum = i;
HISI_INFO(MODULE_PRINT_CAM, "654321stViAttr Buffer %p stViAttr enViPort 0X%x ,BUF_MGMT_E %d",\
stViAttr.u32ViBufAddr,stViAttr.enViPort,stViAttr.enBufMgmtMode);
s32Ret = HI_UNF_VI_SetAttr(pArgs->hVi,&stViAttr);
if(HI_SUCCESS != s32Ret)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)Unable to set vi buffer (%x).", s32Ret);
return s32Ret;
}
}
}
/* Queue the buffers. */
for (i = 0; i < SAMPLE_USB_CAM_BUFFER_NUM; ++i)
{
memset(&buf, 0, sizeof(struct v4l2_buffer));
buf.index = i;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
s32Ret = ioctl(fdUsbCam, VIDIOC_QBUF, &buf);
if (s32Ret < 0)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)Unable to queue buffer (%d).", errno);
return s32Ret;
}
}
/*start camera capture */
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
s32Ret = ioctl(fdUsbCam, VIDIOC_STREAMON, &type);
if (s32Ret < 0)
{
HISI_ERR(MODULE_PRINT_CAM, "(err)Unable to streamon (%d).", errno);
return s32Ret;
}
pArgs->UsbCamFd = fdUsbCam;
camera_attach_window(pArgs->hVi);
HISI_INFO(MODULE_PRINT_CAM,"(out)");
return HI_SUCCESS;
}
UINT32_T UsbCamDeinit(USB_CAM_THREAD_ARG_S *pArgs)
{
HISI_INFO(MODULE_PRINT_CAM,"(in)");
enum v4l2_buf_type type;
INT32_T s32Ret, i;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
s32Ret = ioctl(pArgs->UsbCamFd, VIDIOC_STREAMOFF, &type);
if (s32Ret < 0)
{
printf("Unable to streamoff (%d).\n", errno);
return s32Ret;
}
for (i = 0; i < SAMPLE_USB_CAM_BUFFER_NUM; i++)
{
munmap(UsbCamBuff[i].pAddr, UsbCamBuff[i].length);
}
close(pArgs->UsbCamFd);
camera_detach_window(pArgs->hVi);
HISI_INFO(MODULE_PRINT_CAM,"(out)");
return HI_SUCCESS;
}
void *UsbCamRoutine(void* args)
{
HISI_INFO(MODULE_PRINT_CAM, "(in)");
//video抓取
HI_S32 buf_index = 0;
HI_S32 s32Ret;
HI_U32 totalFrame = 0;
HI_U32 releaseFrame =0 ;
struct v4l2_buffer buf;
HI_U32 j,fail_cnt =0;
HI_U32 tagFrame = 0,reopen_flag = 0;
HI_UNF_VI_BUF_S struViBuf;
USB_CAM_THREAD_ARG_S *pArgs = (USB_CAM_THREAD_ARG_S*)args;
HI_HANDLE hVi = pArgs->hVi;
while(g_whCAMVi)
{
if (HI_SUCCESS == UsbCamInit(pArgs))
{
break;
}
else
{
UsbCamDeinit(pArgs);
usleep(100000);
}
}
while(g_whCAMVi)
{
memset(&buf,0,sizeof(buf));
buf.type =V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory =V4L2_MEMORY_MMAP;
buf.index =buf_index ;
//读取缓存
s32Ret=ioctl(pArgs->UsbCamFd, VIDIOC_DQBUF, &buf);
if( s32Ret < 0 )
{
/*启用下边这段会导致视频采集在本地播放很卡*/
usleep(10*1000); //10*10000
fail_cnt++;
if(fail_cnt >= 300) //300
{
HISI_INFO(MODULE_PRINT_CAM, "ioctl failed over 300 times.");
UsbCamDeinit(pArgs);
UsbCamInit(pArgs);
tagFrame = totalFrame;
fail_cnt = 0;
// reopen_flag = 1;
}
}
else
{
totalFrame++;
fail_cnt = 0;
if (V4L2_PIX_FMT_YUYV == pArgs->u32USBCamFmt)
{
struViBuf.enPixelFormat = HI_UNF_FORMAT_YUV_PACKAGE_YUYV;
struViBuf.u32Stride[0] = SAMPLE_VI_USB_CAM_WIDTH * 2;
struViBuf.pVirAddr[0] = UsbCamBuff[buf.index].pAddr;
s32Ret = HI_UNF_VI_PutFrame(hVi, &struViBuf);
}
else
{
printf("fmt unknown\r\n");
}
buf_index = (buf_index +1) % SAMPLE_USB_CAM_BUFFER_NUM;
}
//Always try to get frame from vi
s32Ret = HI_UNF_VI_GetFrame(hVi, &struViBuf);
if(s32Ret == HI_SUCCESS)
{
if(!reopen_flag)
{
for(j = 0; j < SAMPLE_USB_CAM_BUFFER_NUM; j++)
{
if(struViBuf.pVirAddr[0] == UsbCamBuff[j].pAddr)
{
buf.index= j;
releaseFrame++;
//Reput buffer into queue
s32Ret=ioctl(pArgs->UsbCamFd, VIDIOC_QBUF, &buf);
if( s32Ret== -1)
{
printf("EnQ Cam buffer error:%d\n", s32Ret);
break;
}
}
}
}
else
{
releaseFrame++;
if(releaseFrame == tagFrame)
{
reopen_flag = 0;
tagFrame = 0;
}
}
}
}
// UsbCamDeinit(pArgs);
HISI_INFO(MODULE_PRINT_CAM,"(out)");
}
/*
UINT32_T phVi;//视频输入句柄
UINT32_T phVenc;//视频编码通道
*/
INT32_T VIVenc_Init(HI_UNF_VI_E enViPort, HI_UNF_VI_INPUT_MODE_E enViMode, UINT32_T *phVi, HI_UNF_VCODEC_TYPE_E enVencFmt, UINT32_T *phVenc)
{
HISI_INFO(MODULE_PRINT_CAM, "(in)");
INT32_T ret = HI_SUCCESS;
UINT32_T hVi;
UINT32_T hVenc;
HI_UNF_VI_ATTR_S stViAttr;
HI_UNF_VENC_CHN_ATTR_S stVeAttr;
HI_UNF_VENC_CHN_ATTR_S *pstVeAttr=&stVeAttr;
HIAPI_RUN_RETURN(HI_UNF_VI_Init());
HIAPI_RUN_RETURN(HI_UNF_VENC_Init());
HIAPI_RUN_RETURN(HI_UNF_VI_GetDefaultAttr(&stViAttr));
stViAttr.enViPort = enViPort;
stViAttr.enInputMode = enViMode;
if (HI_UNF_VI_MODE_USB_CAM == enViMode)
{
stViAttr.stInputRect.s32X = 0;
stViAttr.stInputRect.s32Y = 0;
stViAttr.stInputRect.s32Width = SAMPLE_VI_USB_CAM_WIDTH;
stViAttr.stInputRect.s32Height = SAMPLE_VI_USB_CAM_HEIGHT;
stViAttr.enStoreMethod = HI_UNF_VI_STORE_METHOD_PKYUV;
stViAttr.enStoreMode = HI_UNF_VI_STORE_FRAME;
stViAttr.enBufMgmtMode = HI_UNF_VI_BUF_MMAP;
stViAttr.u32YStride = SAMPLE_VI_USB_CAM_WIDTH * 2;
stViAttr.u32CStride = 0;
stViAttr.u32BufNum = 6;
}
else
{
HISI_INFO(MODULE_PRINT_CAM,"enViMode NOT support NOW..");
}
HIAPI_RUN(HI_UNF_VI_Create(&stViAttr, &(hVi)), ret);
if (ret != HI_SUCCESS)
{
HISI_INFO(MODULE_PRINT_CAM,"HI_UNF_VI_Create fail ,errno=0x%x",ret);
HI_UNF_VI_DeInit();
return ret;
}
HIAPI_RUN(HI_UNF_VENC_GetDefaultAttr(pstVeAttr), ret);
pstVeAttr->enVencType = enVencFmt;
pstVeAttr->u32Height = stViAttr.stInputRect.s32Height;
pstVeAttr->u32Width = stViAttr.stInputRect.s32Width;
pstVeAttr->bSlcSplitEn = HI_FALSE;
pstVeAttr->u32SplitSize = 1024;
pstVeAttr->u32Gop = 300;
pstVeAttr->u32Qlevel = 0;
pstVeAttr->u32InputFrmRate = 25;
pstVeAttr->u32TargetFrmRate = 24;
pstVeAttr->u32TargetBitRate =1768*1024;
if (HI_UNF_VI_MODE_USB_CAM == enViMode)
{
pstVeAttr->enYuvStoreType = HI_UNF_VENC_STORE_PACKAGE;
pstVeAttr->enYuvSampleType = HI_UNF_VENC_YUV_422;
pstVeAttr->u32InputFrmRate = 30;
pstVeAttr->u32TargetFrmRate = 30;
}
else
{
HISI_INFO(MODULE_PRINT_CAM,"enViMode NOT support NOW.");
}
pstVeAttr->bSendToNet = HI_FALSE;
HIAPI_RUN(HI_UNF_VENC_CreateChn(&hVenc, pstVeAttr), ret);
if (ret != HI_SUCCESS)
{
HISI_ERR(MODULE_PRINT_CAM, "HI_UNF_VENC_CreateChn fail!!!,errno=0x%x",ret);
HI_UNF_VENC_DeInit();
HI_UNF_VI_DeInit();
return ret;
}
HIAPI_RUN(HI_UNF_VENC_AttachInput(hVenc, hVi), ret);
if (ret != HI_SUCCESS)
{
HI_UNF_VENC_DestroyChn(hVenc);
HI_UNF_VENC_DeInit();
HI_UNF_VI_DeInit();
return ret;
}
HIAPI_RUN(HI_UNF_VENC_Start(hVenc), ret);
if (ret != HI_SUCCESS)
{
HI_UNF_VENC_DetachInput(hVenc, hVi);
HI_UNF_VENC_DestroyChn(hVenc);
HI_UNF_VENC_DeInit();
return ret;
}
*phVi = hVi;
*phVenc = hVenc;
g_stUSBCamArgs.hVi = hVi;
g_whCAMVi = HI_TRUE;
// pthread_create(&g_thCAMVi, HI_NULL, UsbCamRoute, (void*)(&g_stUSBCamArgs));
if(g_thCAMVi==0)
{
g_thCAMVi = ipanel_porting_task_create("ucam", UsbCamRoutine, (void*)(&g_stUSBCamArgs), 5, 0x2000);
if(g_thCAMVi==0) goto LAB_ERR;
}
else
{
goto LAB_ERR;
}
HISI_INFO(MODULE_PRINT_CAM, "(out)");
return ret;
LAB_ERR:
HI_ADP_VIVENC_DeInit(hVi, hVenc);
HISI_ERR(MODULE_PRINT_CAM, "(err)");
return -1;
}
INT32_T HI_ADP_VIVENC_DeInit(UINT32_T hVi, UINT32_T hVenc)
{
INT32_T ret = HI_SUCCESS;
HIAPI_RUN(HI_UNF_VENC_Stop(hVenc), ret);
HIAPI_RUN(HI_UNF_VENC_DetachInput(hVenc,hVi), ret);
HIAPI_RUN(HI_UNF_VENC_DestroyChn(hVenc), ret);
HIAPI_RUN(HI_UNF_VENC_DeInit(), ret);
if (g_thCAMVi)
{
g_whCAMVi = HI_FALSE;
ret = ipanel_porting_task_destroy(g_thCAMVi);
if(ret==0)
{
g_thCAMVi = 0;
}
}
HIAPI_RUN(HI_UNF_VI_Destroy(hVi), ret);
HIAPI_RUN(HI_UNF_VI_DeInit(), ret);
return ret;
}
HI_HANDLE camera_attach_window(HI_HANDLE vihandle)
{
INT32_T ret;
HI_HANDLE winhdl;
HI_UNF_WINDOW_ATTR_S win_attr;
HI_UNF_ENC_FMT_E enc_format = HI_UNF_ENC_FMT_720P_50;
HI_U32 width = 0, height = 0;
ret = HI_UNF_VO_GetWindowAttr(porting_display_get_video_window(), &win_attr);
if (HI_SUCCESS != ret)
{
HISI_ERR(MODULE_PRINT_CAM,"(err)HI_UNF_VO_GetWindowAttr error:0x%x", ret);
return -1;
}
win_attr.enVo = HI_UNF_VO_HD0;
win_attr.bVirtual = 0;
win_attr.enVideoFormat = HI_UNF_FORMAT_YUV_PACKAGE_YUYV;
win_attr.enAspectRatio = HI_UNF_ASPECT_RATIO_16TO9;
win_attr.enAspectCvrs = HI_UNF_ASPECT_CVRS_IGNORE;
win_attr.stInputRect.s32X = 0;
win_attr.stInputRect.s32Y = 0;
win_attr.stInputRect.s32Width = 1280;
win_attr.stInputRect.s32Height = 720;
win_attr.stOutputRect.s32X = win_attr.stOutputRect.s32X+win_attr.stOutputRect.s32Width*3/4;
win_attr.stOutputRect.s32Y = win_attr.stOutputRect.s32Y+win_attr.stOutputRect.s32Height*3/4;
win_attr.stOutputRect.s32Width = win_attr.stOutputRect.s32Width/4;
win_attr.stOutputRect.s32Height = win_attr.stOutputRect.s32Height/4;
ret = HI_UNF_VO_CreateWindow(&win_attr, &winhdl);
if(ret != IPANEL_OK)
{
HISI_ERR(MODULE_PRINT_CAM,"(err)creat VOIP1 window fail!!!,errno=0x%x",ret);
return IPANEL_ERR;
}
ret = HI_UNF_VO_SetWindowZorder(winhdl, HI_LAYER_ZORDER_MOVETOP);
ret = HI_UNF_VO_AttachWindow(winhdl, vihandle);
if(ret != IPANEL_OK)
{
HISI_ERR(MODULE_PRINT_CAM,"(err)HI_UNF_VO_SetWindowZorder fail!!!,errno=0x%x",ret);
return IPANEL_ERR;
}
ret = HI_UNF_VO_SetWindowEnable(winhdl, HI_TRUE);
if(ret != IPANEL_OK)
{
HISI_ERR(MODULE_PRINT_CAM,"(err)HI_UNF_VO_SetWindowZorder fail!!!,errno=0x%x",ret);
return IPANEL_ERR;
}
g_Winhdl = winhdl;
return winhdl;
}
void camera_detach_window(HI_HANDLE vihandle)
{
HI_UNF_VO_SetWindowEnable(g_Winhdl, HI_FALSE);
HI_UNF_VO_DetachWindow(g_Winhdl, vihandle);
HI_UNF_VO_DestroyWindow(g_Winhdl);
g_Winhdl = 0;
}
int porting_camera_set_location( HI_UNF_WINDOW_ATTR_S *win_attr)
{
if(g_Winhdl==0)
{
return 0;
}
int ret;
HI_UNF_WINDOW_ATTR_S attr;
ret = HI_UNF_VO_GetWindowAttr(g_Winhdl, &attr);
if (HI_SUCCESS != ret)
{
HISI_ERR(MODULE_PRINT_CAM,"(err)HI_UNF_VO_GetWindowAttr error:0x%x", ret);
goto LAB_ERR;
}
attr.stOutputRect.s32X = win_attr->stOutputRect.s32X+win_attr->stOutputRect.s32Width*3/4;
attr.stOutputRect.s32Y = win_attr->stOutputRect.s32Y+win_attr->stOutputRect.s32Height*3/4;
attr.stOutputRect.s32Width = win_attr->stOutputRect.s32Width/4;
attr.stOutputRect.s32Height = win_attr->stOutputRect.s32Height/4;
ret = HI_UNF_VO_SetWindowAttr(g_Winhdl, &attr);
if (HI_SUCCESS != ret)
{
HISI_ERR(MODULE_PRINT_CAM,"(err)HI_UNF_VO_SetWindowAttr error:0x%x", ret);
goto LAB_ERR;
}
return IPANEL_OK;
LAB_ERR:
return IPANEL_ERR;
}
void porting_camera_set_location_by_rect(void *arg)
{
IPANEL_RECT *rect;
HI_UNF_WINDOW_ATTR_S attr;
int ret;
rect=(IPANEL_RECT *)arg;
if(g_Winhdl==0&&rect!=NULL)
{
return ;
}
ret = HI_UNF_VO_GetWindowAttr(g_Winhdl, &attr);
if (HI_SUCCESS != ret)
{
HISI_ERR(PORT_MODULE_CAM,"(err)HI_UNF_VO_GetWindowAttr error:0x%x", ret);
return;
}
attr.stOutputRect.s32X = rect->x;
attr.stOutputRect.s32Y = rect->y;
attr.stOutputRect.s32Width = rect->w;
attr.stOutputRect.s32Height = rect->h;
ret = HI_UNF_VO_SetWindowAttr(g_Winhdl, &attr);
if (HI_SUCCESS != ret)
{
HISI_ERR(PORT_MODULE_CAM,"(err)HI_UNF_VO_SetWindowAttr error:0x%x", ret);
return;
}
return;
}