camera: Implement camera on Mac
authorJun Tian <jun.j.tian@intel.com>
Tue, 13 Nov 2012 02:39:13 +0000 (10:39 +0800)
committerJun Tian <jun.j.tian@intel.com>
Tue, 13 Nov 2012 02:41:15 +0000 (10:41 +0800)
Implement camera emulation driver by Cocoa QTKit framework.

Signed-off-by: Jun Tian <jun.j.tian@intel.com>
tizen/emulator_configure.sh
tizen/src/Makefile.tizen
tizen/src/emulator.c
tizen/src/hw/maru_camera_darwin.h [new file with mode: 0644]
tizen/src/hw/maru_camera_darwin_converter.c [new file with mode: 0644]
tizen/src/hw/maru_camera_darwin_pci.m [new file with mode: 0644]
tizen/src/ns_event.h [new file with mode: 0644]
tizen/src/ns_event.m [new file with mode: 0644]

index deaee48567759f0fc4d98bf6e4da67fdaecc2195..795a023979b8675c337cfd69ea4ff0e831056aea 100755 (executable)
@@ -279,8 +279,8 @@ echo "##### QEMU configure append:" $CONFIGURE_APPEND
  --enable-maru \
  --enable-hax \
  --disable-vnc \
- --disable-cocoa \
- --enable-gl \
+ --enable-cocoa \
+ --disable-gl \
  --disable-sdl $1
 ;;
 esac
index 75b0c8def27df69e5a92278343d68556b2c19b46..40e005ae3d4769640131f70ab1b819f9fb99cce3 100755 (executable)
@@ -11,6 +11,7 @@ QEMU_CFLAGS += $(SDL_CFLAGS)
 QEMU_CFLAGS += $(GLIB_CFLAGS)
 ifdef CONFIG_DARWIN
 QEMU_CFLAGS += -framework Foundation -framework SystemConfiguration
+QEMU_CFLAGS += -framework Cocoa -framework QTKit -framework CoreVideo
 endif
 ifndef CONFIG_DEBUG_EXEC
 CFLAGS += -g -O2
@@ -99,6 +100,11 @@ obj-y += sdb.o
 # mloop event
 obj-y += mloop_event.o
 
+# NSRunLoop on Mac
+ifdef CONFIG_DARWIN
+obj-y += ns_event.o
+endif
+
 # debug channel
 obj-y += debug_ch.o
 
@@ -109,11 +115,12 @@ obj-y += maru_brightness.o
 obj-y += maru_usb_touchscreen.o maru_virtio_touchscreen.o
 obj-y += maru_virtio_keyboard.o
 obj-y += maru_codec.o
-ifndef CONFIG_DARWIN
+
 obj-$(CONFIG_PCI) += maru_camera_common_pci.o
 obj-$(CONFIG_LINUX) += maru_camera_linux_pci.o
 obj-$(CONFIG_WIN32) += maru_camera_win32_pci.o
-endif
+obj-$(CONFIG_DARWIN) += maru_camera_darwin_converter.o
+obj-$(CONFIG_DARWIN) += maru_camera_darwin_pci.o
 
 ifdef CONFIG_LINUX # libs for maru camera on linux host
 LIBS += -lv4l2 -lv4lconvert
index c00ffcfcdf71caa401d77b6762669d1618386212..b211dd3b7cd952ab52f4029baf8c68409f5aa31c 100644 (file)
@@ -66,6 +66,7 @@
 #include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/shm.h>
+#include "tizen/src/ns_event.h"
 #endif
 
 #include "mloop_event.h"
@@ -92,6 +93,10 @@ static char **skin_argv;
 static int qemu_argc;
 static char **qemu_argv;
 
+#ifdef CONFIG_DARWIN
+int thread_running = 1; /* Check if we need exit main */
+#endif
+
 void maru_display_fini(void);
 
 char *get_logpath(void)
@@ -541,8 +546,34 @@ void prepare_maru(void)
 
 int qemu_main(int argc, char **argv, char **envp);
 
+#ifdef CONFIG_DARWIN
+int g_argc;
+
+void* main_thread(void* args);
+
 int main(int argc, char *argv[])
 {
+    char** args;
+    pthread_t main_thread_id;
+
+    g_argc = argc;
+    args = argv;
+
+    if (0 != pthread_create(&main_thread_id, NULL, main_thread, args)) {
+        INFO("Create main thread failed\n");
+        return -1;
+    }
+
+    ns_event_loop(&thread_running);
+    return 0;
+}
+
+void* main_thread(void* args)
+{
+    char** argv;
+    int argc = g_argc;
+
+    argv = (char**) args;
     parse_options(argc, argv, &skin_argc, &skin_argv, &qemu_argc, &qemu_argv);
     get_bin_dir(qemu_argv[0]);
     socket_init();
@@ -583,7 +614,55 @@ int main(int argc, char *argv[])
     qemu_main(qemu_argc, qemu_argv, NULL);
 
     exit_emulator();
+    thread_running = 0;
+    pthread_exit(NULL);
 
     return 0;
 }
