Mauro Carvalho Chehab 6bdec7f
diff -r 60f92d860a1f zbar/convert.c
Mauro Carvalho Chehab 6bdec7f
--- a/zbar/convert.c	Sat Dec 25 08:29:33 2010 -0200
Mauro Carvalho Chehab 6bdec7f
+++ b/zbar/convert.c	Sat Dec 25 14:36:04 2010 -0200
Mauro Carvalho Chehab 6bdec7f
@@ -1157,6 +1157,42 @@
Mauro Carvalho Chehab 6bdec7f
                 break;
Mauro Carvalho Chehab 6bdec7f
         }
Mauro Carvalho Chehab 6bdec7f
     }
Mauro Carvalho Chehab 6bdec7f
+    if(!min_fmt && vdo->emu_formats) {
Mauro Carvalho Chehab 6bdec7f
+        /* As vdo->formats aren't compatible, just free them */
Mauro Carvalho Chehab 6bdec7f
+        free(vdo->formats);
Mauro Carvalho Chehab 6bdec7f
+        vdo->formats = vdo->emu_formats;
Mauro Carvalho Chehab 6bdec7f
+        vdo->emu_formats = NULL;
Mauro Carvalho Chehab 6bdec7f
+
Mauro Carvalho Chehab 6bdec7f
+        /*
Mauro Carvalho Chehab 6bdec7f
+        * Use the same cost algorithm to select emulated formats.
Mauro Carvalho Chehab 6bdec7f
+        * This might select a sub-optimal conversion, but, in practice,
Mauro Carvalho Chehab 6bdec7f
+        * it will select a conversion to YUV at libv4l, and a YUY->Y8
Mauro Carvalho Chehab 6bdec7f
+        * in zbar, with it is OK. Yet, it is better to not select the
Mauro Carvalho Chehab 6bdec7f
+        * most performatic conversion than to not support the webcam.
Mauro Carvalho Chehab 6bdec7f
+        */
Mauro Carvalho Chehab 6bdec7f
+        for(fmt = _zbar_formats; *fmt; fmt++) {
Mauro Carvalho Chehab 6bdec7f
+            /* only consider formats supported by video device */
Mauro Carvalho Chehab 6bdec7f
+            uint32_t win_fmt = 0;
Mauro Carvalho Chehab 6bdec7f
+            int cost;
Mauro Carvalho Chehab 6bdec7f
+            if(!has_format(*fmt, srcs))
Mauro Carvalho Chehab 6bdec7f
+                continue;
Mauro Carvalho Chehab 6bdec7f
+            cost = _zbar_best_format(*fmt, &win_fmt, dsts);
Mauro Carvalho Chehab 6bdec7f
+            if(cost < 0) {
Mauro Carvalho Chehab 6bdec7f
+                zprintf(4, "%.4s(%08" PRIx32 ") -> ? (unsupported)\n",
Mauro Carvalho Chehab 6bdec7f
+                        (char*)fmt, *fmt);
Mauro Carvalho Chehab 6bdec7f
+                continue;
Mauro Carvalho Chehab 6bdec7f
+            }
Mauro Carvalho Chehab 6bdec7f
+            zprintf(4, "%.4s(%08" PRIx32 ") -> %.4s(%08" PRIx32 ") (%d)\n",
Mauro Carvalho Chehab 6bdec7f
+                    (char*)fmt, *fmt, (char*)&win_fmt, win_fmt, cost);
Mauro Carvalho Chehab 6bdec7f
+            if(min_cost > cost) {
Mauro Carvalho Chehab 6bdec7f
+                min_cost = cost;
Mauro Carvalho Chehab 6bdec7f
+                min_fmt = *fmt;
Mauro Carvalho Chehab 6bdec7f
+                if(!cost)
Mauro Carvalho Chehab 6bdec7f
+                    break;
Mauro Carvalho Chehab 6bdec7f
+            }
Mauro Carvalho Chehab 6bdec7f
+        }
Mauro Carvalho Chehab 6bdec7f
+    }
Mauro Carvalho Chehab 6bdec7f
+
Mauro Carvalho Chehab 6bdec7f
     if(win)
Mauro Carvalho Chehab 6bdec7f
         (void)window_unlock(win);
Mauro Carvalho Chehab 6bdec7f
 
