[Title] improved camera performance & add win32 dll source
[sdk/emulator/qemu.git] / tizen / src / hw / svcamera_win32.c
1 /*
2  * Samsung Virtual Camera device(PCI) for Windows host.
3  *
4  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact:
7  * JinHyung Jo <jinhyung.jo@samsung.com>
8  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
9  * DongKyun Yun <dk77.yun@samsung.com>
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  *
25  * Contributors:
26  * - S-Core Co., Ltd
27  *
28  */
29
30
31 #include "qemu-common.h"
32 #include "svcamera.h"
33 #include "pci.h"
34 #include "kvm.h"
35 #include "tizen/src/debug_ch.h"
36
37 #include "windows.h"
38 #include "basetyps.h"
39 #include "mmsystem.h"
40
41 MULTI_DEBUG_CHANNEL(tizen, camera_win32);
42
43 // V4L2 defines copy from videodev2.h
44 #define V4L2_CTRL_FLAG_SLIDER           0x0020
45
46 #define V4L2_CTRL_CLASS_USER            0x00980000
47 #define V4L2_CID_BASE                           (V4L2_CTRL_CLASS_USER | 0x900)
48 #define V4L2_CID_BRIGHTNESS                     (V4L2_CID_BASE+0)
49 #define V4L2_CID_CONTRAST                       (V4L2_CID_BASE+1)
50 #define V4L2_CID_SATURATION                     (V4L2_CID_BASE+2)
51 #define V4L2_CID_SHARPNESS                      (V4L2_CID_BASE+27)
52
53 #define V4L2_PIX_FMT_YUYV    MAKEFOURCC('Y', 'U', 'Y', 'V') /* 16  YUV 4:2:2     */
54 #define V4L2_PIX_FMT_YUV420  MAKEFOURCC('Y', 'U', '1', '2') /* 12  YUV 4:2:0     */
55 #define V4L2_PIX_FMT_YVU420  MAKEFOURCC('Y', 'V', '1', '2') /* 12  YVU 4:2:0     */
56
57 enum {
58         HWC_OPEN,
59         HWC_CLOSE,
60         HWC_START,
61         HWC_STOP,
62         HWC_S_FPS,
63         HWC_G_FPS,
64         HWC_S_FMT,
65         HWC_G_FMT,
66         HWC_TRY_FMT,
67         HWC_ENUM_FMT,
68         HWC_QCTRL,
69         HWC_S_CTRL,
70         HWC_G_CTRL,
71         HWC_ENUM_FSIZES,
72         HWC_ENUM_INTERVALS
73 };
74
75 typedef enum tagVideoProcAmpProperty {
76   VideoProcAmp_Brightness,
77   VideoProcAmp_Contrast,
78   VideoProcAmp_Hue,
79   VideoProcAmp_Saturation,
80   VideoProcAmp_Sharpness,
81   VideoProcAmp_Gamma,
82   VideoProcAmp_ColorEnable,
83   VideoProcAmp_WhiteBalance,
84   VideoProcAmp_BacklightCompensation,
85   VideoProcAmp_Gain
86 } VideoProcAmpProperty;
87
88 typedef struct tagHWCParam {
89         long val1;
90         long val2;
91         long val3;
92         long val4;
93         long val5;
94 } HWCParam;
95
96 typedef struct tagSVCamConvertPixfmt {
97         uint32_t fmt;   /* fourcc */
98         uint32_t bpp;   /* bits per pixel, 0 for compressed formats */
99         uint32_t needs_conversion;
100 } SVCamConvertPixfmt;
101
102 static SVCamConvertPixfmt supported_dst_pixfmts[] = {
103                 { V4L2_PIX_FMT_YUYV, 16, 0 },
104                 { V4L2_PIX_FMT_YUV420, 12, 0 },
105                 { V4L2_PIX_FMT_YVU420, 12, 0 },
106 };
107
108 typedef struct tagSVCamConvertFrameInfo {
109         uint32_t width;
110         uint32_t height;
111 } SVCamConvertFrameInfo;
112
113 static SVCamConvertFrameInfo supported_dst_frames[] = {
114                 { 640, 480 },
115                 { 352, 288 },
116                 { 320, 240 },
117                 { 176, 144 },
118                 { 160, 120 },
119 };
120
121 #define SVCAM_CTRL_VALUE_MAX            20
122 #define SVCAM_CTRL_VALUE_MIN            1
123 #define SVCAM_CTRL_VALUE_MID            10
124 #define SVCAM_CTRL_VALUE_STEP           1
125
126 struct svcam_qctrl {
127         uint32_t id;
128         uint32_t hit;
129         long min;
130         long max;
131         long step;
132         long init_val;
133 };
134
135 static struct svcam_qctrl qctrl_tbl[] = {
136         { V4L2_CID_BRIGHTNESS, 0, },
137         { V4L2_CID_CONTRAST, 0, },
138         { V4L2_CID_SATURATION,0, },
139         { V4L2_CID_SHARPNESS, 0, },
140 };
141
142 typedef int (STDAPICALLTYPE *CallbackFn)(ULONG dwSize, BYTE *pBuffer);
143 typedef HRESULT (STDAPICALLTYPE *CTRLFN)(UINT, UINT, LPVOID);
144 typedef HRESULT (STDAPICALLTYPE *SETCALLBACKFN)(CallbackFn);
145
146
147 static HINSTANCE g_hInst = NULL;
148 static SVCamState *g_state = NULL;
149
150 static CTRLFN SVCamCtrl;
151 static SETCALLBACKFN SVCamSetCallbackFn;
152
153 static uint32_t cur_fmt_idx = 0;
154 static uint32_t cur_frame_idx = 0;
155
156 void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,
157                 uint32_t width, uint32_t height, uint32_t yvu);
158
159
160 static long value_convert_from_guest(long min, long max, long value)
161 {
162         double rate = 0.0;
163         long dist = 0, ret = 0;
164
165         dist = max - min;
166
167         if (dist < SVCAM_CTRL_VALUE_MAX) {
168                 rate = (double)SVCAM_CTRL_VALUE_MAX / (double)dist;
169                 ret = min + (int32_t)(value / rate);
170         } else {
171                 rate = (double)dist / (double)SVCAM_CTRL_VALUE_MAX;
172                 ret = min + (int32_t)(rate * value);
173         }
174         return ret;
175 }
176
177 static long value_convert_to_guest(long min, long max, long value)
178 {
179         double rate  = 0.0;
180         long dist = 0, ret = 0;
181
182         dist = max - min;
183
184         if (dist < SVCAM_CTRL_VALUE_MAX) {
185                 rate = (double)SVCAM_CTRL_VALUE_MAX / (double)dist;
186                 ret = (int32_t)((double)(value - min) * rate);
187         } else {
188                 rate = (double)dist / (double)SVCAM_CTRL_VALUE_MAX;
189                 ret = (int32_t)((double)(value - min) / rate);
190         }
191
192         return ret;
193 }
194
195 static int STDAPICALLTYPE svcam_device_callbackfn(ULONG dwSize, BYTE *pBuffer)
196 {
197         static uint32_t index = 0;
198         uint32_t width, height;
199         width = supported_dst_frames[cur_frame_idx].width;
200         height = supported_dst_frames[cur_frame_idx].height;
201         void *buf = g_state->vaddr + (g_state->buf_size * index);
202
203         switch (supported_dst_pixfmts[cur_fmt_idx].fmt) {
204         case V4L2_PIX_FMT_YUV420:
205                 v4lconvert_yuyv_to_yuv420(pBuffer, buf, width, height, 0);
206                 break;
207         case V4L2_PIX_FMT_YVU420:
208                 v4lconvert_yuyv_to_yuv420(pBuffer, buf, width, height, 1);
209                 break;
210         case V4L2_PIX_FMT_YUYV:
211                 memcpy(buf, (void*)pBuffer, dwSize);
212                 break;
213         }
214         index = !index;
215
216         if (g_state->req_frame) {
217                 qemu_irq_raise(g_state->dev.irq[2]);
218                 g_state->req_frame = 0;
219         }
220         return 1;
221 }
222
223 // SVCAM_CMD_INIT
224 void svcam_device_init(SVCamState* state)
225 {
226         SVCamThreadInfo *thread = state->thread;
227
228         pthread_cond_init(&thread->thread_cond, NULL);
229         pthread_mutex_init(&thread->mutex_lock, NULL);
230
231         g_state = state;
232 }
233
234 // SVCAM_CMD_OPEN
235 void svcam_device_open(SVCamState* state)
236 {
237         HRESULT hr;
238         SVCamParam *param = state->thread->param;
239         param->top = 0;
240
241         g_hInst = LoadLibrary("hwcfilter.dll");
242
243         if (!g_hInst) {
244                 g_hInst = LoadLibrary("bin\\hwcfilter.dll");
245                 if (!g_hInst) {
246                         ERR("load library failed!!!!\n");
247                         param->errCode = EINVAL;
248                         return;
249                 }
250         }
251
252         SVCamCtrl = (CTRLFN)GetProcAddress(g_hInst, "HWCCtrl");
253         if (!SVCamCtrl) {
254                 ERR("HWCCtrl get failed!!!\n");
255                 FreeLibrary(g_hInst);
256                 param->errCode = EINVAL;
257                 return;
258         }
259
260         SVCamSetCallbackFn = (SETCALLBACKFN)GetProcAddress(g_hInst, "HWCSetCallback");
261         if (!SVCamSetCallbackFn) {
262                 ERR("HWCSetCallback get failed!!!\n");
263                 FreeLibrary(g_hInst);
264                 param->errCode = EINVAL;
265                 return;
266         }
267
268         hr = SVCamCtrl(HWC_OPEN, 0, NULL);
269         if (FAILED(hr)) {
270                 param->errCode = EINVAL;
271                 FreeLibrary(g_hInst);
272                 ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
273                 return;
274         }
275         hr = SVCamSetCallbackFn((CallbackFn)svcam_device_callbackfn);
276         if (FAILED(hr)) {
277                 param->errCode = EINVAL;
278                 SVCamCtrl(HWC_CLOSE, 0, NULL);
279                 FreeLibrary(g_hInst);
280                 ERR("call back function set failed!!!, [HRESULT : 0x%x]\n", hr);
281         }
282
283         TRACE("camera device open success!!!, [HRESULT : 0x%x]\n", hr);
284 }
285
286 // SVCAM_CMD_CLOSE
287 void svcam_device_close(SVCamState* state)
288 {
289         HRESULT hr;
290         SVCamParam *param = state->thread->param;
291         param->top = 0;
292         hr = SVCamCtrl(HWC_CLOSE, 0, NULL);
293         if (FAILED(hr)) {
294                 param->errCode = EINVAL;
295                 ERR("camera device close failed!!!, [HRESULT : 0x%x]\n", hr);
296         }
297         FreeLibrary(g_hInst);
298         TRACE("camera device close success!!!, [HRESULT : 0x%x]\n", hr);
299 }
300
301 // SVCAM_CMD_START_PREVIEW
302 void svcam_device_start_preview(SVCamState* state)
303 {
304         HRESULT hr;
305         uint32_t width, height;
306         SVCamParam *param = state->thread->param;
307         TRACE("svcam_device_start_preview\n");
308         param->top = 0;
309         hr = SVCamCtrl(HWC_START, 0, NULL);
310         if (FAILED(hr)) {
311                 param->errCode = EINVAL;
312                 ERR("start preview failed!!!, [HRESULT : 0x%x]\n", hr);
313                 return;
314         }
315         pthread_mutex_lock(&state->thread->mutex_lock);
316         state->streamon = 1;
317         pthread_mutex_unlock(&state->thread->mutex_lock);
318
319         width = supported_dst_frames[cur_frame_idx].width;
320         height = supported_dst_frames[cur_frame_idx].height;
321         state->buf_size = height * ((width * supported_dst_pixfmts[cur_fmt_idx].bpp) >> 3);
322 }
323
324 // SVCAM_CMD_STOP_PREVIEW
325 void svcam_device_stop_preview(SVCamState* state)
326 {
327         HRESULT hr;
328         SVCamParam *param = state->thread->param;
329         TRACE("svcam_device_stop_preview\n");
330         param->top = 0;
331         hr = SVCamCtrl(HWC_STOP, 0, NULL);
332         if (FAILED(hr)) {
333                 param->errCode = EINVAL;
334                 ERR("stop preview failed!!!, [HRESULT : 0x%x]\n", hr);
335         }
336         pthread_mutex_lock(&state->thread->mutex_lock);
337         state->streamon = 0;
338         pthread_mutex_unlock(&state->thread->mutex_lock);
339         state->buf_size = 0;
340 }
341
342 // SVCAM_CMD_S_PARAM
343 void svcam_device_s_param(SVCamState* state)
344 {
345         SVCamParam *param = state->thread->param;
346
347         param->top = 0;
348         TRACE("setting fps : %d/%d\n", param->stack[0], param->stack[1]);
349 }
350
351 // SVCAM_CMD_G_PARAM
352 void svcam_device_g_param(SVCamState* state)
353 {
354         SVCamParam *param = state->thread->param;
355
356         param->top = 0;
357         TRACE("getting fps : 30/1\n");
358
359         param->stack[0] = 0x1000; // V4L2_CAP_TIMEPERFRAME
360         param->stack[1] = 1; // numerator;
361         param->stack[2] = 30; // denominator;
362 }
363
364 // SVCAM_CMD_S_FMT
365 void svcam_device_s_fmt(SVCamState* state)
366 {
367         uint32_t width, height, pixfmt, pidx, fidx;
368         SVCamParam *param = state->thread->param;
369
370         param->top = 0;
371         width = param->stack[0];                // width
372         height = param->stack[1];               // height
373         pixfmt = param->stack[2];               // pixelformat
374
375         for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) {
376                 if ((supported_dst_frames[fidx].width == width) &&
377                                 (supported_dst_frames[fidx].height == height)) {
378                         break;
379                 }
380         }
381         if (fidx == ARRAY_SIZE(supported_dst_frames)) {
382                 param->errCode = EINVAL;
383                 return;
384         }
385         for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) {
386                 if (supported_dst_pixfmts[pidx].fmt == pixfmt) {
387                         break;
388                 }
389         }
390         if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) {
391                 param->errCode = EINVAL;
392                 return;
393         }
394
395         if ((supported_dst_frames[cur_frame_idx].width != width) &&
396                         (supported_dst_frames[cur_frame_idx].height != height)) {
397                 HWCParam inParam = {0,};
398                 inParam.val1 = width;
399                 inParam.val2 = height;
400                 HRESULT hr = SVCamCtrl(HWC_S_FMT, sizeof(HWCParam), &inParam);
401                 if (FAILED(hr)) {
402                         param->errCode = EINVAL;
403                         return;
404                 }
405         }
406
407         param->stack[0] = width;
408         param->stack[1] = height;
409         param->stack[2] = 1; // V4L2_FIELD_NONE
410         param->stack[3] = pixfmt;
411         // bytes per line = (width * bpp) / 8
412         param->stack[4] = (width * supported_dst_pixfmts[pidx].bpp) >> 3;
413         param->stack[5] = param->stack[4] * height;     // height * bytesperline
414         param->stack[6] = 0;
415         param->stack[7] = 0;
416
417         cur_frame_idx = fidx;
418         cur_fmt_idx = pidx;
419 }
420
421 // SVCAM_CMD_G_FMT
422 void svcam_device_g_fmt(SVCamState* state)
423 {
424         SVCamParam *param = state->thread->param;
425
426         param->top = 0;
427
428         param->stack[0] = supported_dst_frames[cur_frame_idx].width;    // width
429         param->stack[1] = supported_dst_frames[cur_frame_idx].height;   // height
430         param->stack[2] = 1; // V4L2_FIELD_NONE
431         param->stack[3] = supported_dst_pixfmts[cur_fmt_idx].fmt;       // pixelformat
432         // bytes per line = (width * bpp) / 8
433         param->stack[4] = (param->stack[0] * supported_dst_pixfmts[cur_fmt_idx].bpp) >> 3;
434         param->stack[5] = param->stack[1] * param->stack[4];    // height * bytesperline
435         param->stack[6] = 0;
436         param->stack[7] = 0;
437 }
438
439 void svcam_device_try_fmt(SVCamState* state)
440 {
441         uint32_t width, height, pixfmt, i;
442         SVCamParam *param = state->thread->param;
443
444         param->top = 0;
445         width = param->stack[0];                // width
446         height = param->stack[1];               // height
447         pixfmt = param->stack[2];               // pixelformat
448
449         for (i = 0; i < ARRAY_SIZE(supported_dst_frames); i++) {
450                 if ((supported_dst_frames[i].width == width) &&
451                                 (supported_dst_frames[i].height == height)) {
452                         break;
453                 }
454         }
455         if (i == ARRAY_SIZE(supported_dst_frames)) {
456                 param->errCode = EINVAL;
457                 return;
458         }
459         for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
460                 if (supported_dst_pixfmts[i].fmt == pixfmt) {
461                         break;
462                 }
463         }
464         if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
465                 param->errCode = EINVAL;
466                 return;
467         }
468
469         param->stack[0] = width;
470         param->stack[1] = height;
471         param->stack[2] = 1; // V4L2_FIELD_NONE
472         param->stack[3] = pixfmt;
473         // bytes per line = (width * bpp) / 8
474         param->stack[4] = (width * supported_dst_pixfmts[i].bpp) >> 3;
475         param->stack[5] = param->stack[4] * height;     // height * bytesperline
476         param->stack[6] = 0;
477         param->stack[7] = 0;
478 }
479
480 void svcam_device_enum_fmt(SVCamState* state)
481 {
482         uint32_t index;
483         SVCamParam *param = state->thread->param;
484
485         param->top = 0;
486         index = param->stack[0];
487
488         if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {
489                 param->errCode = EINVAL;
490                 return;
491         }
492         param->stack[1] = 0;                                                    // flags = NONE;
493         param->stack[2] = supported_dst_pixfmts[index].fmt;     // pixelformat;
494         /* set description */
495         switch (supported_dst_pixfmts[index].fmt) {
496         case V4L2_PIX_FMT_YUYV:
497                 memcpy(&param->stack[3], "YUY2", 32);
498                 break;
499         case V4L2_PIX_FMT_YUV420:
500                 memcpy(&param->stack[3], "YU12", 32);
501                 break;
502         case V4L2_PIX_FMT_YVU420:
503                 memcpy(&param->stack[3], "YV12", 32);
504                 break;
505         }
506 }
507
508 void svcam_device_qctrl(SVCamState* state)
509 {
510         HRESULT hr;
511         uint32_t id, i;
512         HWCParam inParam = {0,};
513         char name[32] = {0,};
514         SVCamParam *param = state->thread->param;
515
516         param->top = 0;
517         id = param->stack[0];
518
519         switch (id) {
520         case V4L2_CID_BRIGHTNESS:
521                 TRACE("V4L2_CID_BRIGHTNESS\n");
522                 inParam.val1 = VideoProcAmp_Brightness;
523                 memcpy((void*)name, (void*)"brightness", 32);
524                 i = 0;
525                 break;
526         case V4L2_CID_CONTRAST:
527                 TRACE("V4L2_CID_CONTRAST\n");
528                 inParam.val1 = VideoProcAmp_Contrast;
529                 memcpy((void*)name, (void*)"contrast", 32);
530                 i = 1;
531                 break;
532         case V4L2_CID_SATURATION:
533                 TRACE("V4L2_CID_SATURATION\n");
534                 inParam.val1 = VideoProcAmp_Saturation;
535                 memcpy((void*)name, (void*)"saturation", 32);
536                 i = 2;
537                 break;
538         case V4L2_CID_SHARPNESS:
539                 TRACE("V4L2_CID_SHARPNESS\n");
540                 inParam.val1 = VideoProcAmp_Sharpness;
541                 memcpy((void*)name, (void*)"sharpness", 32);
542                 i = 3;
543                 break;
544         default:
545                 param->errCode = EINVAL;
546                 return;
547         }
548         hr = SVCamCtrl(HWC_QCTRL, sizeof(inParam), &inParam);
549         if (FAILED(hr)) {
550                 param->errCode = EINVAL;
551                 ERR("failed to query video controls [HRESULT : 0x%x]\n", hr);
552                 return;
553         } else {
554                 qctrl_tbl[i].hit = 1;
555                 qctrl_tbl[i].min = inParam.val2;
556                 qctrl_tbl[i].max = inParam.val3;
557                 qctrl_tbl[i].step = inParam.val4;
558                 qctrl_tbl[i].init_val = inParam.val5;
559
560                 if ((qctrl_tbl[i].min + qctrl_tbl[i].max) == 0) {
561                         inParam.val2 = 0;
562                 } else {
563                         inParam.val2 = (qctrl_tbl[i].min + qctrl_tbl[i].max) / 2;
564                 }
565                 hr = SVCamCtrl(HWC_S_CTRL, sizeof(inParam), &inParam);
566                 if (FAILED(hr)) {
567                         param->errCode = EINVAL;
568                         ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr);
569                         return;
570                 }
571         }
572
573         param->stack[0] = id;
574         param->stack[1] = SVCAM_CTRL_VALUE_MIN; // minimum
575         param->stack[2] = SVCAM_CTRL_VALUE_MAX; // maximum
576         param->stack[3] = SVCAM_CTRL_VALUE_STEP;// step
577         param->stack[4] = SVCAM_CTRL_VALUE_MID; // default_value
578         param->stack[5] = V4L2_CTRL_FLAG_SLIDER;
579         /* name field setting */
580         memcpy(&param->stack[6], (void*)name, sizeof(name)/sizeof(name[0]));
581 }
582
583 void svcam_device_s_ctrl(SVCamState* state)
584 {
585         HRESULT hr;
586         uint32_t i;
587         HWCParam inParam = {0,};
588         SVCamParam *param = state->thread->param;
589
590         param->top = 0;
591
592         switch (param->stack[0]) {
593         case V4L2_CID_BRIGHTNESS:
594                 i = 0;
595                 inParam.val1 = VideoProcAmp_Brightness;
596                 break;
597         case V4L2_CID_CONTRAST:
598                 i = 1;
599                 inParam.val1 = VideoProcAmp_Contrast;
600                 break;
601         case V4L2_CID_SATURATION:
602                 i = 2;
603                 inParam.val1 = VideoProcAmp_Saturation;
604                 break;
605         case V4L2_CID_SHARPNESS:
606                 i = 3;
607                 inParam.val1 = VideoProcAmp_Sharpness;
608                 break;
609         default:
610                 param->errCode = EINVAL;
611                 return;
612         }
613         inParam.val2 = value_convert_from_guest(qctrl_tbl[i].min,
614                         qctrl_tbl[i].max, (long)param->stack[1]);
615         hr = SVCamCtrl(HWC_S_CTRL, sizeof(inParam), &inParam);
616         if (FAILED(hr)) {
617                 param->errCode = EINVAL;
618                 ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr);
619                 return;
620         }
621 }
622
623 void svcam_device_g_ctrl(SVCamState* state)
624 {
625         HRESULT hr;
626         uint32_t i;
627         HWCParam inParam = {0,};
628         SVCamParam *param = state->thread->param;
629
630         param->top = 0;
631         switch (param->stack[0]) {
632         case V4L2_CID_BRIGHTNESS:
633                 i = 0;
634                 inParam.val1 = VideoProcAmp_Brightness;
635                 break;
636         case V4L2_CID_CONTRAST:
637                 i = 1;
638                 inParam.val1 = VideoProcAmp_Contrast;
639                 break;
640         case V4L2_CID_SATURATION:
641                 i = 2;
642                 inParam.val1 = VideoProcAmp_Saturation;
643                 break;
644         case V4L2_CID_SHARPNESS:
645                 i = 3;
646                 inParam.val1 = VideoProcAmp_Sharpness;
647                 break;
648         default:
649                 param->errCode = EINVAL;
650                 return;
651         }
652
653         hr = SVCamCtrl(HWC_G_CTRL, sizeof(inParam), &inParam);
654         if (FAILED(hr)) {
655                 param->errCode = EINVAL;
656                 ERR("failed to get video control value!!!, [HRESULT : 0x%x]\n", hr);
657                 return;
658         }
659         param->stack[0] = (uint32_t)value_convert_to_guest(qctrl_tbl[i].min,
660                                 qctrl_tbl[i].max, inParam.val2);
661 }
662
663 void svcam_device_enum_fsizes(SVCamState* state)
664 {
665         uint32_t index, pixfmt, i;
666         SVCamParam *param = state->thread->param;
667
668         param->top = 0;
669         index = param->stack[0];
670         pixfmt = param->stack[1];
671
672         if (index >= ARRAY_SIZE(supported_dst_frames)) {
673                 param->errCode = EINVAL;
674                 return;
675         }
676         for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
677                 if (supported_dst_pixfmts[i].fmt == pixfmt)
678                         break;
679         }
680
681         if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
682                 param->errCode = EINVAL;
683                 return;
684         }
685
686         param->stack[0] = supported_dst_frames[index].width;
687         param->stack[1] = supported_dst_frames[index].height;
688 }
689
690 void svcam_device_enum_fintv(SVCamState* state)
691 {
692         SVCamParam *param = state->thread->param;
693
694         param->top = 0;
695
696         // switch by index(param->stack[0])
697         switch (param->stack[0]) {
698         case 0:
699                 param->stack[1] = 30;   // denominator
700                 break;
701         default:
702                 param->errCode = EINVAL;
703                 return;
704         }
705         param->stack[0] = 1;    // numerator
706 }
707
708 void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,
709                 uint32_t width, uint32_t height, uint32_t yvu)
710 {
711         uint32_t i, j;
712         const unsigned char *src1;
713         unsigned char *udest, *vdest;
714
715         /* copy the Y values */
716         src1 = src;
717         for (i = 0; i < height; i++) {
718                 for (j = 0; j < width; j += 2) {
719                         *dest++ = src1[0];
720                         *dest++ = src1[2];
721                         src1 += 4;
722                 }
723         }
724
725         /* copy the U and V values */
726         src++;                          /* point to V */
727         src1 = src + width * 2;         /* next line */
728         if (yvu) {
729                 vdest = dest;
730                 udest = dest + width * height / 4;
731         } else {
732                 udest = dest;
733                 vdest = dest + width * height / 4;
734         }
735         for (i = 0; i < height; i += 2) {
736                 for (j = 0; j < width; j += 2) {
737                         *udest++ = ((int) src[0] + src1[0]) / 2;        /* U */
738                         *vdest++ = ((int) src[2] + src1[2]) / 2;        /* V */
739                         src += 4;
740                         src1 += 4;
741                 }
742                 src = src1;
743                 src1 += width * 2;
744         }
745 }