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