V4L2摄像头取数据程序

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;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值