Index: src/camera_v4l2.c
===================================================================
--- src/camera_v4l2.c	(revision 2107)
+++ src/camera_v4l2.c	(working copy)
@@ -81,6 +81,22 @@
     }
 }
 
+int v4l2_get_capability (int fd, int id, int *value)
+{
+    struct v4l2_queryctrl control;
+    CLEAR(control);
+
+    control.id = id;
+
+    if (-1 == v4l2_xioctl (fd, VIDIOC_QUERYCTRL, &control)) {
+        return 0;
+    }
+    
+    *value = !(control.flags & V4L2_CTRL_FLAG_DISABLED);
+
+    return 1;
+}
+
 /* gets the value of a specific camera control if available */
 int v4l2_get_control (int fd, int id, int *value)
 {
Index: src/_camera.c
===================================================================
--- src/_camera.c	(revision 2107)
+++ src/_camera.c	(working copy)
@@ -46,6 +46,7 @@
 PyObject* list_cameras (PyObject* self, PyObject* arg);
 PyObject* camera_start (PyCameraObject* self);
 PyObject* camera_stop (PyCameraObject* self);
+PyObject* camera_get_hw_capabilities (PyCameraObject* self);
 PyObject* camera_get_controls (PyCameraObject* self);
 PyObject* camera_set_controls (PyCameraObject* self, PyObject* arg, PyObject *kwds);
 PyObject* camera_get_size (PyCameraObject* self);
@@ -203,6 +204,17 @@
     Py_RETURN_NONE;
 }
 
+/* get_hw_capabilities() - gets the capabilities of the camera device */
+PyObject *camera_get_hw_capabilities (PyCameraObject *self)
+{
+    int hflip = 0;
+    int vflip = 0;
+    v4l2_get_capability(self->fd, V4L2_CID_HFLIP, &hflip);
+    v4l2_get_capability(self->fd, V4L2_CID_VFLIP, &vflip);
+
+    return Py_BuildValue("(NN)", PyBool_FromLong(hflip), PyBool_FromLong(vflip));
+}
+
 /* get_controls() - gets current values of user controls */
 /* TODO: Support brightness, contrast, and other common controls */
 PyObject* camera_get_controls (PyCameraObject* self)
@@ -210,10 +222,10 @@
     int value;
 #if defined(__unix__)    
     if (v4l2_get_control(self->fd, V4L2_CID_HFLIP, &value))
-        self->hflip = value;
+        self->hflip = value | (self->filter & CAM_SW_FILTER_HFLIP);
     
     if (v4l2_get_control(self->fd, V4L2_CID_VFLIP, &value))
-        self->vflip = value;
+        self->vflip = value | (self->filter & CAM_SW_FILTER_VFLIP);
 
     if (v4l2_get_control(self->fd, V4L2_CID_BRIGHTNESS, &value))
         self->brightness = value;
@@ -221,7 +233,7 @@
     return Py_BuildValue ("(NNN)", PyBool_FromLong(self->hflip), PyBool_FromLong(self->vflip), PyInt_FromLong(self->brightness));
 }
 
-/* set_controls() - changes camera settings if supported by the camera */
+/* set_controls() - changes camera settings if supported by the camera otherwise activate software filter */
 PyObject* camera_set_controls (PyCameraObject* self, PyObject* arg, PyObject *kwds)
 {
     int hflip = 0, vflip = 0, brightness = 0;
@@ -234,13 +246,35 @@
     
     if (!PyArg_ParseTupleAndKeywords(arg, kwds, "|iii", kwids, &hflip, &vflip, &brightness))
         return NULL;
-#if defined(__unix__)        
-    if (v4l2_set_control(self->fd, V4L2_CID_HFLIP, hflip))
-        self->hflip = hflip;
+#if defined(__unix__)
+    self->hflip = hflip;
+    if (v4l2_set_control(self->fd, V4L2_CID_HFLIP, hflip)) {
+        if (hflip)
+            self->filter &= ~CAM_SW_FILTER_HFLIP;
+        else
+            self->filter |= CAM_SW_FILTER_HFLIP;
+    }
+    else {
+        if (hflip)
+            self->filter |= CAM_SW_FILTER_HFLIP;
+        else
+            self->filter &= ~CAM_SW_FILTER_HFLIP;
+    }
+
+    self->vflip = vflip;
+    if (v4l2_set_control(self->fd, V4L2_CID_VFLIP, vflip)) {
+        if (vflip)
+            self->filter &= ~CAM_SW_FILTER_VFLIP;
+        else
+            self->filter |= CAM_SW_FILTER_VFLIP;
+    }
+    else {
+        if (vflip)
+            self->filter |= CAM_SW_FILTER_VFLIP;
+        else
+            self->filter &= ~CAM_SW_FILTER_VFLIP;
+    }
         
-    if (v4l2_set_control(self->fd, V4L2_CID_VFLIP, vflip))
-        self->vflip = vflip;
-        
     if (v4l2_set_control(self->fd, V4L2_CID_BRIGHTNESS, brightness))
         self->brightness = brightness;
 #endif    
@@ -274,7 +308,7 @@
 
     if (!surfobj) {
         surf = SDL_CreateRGBSurface (0, self->width, self->height, 24, 0xFF<<16, 
-                                 0xFF<<8, 0xFF, 0);
+                                     0xFF<<8, 0xFF, 0);
     } else {
         surf = PySurface_AsSurface (surfobj);
     }