Mauro Carvalho Chehab 6bdec7f
diff -r 60f92d860a1f zbar/video.c
Mauro Carvalho Chehab 6bdec7f
--- a/zbar/video.c	Sat Dec 25 08:29:33 2010 -0200
Mauro Carvalho Chehab 6bdec7f
+++ b/zbar/video.c	Sat Dec 25 14:36:04 2010 -0200
Mauro Carvalho Chehab 6bdec7f
@@ -111,6 +111,9 @@
Mauro Carvalho Chehab 6bdec7f
         free(vdo->buf);
Mauro Carvalho Chehab 6bdec7f
     if(vdo->formats)
Mauro Carvalho Chehab 6bdec7f
         free(vdo->formats);
Mauro Carvalho Chehab 6bdec7f
+    if(vdo->emu_formats)
Mauro Carvalho Chehab 6bdec7f
+        free(vdo->emu_formats);
Mauro Carvalho Chehab 6bdec7f
+
Mauro Carvalho Chehab 6bdec7f
     err_cleanup(&vdo->err);
Mauro Carvalho Chehab 6bdec7f
     _zbar_mutex_destroy(&vdo->qlock);
Mauro Carvalho Chehab 6bdec7f
 
Mauro Carvalho Chehab 6bdec7f
diff -r 60f92d860a1f zbar/video.h
Mauro Carvalho Chehab 6bdec7f
--- a/zbar/video.h	Sat Dec 25 08:29:33 2010 -0200
Mauro Carvalho Chehab 6bdec7f
+++ b/zbar/video.h	Sat Dec 25 14:36:04 2010 -0200
Mauro Carvalho Chehab 6bdec7f
@@ -69,6 +69,7 @@
Mauro Carvalho Chehab 6bdec7f
     uint32_t format;            /* selected fourcc */
Mauro Carvalho Chehab 6bdec7f
     unsigned palette;           /* v4l1 format index corresponding to format */
Mauro Carvalho Chehab 6bdec7f
     uint32_t *formats;          /* 0 terminated list of supported formats */
Mauro Carvalho Chehab 6bdec7f
+    uint32_t *emu_formats;      /* 0 terminated list of emulated formats */
Mauro Carvalho Chehab 6bdec7f
 
Mauro Carvalho Chehab 6bdec7f
     unsigned long datalen;      /* size of image data for selected format */
Mauro Carvalho Chehab 6bdec7f
     unsigned long buflen;       /* total size of image data buffer */
Mauro Carvalho Chehab 6bdec7f
diff -r 60f92d860a1f zbar/video/v4l2.c
Mauro Carvalho Chehab 6bdec7f
--- a/zbar/video/v4l2.c	Sat Dec 25 08:29:33 2010 -0200
Mauro Carvalho Chehab 6bdec7f
+++ b/zbar/video/v4l2.c	Sat Dec 25 14:36:04 2010 -0200
Mauro Carvalho Chehab 6bdec7f
@@ -347,6 +347,8 @@
Mauro Carvalho Chehab 6bdec7f
 
Mauro Carvalho Chehab 6bdec7f
 static inline int v4l2_probe_formats (zbar_video_t *vdo)