+#else
+int main(int argc, char *argv[])
+{
+    parse_options(argc, argv, &skin_argc, &skin_argv, &qemu_argc, &qemu_argv);
+    get_bin_dir(qemu_argv[0]);
+    socket_init();
+    extract_qemu_info(qemu_argc, qemu_argv);
+
+    INFO("Emulator start !!!\n");
+    atexit(maru_atexit);
 
+    extract_skin_info(skin_argc, skin_argv);
+
+    check_shdmem();
+    make_shdmem();
+    sdb_setup();
+
+    system_info();
+
+    INFO("Prepare running...\n");
+    /* Redirect stdout and stderr after debug_ch is initialized. */
+    redir_output();
+
+    int i;
+
+    fprintf(stdout, "qemu args : =========================================\n");
+    for (i = 0; i < qemu_argc; ++i) {
+        fprintf(stdout, "%s ", qemu_argv[i]);
+    }
+    fprintf(stdout, "\n");
+    fprintf(stdout, "=====================================================\n");
+
+    fprintf(stdout, "skin args : =========================================\n");
+    for (i = 0; i < skin_argc; ++i) {
+        fprintf(stdout, "%s ", skin_argv[i]);
+    }
+    fprintf(stdout, "\n");
+    fprintf(stdout, "=====================================================\n");
+
+    INFO("qemu main start!\n");
+    qemu_main(qemu_argc, qemu_argv, NULL);
+
+    exit_emulator();
+
+    return 0;
+}
+#endif
diff --git a/tizen/src/hw/maru_camera_darwin.h b/tizen/src/hw/maru_camera_darwin.h
new file mode 100644 (file)
index 0000000..25e4807
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _MARU_CAMERA_DARWIN_H_
+#define _MARU_CAMERA_DARWIN_H_
+
+#define MAKEFOURCC(a,b,c,d)\
+    (((uint32_t)(a)<<0)|((uint32_t)(b)<<8)|((uint32_t)(c)<<16)|((uint32_t)(d)<<24))
+
+/*      Pixel format         FOURCC                        depth  Description  */
+#define V4L2_PIX_FMT_RGB555  MAKEFOURCC('R','G','B','O') /* 16  RGB-5-5-5     */
+#define V4L2_PIX_FMT_RGB565  MAKEFOURCC('R','G','B','P') /* 16  RGB-5-6-5     */
+#define V4L2_PIX_FMT_RGB555X MAKEFOURCC('R','G','B','Q') /* 16  RGB-5-5-5 BE  */
+#define V4L2_PIX_FMT_RGB565X MAKEFOURCC('R','G','B','R') /* 16  RGB-5-6-5 BE  */
+#define V4L2_PIX_FMT_BGR24   MAKEFOURCC('B','G','R','3') /* 24  BGR-8-8-8     */
+#define V4L2_PIX_FMT_RGB24   MAKEFOURCC('R','G','B','3') /* 24  RGB-8-8-8     */
+#define V4L2_PIX_FMT_BGR32   MAKEFOURCC('B','G','R','4') /* 32  BGR-8-8-8-8   */
+#define V4L2_PIX_FMT_RGB32   MAKEFOURCC('R','G','B','4') /* 32  RGB-8-8-8-8   */
+#define V4L2_PIX_FMT_YVU410  MAKEFOURCC('Y','V','U','9') /*  9  YVU 4:1:0     */
+#define V4L2_PIX_FMT_YVU420  MAKEFOURCC('Y','V','1','2') /* 12  YVU 4:2:0     */
+#define V4L2_PIX_FMT_YUYV    MAKEFOURCC('Y','U','Y','V') /* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_UYVY    MAKEFOURCC('U','Y','V','Y') /* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_YUV422P MAKEFOURCC('4','2','2','P') /* 16  YVU422 planar */
+#define V4L2_PIX_FMT_YUV411P MAKEFOURCC('4','1','1','P') /* 16  YVU411 planar */
+#define V4L2_PIX_FMT_Y41P    MAKEFOURCC('Y','4','1','P') /* 12  YUV 4:1:1     */
+#define V4L2_PIX_FMT_YUV444  MAKEFOURCC('Y','4','4','4') /* 16  xxxxyyyy uuuuvvvv */
+#define V4L2_PIX_FMT_YUV555  MAKEFOURCC('Y','U','V','O') /* 16  YUV-5-5-5     */
+#define V4L2_PIX_FMT_YUV565  MAKEFOURCC('Y','U','V','P') /* 16  YUV-5-6-5     */
+#define V4L2_PIX_FMT_YUV32   MAKEFOURCC('Y','U','V','4') /* 32  YUV-8-8-8-8   */
+#define V4L2_PIX_FMT_YUV410  MAKEFOURCC('Y','U','V','9') /*  9  YUV 4:1:0     */
+#define V4L2_PIX_FMT_YUV420  MAKEFOURCC('Y','U','1','2') /* 12  YUV 4:2:0     */
+#define V4L2_PIX_FMT_YYUV    MAKEFOURCC('Y','Y','U','V') /* 16  YUV 4:2:2     */
+
+void convert_frame(uint32_t pixel_format, int frame_width, int frame_height,
+                   size_t frame_size, void* frame_pixels, void* video_buf);
+
+#endif /* _MARU_CAMERA_DARWIN_H_ */
diff --git a/tizen/src/hw/maru_camera_darwin_converter.c b/tizen/src/hw/maru_camera_darwin_converter.c
new file mode 100644 (file)
index 0000000..1037fc7
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#include "qemu-common.h"
+#include "maru_camera_darwin.h"
+
+static void UYVYToYUV420(unsigned char *bufsrc, unsigned char *bufdest, int width, int height);
+static void YVU420ToYUV420(unsigned char *bufsrc, unsigned char *bufdest, int width, int height);
+static void YUYVToYUV420(unsigned char *bufsrc, unsigned char *bufdest, int width, int height);
+
+/* Convert pixel format to YUV420 */
+void convert_frame(uint32_t pixel_format, int frame_width, int frame_height,
+                    size_t frame_size, void* frame_pixels, void* video_buf)
+{
+    switch (pixel_format) {
+        case V4L2_PIX_FMT_YUV420:
+            printf("format: V4L2_PIX_FMT_YUV420\n");
+            memcpy(video_buf, (void*)frame_pixels, (size_t)frame_size);
+            break;
+        case V4L2_PIX_FMT_YVU420:
+            printf("format: V4L2_PIX_FMT_YVU420\n");
+            YVU420ToYUV420(frame_pixels, video_buf, frame_width, frame_height);
+            break;
+        case V4L2_PIX_FMT_YUYV:
+            printf("format: V4L2_PIX_FMT_YUYV\n");
+            YUYVToYUV420(frame_pixels, video_buf, frame_width, frame_height);
+            break;
+        case V4L2_PIX_FMT_UYVY: // Mac default format
+            printf("format: V4L2_PIX_FMT_UYVY\n");
+            UYVYToYUV420(frame_pixels, video_buf, frame_width, frame_height);
+            break;
+        default:
+            printf("Cannot convert the pixel format (%.4s)...\n", (const char*)&pixel_format);
+            break;
+    }
+}
+
+static void UYVYToYUV420(unsigned char *bufsrc, unsigned char *bufdest, int width, int height)
+{
+    int i, j;
+
+    /* Source */
+    unsigned char *ptrsrcy1, *ptrsrcy2;
+       unsigned char *ptrsrcy3, *ptrsrcy4;
+       unsigned char *ptrsrccb1, *ptrsrccb2;
+       unsigned char *ptrsrccb3, *ptrsrccb4;
+       unsigned char *ptrsrccr1, *ptrsrccr2;
+       unsigned char *ptrsrccr3, *ptrsrccr4;
+       int srcystride, srcccstride;
+
+       ptrsrcy1  = bufsrc + 1;
+       ptrsrcy2  = bufsrc + (width<<1) + 1;
+       ptrsrcy3  = bufsrc + (width<<1)*2 + 1;
+       ptrsrcy4  = bufsrc + (width<<1)*3 + 1;
+
+       ptrsrccb1 = bufsrc;
+       ptrsrccb2 = bufsrc + (width<<1);
+       ptrsrccb3 = bufsrc + (width<<1)*2;
+       ptrsrccb4 = bufsrc + (width<<1)*3;
+
+       ptrsrccr1 = bufsrc + 2;
+       ptrsrccr2 = bufsrc + (width<<1) + 2;
+       ptrsrccr3 = bufsrc + (width<<1)*2 + 2;
+       ptrsrccr4 = bufsrc + (width<<1)*3 + 2;
+
+       srcystride  = (width<<1)*3;
+       srcccstride = (width<<1)*3;
+
+    /* Destination */
+       unsigned char *ptrdesty1, *ptrdesty2;
+       unsigned char *ptrdesty3, *ptrdesty4;
+       unsigned char *ptrdestcb1, *ptrdestcb2;
+       unsigned char *ptrdestcr1, *ptrdestcr2;
+       int destystride, destccstride;
+
+       ptrdesty1 = bufdest;
+       ptrdesty2 = bufdest + width;
+       ptrdesty3 = bufdest + width*2;
+       ptrdesty4 = bufdest + width*3;
+
+       ptrdestcb1 = bufdest + width*height;
+       ptrdestcb2 = bufdest + width*height + (width>>1);
+
+       ptrdestcr1 = bufdest + width*height + ((width*height) >> 2);
+       ptrdestcr2 = bufdest + width*height + ((width*height) >> 2) + (width>>1);
+
+       destystride  = (width)*3;
+       destccstride = (width>>1);
+
+       for(j=0; j<(height/4); j++)
+       {
+               for(i=0;i<(width/2);i++)
+               {
+                       (*ptrdesty1++) = (*ptrsrcy1);
+                       (*ptrdesty2++) = (*ptrsrcy2);
+                       (*ptrdesty3++) = (*ptrsrcy3);
+                       (*ptrdesty4++) = (*ptrsrcy4);
+
+                       ptrsrcy1 += 2;
+                       ptrsrcy2 += 2;
+                       ptrsrcy3 += 2;
+                       ptrsrcy4 += 2;
+
+                       (*ptrdesty1++) = (*ptrsrcy1);
+                       (*ptrdesty2++) = (*ptrsrcy2);
+                       (*ptrdesty3++) = (*ptrsrcy3);
+                       (*ptrdesty4++) = (*ptrsrcy4);
+
+                       ptrsrcy1 += 2;
+                       ptrsrcy2 += 2;
+                       ptrsrcy3 += 2;
+                       ptrsrcy4 += 2;
+
+                       (*ptrdestcb1++) = (*ptrsrccb1);
+                       (*ptrdestcb2++) = (*ptrsrccb3);
+
+                       ptrsrccb1 += 4;
+                       ptrsrccb3 += 4;
+
+                       (*ptrdestcr1++) = (*ptrsrccr1);
+                       (*ptrdestcr2++) = (*ptrsrccr3);
+
+                       ptrsrccr1 += 4;
+                       ptrsrccr3 += 4;
+
+               }
+
+               /* Update src pointers */
+               ptrsrcy1  += srcystride;
+               ptrsrcy2  += srcystride;
+               ptrsrcy3  += srcystride;
+               ptrsrcy4  += srcystride;
+
+               ptrsrccb1 += srcccstride;
+               ptrsrccb3 += srcccstride;
+
+               ptrsrccr1 += srcccstride;
+               ptrsrccr3 += srcccstride;
+
+               /* Update dest pointers */
+               ptrdesty1 += destystride;
+               ptrdesty2 += destystride;
+               ptrdesty3 += destystride;
+               ptrdesty4 += destystride;
+
+               ptrdestcb1 += destccstride;
+               ptrdestcb2 += destccstride;
+
+               ptrdestcr1 += destccstride;
+               ptrdestcr2 += destccstride;
+    }
+}
+
+static void YVU420ToYUV420(unsigned char *bufsrc, unsigned char *bufdest, int width, int height)
+{
+    int i, j;
+
+    /* Source*/
+    unsigned char *ptrsrcy1, *ptrsrcy2;
+       unsigned char *ptrsrcy3, *ptrsrcy4;
+       unsigned char *ptrsrccb1, *ptrsrccb2;
+       unsigned char *ptrsrccr1, *ptrsrccr2;
+       int srcystride, srcccstride;
+
+       ptrsrcy1 = bufsrc;
+       ptrsrcy2 = bufsrc + width;
+       ptrsrcy3 = bufsrc + width*2;
+       ptrsrcy4 = bufsrc + width*3;
+
+       ptrsrccr1 = bufsrc + width*height;
+       ptrsrccr2 = bufsrc + width*height + (width>>1);
+
+       ptrsrccb1 = bufsrc + width*height + ((width*height) >> 2);
+       ptrsrccb2 = bufsrc + width*height + ((width*height) >> 2) + (width>>1);
+
+       srcystride  = (width)*3;
+       srcccstride = (width>>1);
+
+    /* Destination */
+    unsigned char *ptrdesty1, *ptrdesty2;
+       unsigned char *ptrdesty3, *ptrdesty4;
+       unsigned char *ptrdestcb1, *ptrdestcb2;
+       unsigned char *ptrdestcr1, *ptrdestcr2;
+       int destystride, destccstride;
+
+       ptrdesty1 = bufdest;
+       ptrdesty2 = bufdest + width;
+       ptrdesty3 = bufdest + width*2;
+       ptrdesty4 = bufdest + width*3;
+
+       ptrdestcb1 = bufdest + width*height;
+       ptrdestcb2 = bufdest + width*height + (width>>1);
+
+       ptrdestcr1 = bufdest + width*height + ((width*height) >> 2);
+       ptrdestcr2 = bufdest + width*height + ((width*height) >> 2) + (width>>1);
+
+       destystride  = (width)*3;
+       destccstride = (width>>1);
+
+       for(j=0; j<(height/4); j++)
+       {
+               for(i=0;i<(width/2);i++)
+               {
+
+                       (*ptrdesty1++) = (*ptrsrcy1++);
+                       (*ptrdesty2++) = (*ptrsrcy2++);
+                       (*ptrdesty3++) = (*ptrsrcy3++);
+                       (*ptrdesty4++) = (*ptrsrcy4++);
+                       (*ptrdesty1++) = (*ptrsrcy1++);
+                       (*ptrdesty2++) = (*ptrsrcy2++);
+                       (*ptrdesty3++) = (*ptrsrcy3++);
+                       (*ptrdesty4++) = (*ptrsrcy4++);
+
+                       (*ptrdestcb1++) = (*ptrsrccb1++);
+                       (*ptrdestcr1++) = (*ptrsrccr1++);
+                       (*ptrdestcb2++) = (*ptrsrccb2++);
+                       (*ptrdestcr2++) = (*ptrsrccr2++);
+
+               }
+
+               /* Update src pointers */
+               ptrsrcy1  += srcystride;
+               ptrsrcy2  += srcystride;
+               ptrsrcy3  += srcystride;
+               ptrsrcy4  += srcystride;
+
+               ptrsrccb1 += srcccstride;
+               ptrsrccb2 += srcccstride;
+
+               ptrsrccr1 += srcccstride;
+               ptrsrccr2 += srcccstride;
+
+               /* Update dest pointers */
+               ptrdesty1 += destystride;
+               ptrdesty2 += destystride;
+               ptrdesty3 += destystride;
+               ptrdesty4 += destystride;
+
+               ptrdestcb1 += destccstride;
+               ptrdestcb2 += destccstride;
+
+               ptrdestcr1 += destccstride;
+               ptrdestcr2 += destccstride;
+
+       }
+
+}
+
+static void YUYVToYUV420(unsigned char *bufsrc, unsigned char *bufdest, int width, int height)
+{
+       int i, j;
+
+    /* Source*/
+    unsigned char *ptrsrcy1, *ptrsrcy2;
+       unsigned char *ptrsrcy3, *ptrsrcy4;
+       unsigned char *ptrsrccb1, *ptrsrccb2;
+       unsigned char *ptrsrccb3, *ptrsrccb4;
+       unsigned char *ptrsrccr1, *ptrsrccr2;
+       unsigned char *ptrsrccr3, *ptrsrccr4;
+       int srcystride, srcccstride;
+
+       ptrsrcy1  = bufsrc ;
+       ptrsrcy2  = bufsrc + (width<<1) ;
+       ptrsrcy3  = bufsrc + (width<<1)*2 ;
+       ptrsrcy4  = bufsrc + (width<<1)*3 ;
+
+       ptrsrccb1 = bufsrc + 1;
+       ptrsrccb2 = bufsrc + (width<<1) + 1;
+       ptrsrccb3 = bufsrc + (width<<1)*2 + 1;
+       ptrsrccb4 = bufsrc + (width<<1)*3 + 1;
+
+       ptrsrccr1 = bufsrc + 3;
+       ptrsrccr2 = bufsrc + (width<<1) + 3;
+       ptrsrccr3 = bufsrc + (width<<1)*2 + 3;
+       ptrsrccr4 = bufsrc + (width<<1)*3 + 3;
+
+       srcystride  = (width<<1)*3;
+       srcccstride = (width<<1)*3;
+
+    /* Destination */
+    unsigned char *ptrdesty1, *ptrdesty2;
+       unsigned char *ptrdesty3, *ptrdesty4;
+       unsigned char *ptrdestcb1, *ptrdestcb2;
+       unsigned char *ptrdestcr1, *ptrdestcr2;
+       int destystride, destccstride;
+
+       ptrdesty1 = bufdest;
+       ptrdesty2 = bufdest + width;
+       ptrdesty3 = bufdest + width*2;
+       ptrdesty4 = bufdest + width*3;
+
+       ptrdestcb1 = bufdest + width*height;
+       ptrdestcb2 = bufdest + width*height + (width>>1);
+
+       ptrdestcr1 = bufdest + width*height + ((width*height) >> 2);
+       ptrdestcr2 = bufdest + width*height + ((width*height) >> 2) + (width>>1);
+
+       destystride  = (width)*3;
+       destccstride = (width>>1);
+
+       for(j=0; j<(height/4); j++)
+       {
+               for(i=0;i<(width/2);i++)
+               {
+                       (*ptrdesty1++) = (*ptrsrcy1);
+                       (*ptrdesty2++) = (*ptrsrcy2);
+                       (*ptrdesty3++) = (*ptrsrcy3);
+                       (*ptrdesty4++) = (*ptrsrcy4);
+
+                       ptrsrcy1 += 2;
+                       ptrsrcy2 += 2;
+                       ptrsrcy3 += 2;
+                       ptrsrcy4 += 2;
+
+                       (*ptrdesty1++) = (*ptrsrcy1);
+                       (*ptrdesty2++) = (*ptrsrcy2);
+                       (*ptrdesty3++) = (*ptrsrcy3);
+                       (*ptrdesty4++) = (*ptrsrcy4);
+
+                       ptrsrcy1 += 2;
+                       ptrsrcy2 += 2;
+                       ptrsrcy3 += 2;
+                       ptrsrcy4 += 2;
+
+                       (*ptrdestcb1++) = (*ptrsrccb1);
+                       (*ptrdestcb2++) = (*ptrsrccb3);
+
+                       ptrsrccb1 += 4;
+                       ptrsrccb3 += 4;
+
+                       (*ptrdestcr1++) = (*ptrsrccr1);
+                       (*ptrdestcr2++) = (*ptrsrccr3);
+
+                       ptrsrccr1 += 4;
+                       ptrsrccr3 += 4;
+
+               }
+
+               /* Update src pointers */
+               ptrsrcy1  += srcystride;
+               ptrsrcy2  += srcystride;
+               ptrsrcy3  += srcystride;
+               ptrsrcy4  += srcystride;
+
+               ptrsrccb1 += srcccstride;
+               ptrsrccb3 += srcccstride;
+
+               ptrsrccr1 += srcccstride;
+               ptrsrccr3 += srcccstride;
+
+               /* Update dest pointers */
+               ptrdesty1 += destystride;
+               ptrdesty2 += destystride;
+               ptrdesty3 += destystride;
+               ptrdesty4 += destystride;
+
+               ptrdestcb1 += destccstride;
+               ptrdestcb2 += destccstride;
+
+               ptrdestcr1 += destccstride;
+               ptrdestcr2 += destccstride;
+       }
+}
diff --git a/tizen/src/hw/maru_camera_darwin_pci.m b/tizen/src/hw/maru_camera_darwin_pci.m
new file mode 100644 (file)
index 0000000..e91bbf1
--- /dev/null
@@ -0,0 +1,848 @@
+/*
+ * Implementation of MARU Virtual Camera device by PCI bus on Linux.
+ *
+ * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * JinHyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ * Jun Tian <jun.j.tian@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#import <Cocoa/Cocoa.h>
+#import <QTKit/QTKit.h>
+#import <CoreAudio/CoreAudio.h>
+
+#include <pthread.h>
+#include "qemu-common.h"
+#include "maru_camera_common.h"
+#include "maru_camera_darwin.h"
+#include "pci.h"
+#include "tizen/src/debug_ch.h"
+
+MULTI_DEBUG_CHANNEL(tizen, camera_darwin);
+
+/* V4L2 defines copy from videodev2.h */
+#define V4L2_CTRL_FLAG_SLIDER       0x0020
+
+#define V4L2_CTRL_CLASS_USER        0x00980000
+#define V4L2_CID_BASE               (V4L2_CTRL_CLASS_USER | 0x900)
+#define V4L2_CID_BRIGHTNESS         (V4L2_CID_BASE+0)
+#define V4L2_CID_CONTRAST           (V4L2_CID_BASE+1)
+#define V4L2_CID_SATURATION         (V4L2_CID_BASE+2)
+#define V4L2_CID_SHARPNESS          (V4L2_CID_BASE+27)
+
+typedef struct tagMaruCamConvertPixfmt {
+    uint32_t fmt;   /* fourcc */
+    uint32_t bpp;   /* bits per pixel, 0 for compressed formats */
+    uint32_t needs_conversion;
+} MaruCamConvertPixfmt;
+
+
+static MaruCamConvertPixfmt supported_dst_pixfmts[] = {
+    { V4L2_PIX_FMT_YUYV, 16, 0 },
+    { V4L2_PIX_FMT_UYVY, 16, 0 },
+    { V4L2_PIX_FMT_YUV420, 12, 0 },
+    { V4L2_PIX_FMT_YVU420, 12, 0 },
+};
+
+typedef struct tagMaruCamConvertFrameInfo {
+    uint32_t width;
+    uint32_t height;
+} MaruCamConvertFrameInfo;
+
+static MaruCamConvertFrameInfo supported_dst_frames[] = {
+    { 640, 480 },
+    { 352, 288 },
+    { 320, 240 },
+    { 176, 144 },
+    { 160, 120 },
+};
+
+#define MARUCAM_CTRL_VALUE_MAX      20
+#define MARUCAM_CTRL_VALUE_MIN      1
+#define MARUCAM_CTRL_VALUE_MID      10
+#define MARUCAM_CTRL_VALUE_STEP     1
+
+#if 0
+struct marucam_qctrl {
+    uint32_t id;
+    uint32_t hit;
+    long min;
+    long max;
+    long step;
+    long init_val;
+};
+
+static struct marucam_qctrl qctrl_tbl[] = {
+    { V4L2_CID_BRIGHTNESS, 0, },
+    { V4L2_CID_CONTRAST, 0, },
+    { V4L2_CID_SATURATION,0, },
+    { V4L2_CID_SHARPNESS, 0, },
+};
+#endif
+
+static MaruCamState *g_state = NULL;
+
+static uint32_t ready_count = 0;
+static uint32_t cur_fmt_idx = 0;
+static uint32_t cur_frame_idx = 0;
+
+/***********************************
+ * Mac camera helper functions
+ ***********************************/
+
+/* Returns current time in microseconds. */
+static uint64_t camera_get_timestamp(void)
+{
+    struct timeval t;
+    t.tv_sec = t.tv_usec = 0;
+    gettimeofday(&t, NULL);
+    return (uint64_t)t.tv_sec * 1000000LL + t.tv_usec;
+}
+
+/* Sleeps for the given amount of milliseconds */
+static void camera_sleep(int millisec)
+{
+    struct timeval t;
+    const uint64_t wake_at = camera_get_timestamp() + (uint64_t)millisec * 1000;
+    do {
+        const uint64_t stamp = camera_get_timestamp();
+        if ((stamp / 1000) >= (wake_at / 1000)) {
+            break;
+        }
+        t.tv_sec = (wake_at - stamp) / 1000000;
+        t.tv_usec = (wake_at - stamp) - (uint64_t)t.tv_sec * 1000000;
+    } while (select(0, NULL, NULL, NULL, &t) < 0 && errno == EINTR);
+}
+
+// Convert Core Video format to FOURCC
+static uint32_t corevideo_to_fourcc(uint32_t cv_pix_fmt)
+{
+    //INFO("%s, cv_pix_fmt:%d, %s\n", __FUNCTION__, cv_pix_fmt, (const char*)&cv_pix_fmt);
+    switch (cv_pix_fmt) {
+        case kCVPixelFormatType_420YpCbCr8Planar:
+            return V4L2_PIX_FMT_YVU420;
+        case kCVPixelFormatType_422YpCbCr8:
+            return V4L2_PIX_FMT_UYVY;
+        case kCVPixelFormatType_422YpCbCr8_yuvs:
+            return V4L2_PIX_FMT_YUYV;
+        case kCVPixelFormatType_32ARGB:
+        case kCVPixelFormatType_32RGBA:
+            return V4L2_PIX_FMT_RGB32;
+        case kCVPixelFormatType_32BGRA:
+        case kCVPixelFormatType_32ABGR:
+            return V4L2_PIX_FMT_BGR32;
+        case kCVPixelFormatType_24RGB:
+            return V4L2_PIX_FMT_RGB24;
+        case kCVPixelFormatType_24BGR:
+            return V4L2_PIX_FMT_BGR32;
+        default:
+            ERR("Unknown pixel format '%.4s'", (const char*)&cv_pix_fmt);
+            return 0;
+    }
+}
+
+static uint32_t get_bytesperline(uint32_t pixfmt, uint32_t width)
+{
+    uint32_t bytesperline;
+
+    switch (pixfmt) {
+        case V4L2_PIX_FMT_YUV420:
+        case V4L2_PIX_FMT_YVU420:
+            bytesperline = (width * 12) >> 3;
+            break;
+        case V4L2_PIX_FMT_YUYV:
+        case V4L2_PIX_FMT_UYVY:
+        default:
+            bytesperline = width * 2;
+            break;
+    }
+
+    return bytesperline;
+}
+
+static uint32_t get_sizeimage(uint32_t pixfmt, uint32_t width, uint32_t height)
+{
+    return (get_bytesperline(pixfmt, width) * height);
+}
+
+///////////////////////////////////////////////////////////////////
+//   Maru Camera Implementation
+///////////////////////////////////////////////////////////////////
+
+@interface MaruCameraDriver : NSObject {
+    QTCaptureSession               *mCaptureSession;
+    //QTCaptureMovieFileOutput       *mCaptureMovieFileOutput;
+    QTCaptureVideoPreviewOutput    *mCaptureVideoPreviewOutput;
+    QTCaptureDeviceInput           *mCaptureVideoDeviceInput;
+    QTCaptureDeviceInput           *mCaptureAudioDeviceInput;
+
+    CVImageBufferRef      mCurrentImageBuffer;
+    CVImageBufferRef imageBuffer;
+    BOOL mDeviceIsOpened;
+    BOOL mCaptureIsStarted;
+}
+
+- (MaruCameraDriver*)init;
+- (int)startCapture:(int)width:(int)height;
+- (int)readFrame:(void*)video_buf;
+- (int)setCaptureFormat:(int)width:(int)height:(int)pix_format;
+- (int)getCaptureFormat:(int)width:(int)height:(int)pix_format;
+- (BOOL)deviceStatus;
+
+@end
+
+@implementation MaruCameraDriver
+
+- (MaruCameraDriver*)init
+{
+       BOOL success = NO;
+       NSError *error;
+    mDeviceIsOpened = NO;
+    mCaptureIsStarted = NO;
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+    // Create the capture session
+    mCaptureSession = [[QTCaptureSession alloc] init];
+
+    // Find a video device
+    QTCaptureDevice *videoDevice = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo];
+    success = [videoDevice open:&error];
+
+    // If a video input device can't be found or opened, try to find and open a muxed input device
+       if (!success) {
+        videoDevice = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeMuxed];
+               success = [videoDevice open:&error];
+        [pool release];
+        return nil;
+    }
+
+    if (!success) {
+        videoDevice = nil;
+        [pool release];
+        return nil;
+    }
+
+    if (videoDevice) {
+        // Add the video device to the session as a device input
+               mCaptureVideoDeviceInput = [[QTCaptureDeviceInput alloc] initWithDevice:videoDevice];
+        success = [mCaptureSession addInput:mCaptureVideoDeviceInput error:&error];
+
+        if (!success) {
+            [pool release];
+            return nil;
+               }
+
+        mCaptureVideoPreviewOutput = [[QTCaptureVideoPreviewOutput alloc] init];
+        success = [mCaptureSession addOutput:mCaptureVideoPreviewOutput error:&error];
+        if (!success) {
+            [pool release];
+            return nil;
+        }
+
+        mDeviceIsOpened = YES;
+        [mCaptureVideoPreviewOutput setDelegate:self];
+        INFO("Camera session bundling successfully!\n");
+        [pool release];
+        return self;
+    } else {
+        [pool release];
+        return nil;
+    }
+}
+
+- (int)startCapture:(int)width:(int)height
+{
+    int ret = -1;
+
+    if (![mCaptureSession isRunning]) {
+        /* Set width & height, using default pixel format to capture */
+        NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
+                                                      [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey,
+                                                      [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey,
+                                                 nil];
+        [mCaptureVideoPreviewOutput setPixelBufferAttributes:attributes];
+        [mCaptureSession startRunning];
+    } else {
+        ERR("Capture session is already running, exit\n");
+        return ret;
+    }
+
+    if ([mCaptureSession isRunning]) {
+        while(!mCaptureIsStarted) {
+            // Wait Until Capture is started
+            [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1]];
+        }
+        INFO("Capture session started!\n");
+        ret = 0;
+    }
+    return ret;
+}
+
+- (int)readFrame:(void*)video_buf
+{
+    int ret = -1;
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+    @synchronized (self) {
+        if (mCurrentImageBuffer != nil) {
+            const uint32_t pixel_format = corevideo_to_fourcc(CVPixelBufferGetPixelFormatType(mCurrentImageBuffer));
+            const int frame_width = CVPixelBufferGetWidth(mCurrentImageBuffer);
+            const int frame_height = CVPixelBufferGetHeight(mCurrentImageBuffer);
+            const size_t frame_size =CVPixelBufferGetBytesPerRow(mCurrentImageBuffer) * frame_height;
+            INFO("buffer(%p), pixel_format(%d,%.4s), frame_width(%d), frame_height(%d0, frame_size(%d)\n",
+                 mCurrentImageBuffer, (int)pixel_format, (const char*)&pixel_format, frame_width, frame_height, (int)frame_size);
+
+            //convert frame to v4l2 format
+            CVPixelBufferLockBaseAddress(mCurrentImageBuffer, 0);
+            const void* frame_pixels = CVPixelBufferGetBaseAddress(mCurrentImageBuffer);
+            if (frame_pixels != nil && video_buf != nil) {
+                convert_frame(pixel_format, frame_width, frame_height,
+                              frame_size, (void*)frame_pixels, video_buf);
+            } else {
+                INFO("Unable to obtain framebuffer");
+                return -1;
+            }
+            CVPixelBufferUnlockBaseAddress(mCurrentImageBuffer, 0);
+            return 0;
+        } else {
+            //INFO("%s, First frame not captured ?\n", __FUNCTION__);
+            return 1;
+        }
+    }
+
+    [pool release];
+    return ret;
+}
+
+- (int)setCaptureFormat:(int)width:(int)height:(int)pix_format
+{
+    int ret = -1;
+    NSDictionary *attributes;
+
+    if (mCaptureSession == nil || mCaptureVideoPreviewOutput == nil) {
+        ERR("Capture session is not initiated.\n");
+        return ret;
+    }
+
+    /* Set the pixel buffer attributes before running the capture session */
+    if (![mCaptureSession isRunning]) {
+        if (pix_format) {
+            attributes = [NSDictionary dictionaryWithObjectsAndKeys:
+                                            [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey,
+                                            [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey,
+                                            [NSNumber numberWithInt: pix_format], (id)kCVPixelBufferPixelFormatTypeKey,
+                                       nil];
+        } else {
+            attributes = [NSDictionary dictionaryWithObjectsAndKeys:
+                                            [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey,
+                                            [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey,
+                                       nil];
+        }
+        [mCaptureVideoPreviewOutput setPixelBufferAttributes:attributes];
+        ret = 0;
+    } else {
+        ERR("Cannot set pixel buffer attributes when it's running.\n");
+        return ret;
+    }
+
+    return ret;
+}
+
+- (int)getCaptureFormat:(int)width:(int)height:(int)pix_format
+{
+    return 0;
+}
+
+/* Get the device bundling status */
+- (BOOL)deviceStatus
+{
+    return mDeviceIsOpened;
+}
+
+/* Handle deallocation of memory for your capture objects */
+
+- (void)dealloc
+{
+       [mCaptureSession release];
+       [mCaptureVideoDeviceInput release];
+    [mCaptureAudioDeviceInput release];
+    [mCaptureVideoPreviewOutput release];
+    [super dealloc];
+}
+
+/* Receive this method whenever the output decompresses and outputs a new video frame */
+- (void)captureOutput:(QTCaptureOutput *)captureOutput didOutputVideoFrame:(CVImageBufferRef)videoFrame
+     withSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection
+{
+    CVImageBufferRef imageBufferToRelease;
+    CVBufferRetain(videoFrame);
+
+    @synchronized (self)
+    {
+        imageBufferToRelease = mCurrentImageBuffer;
+        mCurrentImageBuffer = videoFrame;
+        mCaptureIsStarted = YES;
+    }
+    CVBufferRelease(imageBufferToRelease);
+}
+
+@end
+
+///////////////////////////////////////////////////////////////////
+//   Maru Camera APIs
+///////////////////////////////////////////////////////////////////
+
+typedef struct MaruCameraDevice MaruCameraDevice;
+struct MaruCameraDevice {
+    /* Maru camera device object. */
+    MaruCameraDriver *driver;
+};
+
+/* Golbal representation of the Maru camera */
+MaruCameraDevice *mcd = NULL;
+
+static int marucam_device_read_frame()
+{
+    int ret;
+    void* tmp_buf;
+
+    if (g_state->streamon == 0) {
+        INFO("%s, %d, Streaming is off, exiting ...\n", __FUNCTION__, __LINE__);
+        return -1;
+    }
+
+    qemu_mutex_lock(&g_state->thread_mutex);
+    if (g_state->req_frame == 0) {
+        qemu_mutex_unlock(&g_state->thread_mutex);
+        camera_sleep(30);
+        //INFO("%s, %d, req_frame = 0, next loop\n", __FUNCTION__, __LINE__);
+        return 0;
+    }
+    tmp_buf = g_state->vaddr + g_state->buf_size * (g_state->req_frame - 1);
+    qemu_mutex_unlock(&g_state->thread_mutex);
+
+    ret =  [mcd->driver readFrame: tmp_buf];
+    //INFO("%s, %d, ret:%d\n", __FUNCTION__, __LINE__, ret);
+    if (ret == -1) {
+        //INFO("%s, Capture error\n", __FUNCTION__);
+        return -1;
+    }
+    if(ret == 0) {
+        //INFO("%s, Capture a frame\n", __FUNCTION__);
+    }
+    if(ret == 1) {
+        //INFO("%s, Capture first frame missed\n", __FUNCTION__);
+    }
+
+    qemu_mutex_lock(&g_state->thread_mutex);
+    if (g_state->streamon) {
+        g_state->req_frame = 0; // clear request
+        g_state->isr |= 0x01;   // set a flag of rasing a interrupt
+        qemu_bh_schedule(g_state->tx_bh);
+        ret = 1;
+    } else {
+        ret = -1;
+    }
+    qemu_mutex_unlock(&g_state->thread_mutex);
+    return ret;
+}
+
+/* Worker thread to grab frames to the preview window */
+static void *marucam_worker_thread(void *thread_param)
+{
+  //MaruCamState *state = (MaruCamState*)thread_param;
+
+  wait_worker_thread:
+    qemu_mutex_lock(&g_state->thread_mutex);
+    // Wait on the condition
+    qemu_cond_wait(&g_state->thread_cond, &g_state->thread_mutex);
+    qemu_mutex_unlock(&g_state->thread_mutex);
+
+    /* Loop: capture frame -> convert format -> render to screen */
+    while (1)
+    {
+        if (g_state->streamon) {
+            if (marucam_device_read_frame() < 0) {
+                INFO("Streaming is off ...\n");
+                goto wait_worker_thread;
+            }
+        } else {
+            INFO("Streaming is off ...\n");
+            goto wait_worker_thread;
+        }
+        //camera_sleep(50);
+    }
+    return NULL;
+}
+
+int marucam_device_check(int log_flag)
+{
+    // FIXME: check the device parameters
+    INFO("Checking camera device\n");
+    return 1;
+}
+
+/**********************************************
+ * MARU camera routines
+ **********************************************/
+
+void marucam_device_init(MaruCamState* state)
+{
+    g_state = state;
+    qemu_thread_create(&state->thread_id, marucam_worker_thread, (void*)g_state, QEMU_THREAD_JOINABLE);
+}
+
+/* MARUCAM_CMD_OPEN */
+void marucam_device_open(MaruCamState* state)
+{
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    mcd = (MaruCameraDevice*)malloc(sizeof(MaruCameraDevice));
+    if (mcd != NULL) {
+        memset(mcd, 0, sizeof(MaruCameraDevice));
+    } else {
+        ERR("%s: MaruCameraDevice allocate failed\n", __FUNCTION__);
+    }
+    //qemu_mutex_lock(&state->thread_mutex);
+    mcd->driver = [[MaruCameraDriver alloc] init];
+    //qemu_mutex_unlock(&state->thread_mutex);
+    if (mcd->driver == nil) {
+        INFO("Camera device open failed\n");
+        return;
+    }
+    INFO("Camera opened!\n");
+}
+
+/* MARUCAM_CMD_CLOSE */
+void marucam_device_close(MaruCamState* state)
+{
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    if (mcd != NULL) {
+        [mcd->driver dealloc];
+        free(mcd);
+    }
+
+    //marucam_reset_controls();
+    INFO("Camera closed\n");
+}
+
+/* MARUCAM_CMD_START_PREVIEW */
+void marucam_device_start_preview(MaruCamState* state)
+{
+    uint32_t width, height, pixfmt;
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    ready_count = 0;
+    width = supported_dst_frames[cur_frame_idx].width;
+    height = supported_dst_frames[cur_frame_idx].height;
+    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
+    state->buf_size = get_sizeimage(pixfmt, width, height);
+
+    INFO("Pixfmt(%c%c%c%c), W:H(%d:%d), buf size(%u), frame idx(%d), fmt idx(%d)\n",
+         (char)(pixfmt), (char)(pixfmt >> 8),
+         (char)(pixfmt >> 16), (char)(pixfmt >> 24),
+         width, height, state->buf_size,
+         cur_frame_idx, cur_fmt_idx);
+
+    if (mcd->driver != nil) {
+        [mcd->driver startCapture: width: height];
+    } else {
+        ERR("%s: Start capture failed: vaild device", __FUNCTION__);
+        return;
+    }
+
+    // Enable the condition to capture frames now
+    qemu_mutex_lock(&state->thread_mutex);
+    state->streamon = 1;
+    qemu_cond_signal(&state->thread_cond);
+    qemu_mutex_unlock(&state->thread_mutex);
+
+    INFO("Starting preview ...\n");
+}
+
+/* MARUCAM_CMD_STOP_PREVIEW */
+void marucam_device_stop_preview(MaruCamState* state)
+{
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    INFO("Stopping preview ...\n");
+    qemu_mutex_lock(&state->thread_mutex);
+    state->streamon = 0;
+    qemu_mutex_unlock(&state->thread_mutex);
+}
+
+/* MARUCAM_CMD_S_PARAM */
+void marucam_device_s_param(MaruCamState* state)
+{
+    MaruCamParam *param = state->param;
+
+    /* We use default FPS of the webcam */
+    param->top = 0;
+}
+
+/* MARUCAM_CMD_G_PARAM */
+void marucam_device_g_param(MaruCamState* state)
+{
+    MaruCamParam *param = state->param;
+    /* We use default FPS of the webcam
+     * return a fixed value on guest ini file (1/30).
+     */
+    param->top = 0;
+    param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */
+    param->stack[1] = 1; /* numerator */
+    param->stack[2] = 30; /* denominator */
+}
+
+/* MARUCAM_CMD_S_FMT */
+void marucam_device_s_fmt(MaruCamState* state)
+{
+    MaruCamParam *param = state->param;
+    uint32_t width, height, pixfmt, pidx, fidx;
+
+    param->top = 0;
+    width = param->stack[0];
+    height = param->stack[1];
+    pixfmt = param->stack[2];
+
+    INFO("Set format: width(%d), height(%d), pixfmt(%d, %.4s)\n",
+         width, height, pixfmt, (const char*)&pixfmt);
+
+    for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) {
+        if ((supported_dst_frames[fidx].width == width) &&
+            (supported_dst_frames[fidx].height == height)) {
+            break;
+        }
+    }
+    if (fidx == ARRAY_SIZE(supported_dst_frames)) {
+        param->errCode = EINVAL;
+        return;
+    }
+
+    for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) {
+        if (supported_dst_pixfmts[pidx].fmt == pixfmt) {
+            INFO("pixfmt index is match: %d\n", pidx);
+            break;
+        }
+    }
+    if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) {
+        param->errCode = EINVAL;
+        return;
+    }
+
+    if ((supported_dst_frames[cur_frame_idx].width != width) &&
+        (supported_dst_frames[cur_frame_idx].height != height)) {
+        if (mcd->driver == nil || [mcd->driver setCaptureFormat: width: height: 0] < 0) {
+            ERR("Set pixel format failed\n");
+            return;
+        }
+
+        INFO("cur_frame_idx:%d, supported_dst_frames[cur_frame_idx].width:%d\n",
+             cur_frame_idx, supported_dst_frames[cur_frame_idx].width);
+    }
+
+    cur_frame_idx = fidx;
+    cur_fmt_idx = pidx;
+
+    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
+    width = supported_dst_frames[cur_frame_idx].width;
+    height = supported_dst_frames[cur_frame_idx].height;
+
+    param->stack[0] = width;
+    param->stack[1] = height;
+    param->stack[2] = 1; /* V4L2_FIELD_NONE */
+    param->stack[3] = pixfmt;
+    param->stack[4] = get_bytesperline(pixfmt, width);
+    param->stack[5] = get_sizeimage(pixfmt, width, height);
+    param->stack[6] = 0;
+    param->stack[7] = 0;
+
+    INFO("Set device pixel format ...\n");
+}
+
+/* MARUCAM_CMD_G_FMT */
+void marucam_device_g_fmt(MaruCamState* state)
+{
+    uint32_t width, height, pixfmt;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
+    width = supported_dst_frames[cur_frame_idx].width;
+    height = supported_dst_frames[cur_frame_idx].height;
+
+    param->stack[0] = width;
+    param->stack[1] = height;
+    param->stack[2] = 1; /* V4L2_FIELD_NONE */
+    param->stack[3] = pixfmt;
+    param->stack[4] = get_bytesperline(pixfmt, width);
+    param->stack[5] = get_sizeimage(pixfmt, width, height);
+    param->stack[6] = 0;
+    param->stack[7] = 0;
+
+    INFO("Get device frame format ...\n");
+}
+
+void marucam_device_try_fmt(MaruCamState* state)
+{
+    INFO("Try device frame format, use default setting ...\n");
+}
+
+/* Get specific pixelformat description */
+void marucam_device_enum_fmt(MaruCamState* state)
+{
+    uint32_t index;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    index = param->stack[0];
+
+    if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {
+        param->errCode = EINVAL;
+        return;
+    }
+    param->stack[1] = 0; /* flags = NONE */
+    param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */
+    switch (supported_dst_pixfmts[index].fmt) {
+        case V4L2_PIX_FMT_YUYV:
+            memcpy(&param->stack[3], "YUYV", 32);
+            break;
+        case V4L2_PIX_FMT_UYVY:
+            memcpy(&param->stack[3], "UYVY", 32);
+            break;
+        case V4L2_PIX_FMT_YUV420:
+            memcpy(&param->stack[3], "YU12", 32);
+            break;
+        case V4L2_PIX_FMT_YVU420:
+            memcpy(&param->stack[3], "YV12", 32);
+            break;
+    }
+}
+
+/*
+ * QTKit don't support setting brightness, contrast, saturation & sharpness
+ */
+void marucam_device_qctrl(MaruCamState* state)
+{
+    uint32_t id, i;
+    //long property, min, max, step, def_val, set_val;
+    char name[32] = {0,};
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    id = param->stack[0];
+
+    switch (id) {
+    case V4L2_CID_BRIGHTNESS:
+        INFO("V4L2_CID_BRIGHTNESS\n");
+        memcpy((void*)name, (void*)"brightness", 32);
+        i = 0;
+        break;
+    case V4L2_CID_CONTRAST:
+        INFO("V4L2_CID_CONTRAST\n");
+        memcpy((void*)name, (void*)"contrast", 32);
+        i = 1;
+        break;
+    case V4L2_CID_SATURATION:
+        INFO("V4L2_CID_SATURATION\n");
+        memcpy((void*)name, (void*)"saturation", 32);
+        i = 2;
+        break;
+    case V4L2_CID_SHARPNESS:
+        INFO("V4L2_CID_SHARPNESS\n");
+        memcpy((void*)name, (void*)"sharpness", 32);
+        i = 3;
+        break;
+    default:
+        param->errCode = EINVAL;
+        return;
+    }
+
+    param->stack[0] = id;
+    param->stack[1] = MARUCAM_CTRL_VALUE_MIN;  /* minimum */
+    param->stack[2] = MARUCAM_CTRL_VALUE_MAX;  /* maximum */
+    param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /*  step   */
+    param->stack[4] = MARUCAM_CTRL_VALUE_MID;  /* default_value */
+    param->stack[5] = V4L2_CTRL_FLAG_SLIDER;
+    /* name field setting */
+    memcpy(&param->stack[6], (void*)name, sizeof(name)/sizeof(name[0]));
+}
+
+void marucam_device_s_ctrl(MaruCamState* state)
+{
+    INFO("Set control\n");
+}
+
+void marucam_device_g_ctrl(MaruCamState* state)
+{
+    INFO("Get control\n");
+}
+
+/* Get frame width & height */
+void marucam_device_enum_fsizes(MaruCamState* state)
+{
+    uint32_t index, pixfmt, i;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    index = param->stack[0];
+    pixfmt = param->stack[1];
+
+    if (index >= ARRAY_SIZE(supported_dst_frames)) {
+        param->errCode = EINVAL;
+        return;
+    }
+    for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
+        if (supported_dst_pixfmts[i].fmt == pixfmt)
+            break;
+    }
+
+    if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
+        param->errCode = EINVAL;
+        return;
+    }
+
+    param->stack[0] = supported_dst_frames[index].width;
+    param->stack[1] = supported_dst_frames[index].height;
+}
+
+void marucam_device_enum_fintv(MaruCamState* state)
+{
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    /* switch by index(param->stack[0]) */
+    switch (param->stack[0]) {
+        case 0:
+            param->stack[1] = 30; /* denominator */
+            break;
+        default:
+            param->errCode = EINVAL;
+            return;
+    }
+    param->stack[0] = 1; /* numerator */
+}
diff --git a/tizen/src/ns_event.h b/tizen/src/ns_event.h
new file mode 100644 (file)
index 0000000..54655c9
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _NS_EVENT_H_
+#define _NS_EVENT_H_
+
+void ns_event_loop(int* keepRunning);
+
+#endif /* _NS_EVENT_H_ */
diff --git a/tizen/src/ns_event.m b/tizen/src/ns_event.m
new file mode 100644 (file)
index 0000000..9e71f07
--- /dev/null
@@ -0,0 +1,15 @@
+#import <Cocoa/Cocoa.h>                                         
+#import "ns_event.h"
+
+// ns event loop for receive the events from cocoa framework
+void ns_event_loop(int* keepRunning)
+{
+    NSDate* distantFuture;    
+
+    NSRunLoop* theRunLoop = [NSRunLoop currentRunLoop];
+    do {
+         distantFuture = [NSDate dateWithTimeIntervalSinceNow:0.5];
+    }
+    while (*keepRunning && [theRunLoop runMode:NSDefaultRunLoopMode beforeDate:distantFuture]);    
+    // return [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1]];
+}