@@ -297,9 +331,24 @@
         
     if (surfobj) {
         Py_INCREF (surfobj);
+        if (self->filter) {
+            /* TODO: right now inplace sw filter are not supported because 
+             * we use the transform module which doesn't support it. 
+             */
+            printf("no inplace sw filter\n");
+        }
         return surfobj;
     } else {
-        return PySurface_New (surf);
+        surfobj = PySurface_New (surf); 
+        if (self->filter) {
+            if ((self->filter & CAM_SW_FILTER_HFLIP) || 
+                (self->filter & CAM_SW_FILTER_VFLIP)) {
+                surfobj = surf_flip(NULL, Py_BuildValue ("(ONN)", surfobj, 
+                                                         PyBool_FromLong(self->filter & CAM_SW_FILTER_HFLIP), 
+                                                         PyBool_FromLong(self->filter & CAM_SW_FILTER_VFLIP)));
+            }  
+        }
+        return surfobj;
     }
 }
 
@@ -1298,6 +1347,7 @@
 {
     { "start", (PyCFunction) camera_start, METH_NOARGS, DOC_CAMERASTART },
     { "stop", (PyCFunction) camera_stop, METH_NOARGS, DOC_CAMERASTOP },
+    { "get_hw_capabilities", (PyCFunction) camera_get_hw_capabilities, METH_NOARGS, DOC_CAMERAGETHWCAPABILITIES },
     { "get_controls", (PyCFunction) camera_get_controls, METH_NOARGS, DOC_CAMERAGETCONTROLS },
     { "set_controls", (PyCFunction) camera_set_controls, METH_KEYWORDS, DOC_CAMERASETCONTROLS },
     { "get_size", (PyCFunction) camera_get_size, METH_NOARGS, DOC_CAMERAGETSIZE },
@@ -1381,6 +1431,7 @@
         cameraobj->vflip = 0;
         cameraobj->brightness = 0;
         cameraobj->fd = -1;
+        cameraobj->filter = 0;
     }
     
     return (PyObject*)cameraobj;
@@ -1408,6 +1459,10 @@
   if (PyErr_Occurred ()) {
     return;
   }
+  import_pygame_transform ();
+  if (PyErr_Occurred ()) {
+    return;
+  }
 
   /* type preparation */
   PyType_Init(PyCamera_Type);
Index: src/pygame.h
===================================================================
--- src/pygame.h	(revision 2107)
+++ src/pygame.h	(working copy)
@@ -669,9 +669,38 @@
     }
 #endif /* PYGAMEAPI_COLOR_INTERNAL */
 
+/* Transform */
+#define PYGAMEAPI_TRANSFORM_FIRSTSLOT                                       \
+    (PYGAMEAPI_COLOR_FIRSTSLOT + PYGAMEAPI_COLOR_NUMSLOTS)
+#define PYGAMEAPI_TRANSFORM_NUMSLOTS 1
+#ifndef PYGAMEAPI_TRANSFORM_INTERNAL
+#define surf_flip                                                \
+    (*(PyObject*(*)(PyObject*, PyObject*)) PyGAME_C_API[PYGAMEAPI_TRANSFORM_FIRSTSLOT + 0])
+#define import_pygame_transform()                                           \
+    {                                                                   \
+	PyObject *_module = PyImport_ImportModule (IMPPREFIX "transform");     \
+	if (_module != NULL)                                            \
+        {                                                               \
+            PyObject *_dict = PyModule_GetDict (_module);               \
+            PyObject *_c_api = PyDict_GetItemString                     \
+                (_dict, PYGAMEAPI_LOCAL_ENTRY);                         \
+            if (PyCObject_Check (_c_api))                               \
+            {                                                           \
+                int i;                                                  \
+                void** localptr = (void**) PyCObject_AsVoidPtr (_c_api); \
+                for (i = 0; i < PYGAMEAPI_TRANSFORM_NUMSLOTS; ++i)          \
+                    PyGAME_C_API[i + PYGAMEAPI_TRANSFORM_FIRSTSLOT] =       \
+                        localptr[i];                                    \
+            }                                                           \
+            Py_DECREF (_module);                                        \
+        }                                                               \
+    }
+#endif /* PYGAMEAPI_TRANSFORM_INTERNAL */
+
+
 #ifndef NO_PYGAME_C_API
 #define PYGAMEAPI_TOTALSLOTS                                            \