Mauro Carvalho Chehab 6bdec7f
 {
Mauro Carvalho Chehab 6bdec7f
+    int n_formats = 0, n_emu_formats = 0;
Mauro Carvalho Chehab 6bdec7f
+
Mauro Carvalho Chehab 6bdec7f
     zprintf(2, "enumerating supported formats:\n");
Mauro Carvalho Chehab 6bdec7f
     struct v4l2_fmtdesc desc;
Mauro Carvalho Chehab 6bdec7f
     memset(&desc, 0, sizeof(desc));
Mauro Carvalho Chehab 6bdec7f
@@ -354,17 +356,39 @@
Mauro Carvalho Chehab 6bdec7f
     for(desc.index = 0; desc.index < V4L2_FORMATS_MAX; desc.index++) {
Mauro Carvalho Chehab 6bdec7f
         if(v4l2_ioctl(vdo->fd, VIDIOC_ENUM_FMT, &desc) < 0)
Mauro Carvalho Chehab 6bdec7f
             break;
Mauro Carvalho Chehab 6bdec7f
-        zprintf(2, "    [%d] %.4s : %s%s\n",
Mauro Carvalho Chehab 6bdec7f
+        zprintf(2, "    [%d] %.4s : %s%s%s\n",
Mauro Carvalho Chehab 6bdec7f
                 desc.index, (char*)&desc.pixelformat, desc.description,
Mauro Carvalho Chehab 6bdec7f
-                (desc.flags & V4L2_FMT_FLAG_COMPRESSED) ? " COMPRESSED" : "");
Mauro Carvalho Chehab 6bdec7f
-        vdo->formats = realloc(vdo->formats,
Mauro Carvalho Chehab 6bdec7f
-                               (desc.index + 2) * sizeof(uint32_t));
Mauro Carvalho Chehab 6bdec7f
-        vdo->formats[desc.index] = desc.pixelformat;
Mauro Carvalho Chehab 6bdec7f
+                (desc.flags & V4L2_FMT_FLAG_COMPRESSED) ? " COMPRESSED" : "",
Mauro Carvalho Chehab 6bdec7f
+                (desc.flags & V4L2_FMT_FLAG_EMULATED) ? " EMULATED" : "");
Mauro Carvalho Chehab 6bdec7f
+        if (desc.flags & V4L2_FMT_FLAG_EMULATED) {
Mauro Carvalho Chehab 6bdec7f
+            vdo->emu_formats = realloc(vdo->emu_formats,
Mauro Carvalho Chehab 6bdec7f
+                                   (n_emu_formats + 2) * sizeof(uint32_t));
Mauro Carvalho Chehab 6bdec7f
+            vdo->emu_formats[n_emu_formats++] = desc.pixelformat;
Mauro Carvalho Chehab 6bdec7f
+        } else {
Mauro Carvalho Chehab 6bdec7f
+            vdo->formats = realloc(vdo->formats,
Mauro Carvalho Chehab 6bdec7f
+                                   (n_formats + 2) * sizeof(uint32_t));
Mauro Carvalho Chehab 6bdec7f
+            vdo->formats[n_formats++] = desc.pixelformat;
Mauro Carvalho Chehab 6bdec7f
+        }
Mauro Carvalho Chehab 6bdec7f
     }
Mauro Carvalho Chehab 6bdec7f
     if(!desc.index)
Mauro Carvalho Chehab 6bdec7f
         return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__,
Mauro Carvalho Chehab 6bdec7f
                            "enumerating video formats (VIDIOC_ENUM_FMT)"));
Mauro Carvalho Chehab 6bdec7f
-    vdo->formats[desc.index] = 0;
Mauro Carvalho Chehab 6bdec7f
+    if(vdo->formats)
Mauro Carvalho Chehab 6bdec7f
+       vdo->formats[n_formats] = 0;
Mauro Carvalho Chehab 6bdec7f
+    if(vdo->emu_formats)
Mauro Carvalho Chehab 6bdec7f
+       vdo->emu_formats[n_emu_formats] = 0;
Mauro Carvalho Chehab 6bdec7f
+    if(!vdo->formats && vdo->emu_formats) {
Mauro Carvalho Chehab 6bdec7f
+       /*
Mauro Carvalho Chehab 6bdec7f
+        * If only emu formats are available, just move them to vdo->formats.
Mauro Carvalho Chehab 6bdec7f
+        * This happens when libv4l detects that the only available fourcc
Mauro Carvalho Chehab 6bdec7f
+        * formats are webcam proprietary formats or bayer formats.
Mauro Carvalho Chehab 6bdec7f
+        */
Mauro Carvalho Chehab 6bdec7f
+       vdo->formats = vdo->emu_formats;
Mauro Carvalho Chehab 6bdec7f
+       vdo->emu_formats = NULL;
Mauro Carvalho Chehab 6bdec7f
+    }
Mauro Carvalho Chehab 6bdec7f
+
Mauro Carvalho Chehab 6bdec7f
+    zprintf(2, "Found %d formats and %d emulated formats.\n",
Mauro Carvalho Chehab 6bdec7f
+            n_formats, n_emu_formats);
Mauro Carvalho Chehab 6bdec7f
 
Mauro Carvalho Chehab 6bdec7f
     struct v4l2_format fmt;
Mauro Carvalho Chehab 6bdec7f
     struct v4l2_pix_format *pix = &fmt.fmt.pix;