[Title] Set to minimum FPS on non-VT env. & minimal access to host webcam on stream...
authorjinhyung.jo <jinhyung.jo@samsung.com>
Mon, 3 Sep 2012 15:49:39 +0000 (00:49 +0900)
committerjinhyung.jo <jinhyung.jo@samsung.com>
Mon, 3 Sep 2012 15:49:39 +0000 (00:49 +0900)
[Type] Bugfix
[Module] Emulator / Camera
[Priority] Major
[CQ#]
[Redmine#]
[Problem]
[Cause]
[Solution]
[TestCase]

tizen/src/hw/maru_camera_linux_pci.c

index 703401060487b08ac8ebec3f83a284d3d854044e..3646f66cdcac536213c9d2f1a1c188419018218c 100644 (file)
@@ -69,6 +69,29 @@ static int xioctl(int fd, int req, void *arg)
     return r;\r
 }\r
 \r
+typedef struct tagMaruCamConvertPixfmt {\r
+    uint32_t fmt;   /* fourcc */\r
+} MaruCamConvertPixfmt;\r
+\r
+static MaruCamConvertPixfmt supported_dst_pixfmts[] = {\r
+        { V4L2_PIX_FMT_YUYV },\r
+        { V4L2_PIX_FMT_YUV420 },\r
+        { V4L2_PIX_FMT_YVU420 },\r
+};\r
+\r
+typedef struct tagMaruCamConvertFrameInfo {\r
+    uint32_t width;\r
+    uint32_t height;\r
+} MaruCamConvertFrameInfo;\r
+\r
+static MaruCamConvertFrameInfo supported_dst_frames[] = {\r
+        { 640, 480 },\r
+        { 352, 288 },\r
+        { 320, 240 },\r
+        { 176, 144 },\r
+        { 160, 120 },\r
+};\r
+\r
 #define MARUCAM_CTRL_VALUE_MAX      20\r
 #define MARUCAM_CTRL_VALUE_MIN      1\r
 #define MARUCAM_CTRL_VALUE_MID      10\r
@@ -140,6 +163,69 @@ static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value)
     return ret;\r
 }\r
 \r