-    (PYGAMEAPI_COLOR_FIRSTSLOT + PYGAMEAPI_COLOR_NUMSLOTS)
+    (PYGAMEAPI_TRANSFORM_FIRSTSLOT + PYGAMEAPI_TRANSFORM_NUMSLOTS)
 static void* PyGAME_C_API[PYGAMEAPI_TOTALSLOTS] = { NULL };
 #endif
 
Index: src/pygamedocs.h
===================================================================
--- src/pygamedocs.h	(revision 2107)
+++ src/pygamedocs.h	(working copy)
@@ -35,6 +35,8 @@
 
 #define DOC_CAMERASTOP "Camera.stop(): return None\nstops, uninitializes, and closes the camera"
 
+#define DOC_CAMERAGETHWCAPABILITIES "Camera.get_hw_capabilities(): return (hflip, vflip)\ngets the hardware capabilities of this camera"
+
 #define DOC_CAMERAGETCONTROLS "Camera.get_controls(): return (hflip = bool, vflip = bool)\ngets current values of user controls"
 
 #define DOC_CAMERASETCONTROLS "Camera.set_controls(hflip = bool, vflip = bool): return (hflip = bool, vflip = bool)\nchanges camera settings if supported by the camera"
Index: src/transform.c
===================================================================
--- src/transform.c	(revision 2107)
+++ src/transform.c	(working copy)
@@ -24,6 +24,8 @@
 /*
  *  surface transformations for pygame
  */
+#define PYGAMEAPI_TRANSFORM_INTERNAL
+
 #include "pygame.h"
 #include "pgcompat.h"
 #include "pygamedocs.h"
@@ -705,6 +707,7 @@
     if (!PyArg_ParseTuple (arg, "O!ii", &PySurface_Type, &surfobj,
                            &xaxis, &yaxis))
         return NULL;
+
     surf = PySurface_AsSurface (surfobj);
 
     newsurf = newsurf_fromsurf (surf, surf->w, surf->h);
@@ -2702,6 +2705,9 @@
 MODINIT_DEFINE (transform)
 {
     PyObject *module;
+    PyObject *dict;
+    PyObject *apiobj; 
+    static void* c_api[PYGAMEAPI_TRANSFORM_NUMSLOTS];
     struct _module_state *st;
 
 #if PY3
@@ -2747,6 +2753,17 @@
     if (module == 0) {
         MODINIT_ERROR;
     }
+    
+    dict = PyModule_GetDict (module);
+    c_api[0] = surf_flip;
+    apiobj = PyCObject_FromVoidPtr (c_api, NULL);
+    if (apiobj == NULL) {
+        MODINIT_ERROR;
+    }
+    if (PyDict_SetItemString (dict, PYGAMEAPI_LOCAL_ENTRY, apiobj)) {
+        MODINIT_ERROR;
+    }
+    Py_DECREF(apiobj);
 
     st = GETSTATE (module);
     if (st->filter_type == 0) {
@@ -2754,3 +2771,4 @@
     }
     MODINIT_RETURN (module);
 }
+
Index: src/camera.h
===================================================================
--- src/camera.h	(revision 2107)
+++ src/camera.h	(working copy)
@@ -53,7 +53,10 @@
 #define HSV_OUT 4
 #define CAM_V4L 1
 #define CAM_V4L2 2
+#define CAM_SW_FILTER_HFLIP 1
+#define CAM_SW_FILTER_VFLIP 2
 
+
 struct buffer 
 {
     void * start;
@@ -76,6 +79,7 @@
     int vflip;
     int brightness;
     int fd;
+    int filter;
 } PyCameraObject;
 
 /* internal functions for colorspace conversion */