+static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,\r
+                        uint32_t width, uint32_t height)\r
+{\r
+    struct v4l2_frmivalenum fival;\r
+    struct v4l2_streamparm sp;\r
+    uint32_t min_num = 0, min_denom = 0;\r
+\r
+    CLEAR(fival);\r
+    fival.pixel_format = pixel_format;\r
+    fival.width = width;\r
+    fival.height = height;\r
+\r
+    if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) {\r
+        ERR("Unable to enumerate intervals for pixelformat(0x%x), (%d:%d)\n",\r
+            pixel_format, width, height);\r
+        return;\r
+    }\r
+\r
+    if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {\r
+        float max_ival = -1.0;\r
+        do {\r
+            float cur_ival = (float)fival.discrete.numerator\r
+                        / (float)fival.discrete.denominator;\r
+            if (cur_ival > max_ival) {\r
+                max_ival = cur_ival;\r
+                min_num = fival.discrete.numerator;\r
+                min_denom = fival.discrete.denominator;\r
+            }\r
+            TRACE("Discrete frame interval %u/%u supported\n",\r
+                 fival.discrete.numerator, fival.discrete.denominator);\r
+            fival.index++;\r
+        } while (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) >= 0);\r
+    } else if ((fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) ||\r
+                (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) {\r
+        TRACE("Frame intervals from %u/%u to %u/%u supported",\r
+            fival.stepwise.min.numerator, fival.stepwise.min.denominator,\r
+            fival.stepwise.max.numerator, fival.stepwise.max.denominator);\r
+        if(fival.type == V4L2_FRMIVAL_TYPE_STEPWISE)\r
+            TRACE("with %u/%u step",\r
+                 fival.stepwise.step.numerator, fival.stepwise.step.denominator);\r
+        if (((float)fival.stepwise.max.denominator /\r
+             (float)fival.stepwise.max.numerator) >\r
+            ((float)fival.stepwise.min.denominator /\r
+             (float)fival.stepwise.min.numerator)) {\r
+            min_num = fival.stepwise.max.numerator;\r
+            min_denom = fival.stepwise.max.denominator;\r
+        } else {\r
+            min_num = fival.stepwise.min.numerator;\r
+            min_denom = fival.stepwise.min.denominator;\r
+        }\r
+    }\r
+    TRACE("actual min values : %u/%u\n", min_num, min_denom);\r
+\r
+    CLEAR(sp);\r
+    sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
+    sp.parm.capture.timeperframe.numerator = min_num;\r
+    sp.parm.capture.timeperframe.denominator = min_denom;\r
+\r
+    if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) {\r
+        ERR("Failed to set to minimum FPS(%u/%u)\n", min_num, min_denom);\r
+    }\r
+}\r
+\r
 static int is_streamon(MaruCamState *state)\r
 {\r
     int st;\r
@@ -330,10 +416,18 @@ void marucam_device_open(MaruCamState* state)
 \r
 void marucam_device_start_preview(MaruCamState* state)\r
 {\r
+    struct timespec req;\r
+    req.tv_sec = 0;\r
+    req.tv_nsec = 10000000;\r
+\r
+    INFO("Starting preview!\n");\r
     qemu_mutex_lock(&state->thread_mutex);\r
     qemu_cond_signal(&state->thread_cond);\r
     qemu_mutex_unlock(&state->thread_mutex);\r
-    INFO("Starting preview!\n");\r
+\r
+    /* nanosleep until thread is streamon  */\r
+    while (!is_stream_on(state))\r
+        nanosleep(&req, NULL);\r
 }\r
 \r
 void marucam_device_stop_preview(MaruCamState* state)\r
@@ -358,8 +452,15 @@ void marucam_device_s_param(MaruCamState* state)
 {\r
     MaruCamParam *param = state->param;\r
 \r
-    /* We use default FPS of the webcam */\r
     param->top = 0;\r
+\r
+    /* If KVM enabled, We use default FPS of the webcam.\r
+     * If KVM disabled, we use mininum FPS of the webcam */\r
+    if (!kvm_enabled()) {\r
+        set_maxframeinterval(state, dst_fmt.fmt.pix.pixelformat,\r
+                     dst_fmt.fmt.pix.width,\r
+                     dst_fmt.fmt.pix.height);\r
+    }\r
 }\r
 \r
 void marucam_device_g_param(MaruCamState* state)\r
@@ -458,25 +559,30 @@ void marucam_device_try_fmt(MaruCamState* state)
 \r
 void marucam_device_enum_fmt(MaruCamState* state)\r
 {\r
-    struct v4l2_fmtdesc format;\r
+    uint32_t index;\r
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    CLEAR(format);\r
-    format.index = param->stack[0];\r
-    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
+    index = param->stack[0];\r
 \r
-    if (xioctl(v4l2_fd, VIDIOC_ENUM_FMT, &format) < 0) {\r
-        if (errno != EINVAL)\r
-            ERR("failed to enumerate video formats: %s\n", strerror(errno));\r
-        param->errCode = errno;\r
+    if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {\r
+        param->errCode = EINVAL;\r
         return;\r
     }\r
-    param->stack[0] = format.index;\r
-    param->stack[1] = format.flags;\r
-    param->stack[2] = format.pixelformat;\r
+    param->stack[1] = 0; /* flags = NONE */\r
+    param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */\r
     /* set description */\r
-    memcpy(&param->stack[3], format.description, sizeof(format.description));\r
+    switch (supported_dst_pixfmts[index].fmt) {\r
+    case V4L2_PIX_FMT_YUYV:\r
+        memcpy(&param->stack[3], "YUYV", 32);\r
+        break;\r
+    case V4L2_PIX_FMT_YUV420:\r
+        memcpy(&param->stack[3], "YU12", 32);\r
+        break;\r
+    case V4L2_PIX_FMT_YVU420:\r
+        memcpy(&param->stack[3], "YV12", 32);\r
+        break;\r
+    }\r
 }\r
 \r
 void marucam_device_qctrl(MaruCamState* state)\r
@@ -640,56 +746,48 @@ void marucam_device_g_ctrl(MaruCamState* state)
 \r
 void marucam_device_enum_fsizes(MaruCamState* state)\r
 {\r
-    struct v4l2_frmsizeenum fsize;\r
+    uint32_t index, pixfmt, i;\r
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    CLEAR(fsize);\r
-    fsize.index = param->stack[0];\r
-    fsize.pixel_format = param->stack[1];\r
+    index = param->stack[0];\r
+    pixfmt = param->stack[1];\r
 \r
-    if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMESIZES, &fsize) < 0) {\r
-        if (errno != EINVAL)\r
-            ERR("failed to get frame sizes : %s\n", strerror(errno));\r
-        param->errCode = errno;\r
+    if (index >= ARRAY_SIZE(supported_dst_frames)) {\r
+        param->errCode = EINVAL;\r
         return;\r
     }\r
+    for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {\r
+        if (supported_dst_pixfmts[i].fmt == pixfmt)\r
+            break;\r
+    }\r
 \r
-    if (fsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {\r
-        param->stack[0] = fsize.discrete.width;\r
-        param->stack[1] = fsize.discrete.height;\r
-    } else {\r
+    if (i == ARRAY_SIZE(supported_dst_pixfmts)) {\r
         param->errCode = EINVAL;\r
-        ERR("Not Supported mode, we only support DISCRETE\n");\r
+        return;\r
     }\r
+\r
+    param->stack[0] = supported_dst_frames[index].width;\r
+    param->stack[1] = supported_dst_frames[index].height;\r
 }\r
 \r
 void marucam_device_enum_fintv(MaruCamState* state)\r
 {\r
-    struct v4l2_frmivalenum ival;\r
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    CLEAR(ival);\r
-    ival.index = param->stack[0];\r
-    ival.pixel_format = param->stack[1];\r
-    ival.width = param->stack[2];\r
-    ival.height = param->stack[3];\r
-\r
-    if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0) {\r
-        if (errno != EINVAL)\r
-            ERR("failed to get frame intervals : %s\n", strerror(errno));\r
-        param->errCode = errno;\r
-        return;\r
-    }\r
 \r
-    if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {\r
-        param->stack[0] = ival.discrete.numerator;\r
-        param->stack[1] = ival.discrete.denominator;\r
-    } else {\r
+    /* switch by index(param->stack[0]) */\r
+    switch (param->stack[0]) {\r
+    case 0:\r
+        /* we only use 1/30 frame interval */\r
+        param->stack[1] = 30;   /* denominator */\r
+        break;\r
+    default:\r
         param->errCode = EINVAL;\r
-        ERR("Not Supported mode, we only support DISCRETE\n");\r
+        return;\r
     }\r
+    param->stack[0] = 1;    /* numerator */\r
 }\r
 \r
 void marucam_device_close(MaruCamState* state)\r