diff --git a/setup.py b/setup.py
index bdec06b6f9de2d0b91879096189b9645871640cd..168cb908514c6b54449484cc06d469d3450e6cd2 100644
--- a/setup.py
+++ b/setup.py
@@ -61,6 +61,7 @@ setup(
       Extension("xbob.io._library",
         [
           "xbob/io/bobskin.cpp",
+          "xbob/io/codec.cpp",
           "xbob/io/file.cpp",
           "xbob/io/videoreader.cpp",
           "xbob/io/videowriter.cpp",
diff --git a/xbob/io/bobskin.h b/xbob/io/bobskin.h
index c60e754f4ab72755401545d835b7cba7e9647676..5527bb618e5a77ff14f603c0682dad3bd439276d 100644
--- a/xbob/io/bobskin.h
+++ b/xbob/io/bobskin.h
@@ -6,6 +6,9 @@
  * functionality.
  */
 
+#ifndef PYTHON_BOB_IO_BOBSKIN_H
+#define PYTHON_BOB_IO_BOBSKIN_H
+
 #include <Python.h>
 
 #include <bob/core/array.h>
@@ -86,3 +89,5 @@ class bobskin: public bob::core::array::interface {
     void* m_ptr; ///< pointer to the data
 
 };
+
+#endif /* PYTHON_BOB_IO_BOBSKIN_H */
diff --git a/xbob/io/codec.cpp b/xbob/io/codec.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8c2db07c722b330b1553c51874fbe7d71c6cced0
--- /dev/null
+++ b/xbob/io/codec.cpp
@@ -0,0 +1,48 @@
+/**
+ * @author Andre Anjos <andre.anjos@idiap.ch>
+ * @date Wed 14 May 11:53:36 2014 CEST
+ *
+ * @brief Bindings to bob::io::CodecRegistry
+ */
+
+#define XBOB_IO_MODULE
+#include <xbob.io/api.h>
+
+int PyBobIoCodec_Register (const char* extension, const char* description, bob::io::file_factory_t factory) {
+  boost::shared_ptr<bob::io::CodecRegistry> instance =
+    bob::io::CodecRegistry::instance();
+
+  if (instance->isRegistered(extension)) {
+    PyErr_Format(PyExc_RuntimeError, "codec for extension `%s' is already registered with description `%s' - in order to register a new codec for such an extension, first unregister the existing codec", extension, PyBobIoCodec_GetDescription(extension));
+    return 0;
+  }
+
+  instance->registerExtension(extension, description, factory);
+  return 1;
+}
+
+int PyBobIoCodec_Deregister (const char* extension) {
+  boost::shared_ptr<bob::io::CodecRegistry> instance =
+    bob::io::CodecRegistry::instance();
+
+  if (!instance->isRegistered(extension)) {
+    PyErr_Format(PyExc_RuntimeError, "there is no codec registered for extension `%s'", extension);
+    return 0;
+  }
+
+  instance->deregisterExtension(extension);
+  return 1;
+}
+
+int PyBobIoCodec_IsRegistered (const char* extension) {
+  boost::shared_ptr<bob::io::CodecRegistry> instance =
+    bob::io::CodecRegistry::instance();
+  if (instance->isRegistered(extension)) return 1;
+  return 0;
+}
+
+const char* PyBobIoCodec_GetDescription (const char* extension) {
+  boost::shared_ptr<bob::io::CodecRegistry> instance =
+    bob::io::CodecRegistry::instance();
+  return instance->getDescription(extension);
+}
diff --git a/xbob/io/file.cpp b/xbob/io/file.cpp
index e143e456ff753cbec7b4a40efe934bdc8a1c735e..56359e5a67d5ab4376e9c90194dbbd2efc6aa14c 100644
--- a/xbob/io/file.cpp
+++ b/xbob/io/file.cpp
@@ -146,15 +146,15 @@ static PyObject* PyBobIoFile_Repr(PyBobIoFileObject* self) {
   PyString_FromFormat
 # endif
   ("%s(filename='%s', codec='%s')", Py_TYPE(self)->tp_name,
-   self->f->filename().c_str(), self->f->name().c_str());
+   self->f->filename(), self->f->name());
 }
 
 static PyObject* PyBobIoFile_Filename(PyBobIoFileObject* self) {
-  return Py_BuildValue("s", self->f->filename().c_str());
+  return Py_BuildValue("s", self->f->filename());
 }
 
 static PyObject* PyBobIoFile_CodecName(PyBobIoFileObject* self) {
-  return Py_BuildValue("s", self->f->name().c_str());
+  return Py_BuildValue("s", self->f->name());
 }
 
 PyDoc_STRVAR(s_filename_str, "filename");
@@ -242,7 +242,7 @@ static PyObject* PyBobIoFile_GetIndex (PyBobIoFileObject* self, Py_ssize_t i) {
   if (i < 0) i += self->f->size(); ///< adjust for negative indexing
 
   if (i < 0 || (size_t)i >= self->f->size()) {
-    PyErr_Format(PyExc_IndexError, "file index out of range - `%s' only contains %" PY_FORMAT_SIZE_T "d object(s)", self->f->filename().c_str(), self->f->size());
+    PyErr_Format(PyExc_IndexError, "file index out of range - `%s' only contains %" PY_FORMAT_SIZE_T "d object(s)", self->f->filename(), self->f->size());
     return 0;
   }
 
@@ -267,7 +267,7 @@ static PyObject* PyBobIoFile_GetIndex (PyBobIoFileObject* self, Py_ssize_t i) {
     return 0;
   }
   catch (...) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading object #%" PY_FORMAT_SIZE_T "d from file `%s'", i, self->f->filename().c_str());
+    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading object #%" PY_FORMAT_SIZE_T "d from file `%s'", i, self->f->filename());
     return 0;
   }
 
@@ -323,7 +323,7 @@ static PyObject* PyBobIoFile_GetSlice (PyBobIoFileObject* self, PySliceObject* s
       return 0;
     }
     catch (...) {
-      if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading object #%" PY_FORMAT_SIZE_T "d from file `%s'", i, self->f->filename().c_str());
+      if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading object #%" PY_FORMAT_SIZE_T "d from file `%s'", i, self->f->filename());
       return 0;
     }
 
@@ -372,7 +372,7 @@ static PyObject* PyBobIoFile_Read(PyBobIoFileObject* self, PyObject *args, PyObj
     if (i < 0) i += self->f->size();
 
     if (i < 0 || (size_t)i >= self->f->size()) {
-      PyErr_Format(PyExc_IndexError, "file index out of range - `%s' only contains %" PY_FORMAT_SIZE_T "d object(s)", self->f->filename().c_str(), self->f->size());
+      PyErr_Format(PyExc_IndexError, "file index out of range - `%s' only contains %" PY_FORMAT_SIZE_T "d object(s)", self->f->filename(), self->f->size());
       return 0;
     }
 
@@ -399,7 +399,7 @@ static PyObject* PyBobIoFile_Read(PyBobIoFileObject* self, PyObject *args, PyObj
     self->f->read_all(skin);
   }
   catch (std::runtime_error& e) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught std::runtime_error while reading all contents of file `%s': %s", self->f->filename().c_str(), e.what());
+    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught std::runtime_error while reading all contents of file `%s': %s", self->f->filename(), e.what());
     return 0;
   }
   catch (std::exception& e) {
@@ -407,7 +407,7 @@ static PyObject* PyBobIoFile_Read(PyBobIoFileObject* self, PyObject *args, PyObj
     return 0;
   }
   catch (...) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown while reading all contents of file `%s'", self->f->filename().c_str());
+    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown while reading all contents of file `%s'", self->f->filename());
     return 0;
   }
 
@@ -451,7 +451,7 @@ static PyObject* PyBobIoFile_Write(PyBobIoFileObject* self, PyObject *args, PyOb
     self->f->write(skin);
   }
   catch (std::runtime_error& e) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught std::runtime_error while writing to file `%s': %s", self->f->filename().c_str(), e.what());
+    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught std::runtime_error while writing to file `%s': %s", self->f->filename(), e.what());
     return 0;
   }
   catch (std::exception& e) {
@@ -459,7 +459,7 @@ static PyObject* PyBobIoFile_Write(PyBobIoFileObject* self, PyObject *args, PyOb
     return 0;
   }
   catch (...) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown while writing to file `%s'", self->f->filename().c_str());
+    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown while writing to file `%s'", self->f->filename());
     return 0;
   }
 
@@ -504,7 +504,7 @@ static PyObject* PyBobIoFile_Append(PyBobIoFileObject* self, PyObject *args, PyO
     pos = self->f->append(skin);
   }
   catch (std::runtime_error& e) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught std::runtime_error while appending to file `%s': %s", self->f->filename().c_str(), e.what());
+    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught std::runtime_error while appending to file `%s': %s", self->f->filename(), e.what());
     return 0;
   }
   catch (std::exception& e) {
@@ -512,7 +512,7 @@ static PyObject* PyBobIoFile_Append(PyBobIoFileObject* self, PyObject *args, PyO
     return 0;
   }
   catch (...) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown while appending to file `%s'", self->f->filename().c_str());
+    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown while appending to file `%s'", self->f->filename());
     return 0;
   }
 
diff --git a/xbob/io/include/xbob.io/api.h b/xbob/io/include/xbob.io/api.h
index 0fe1983ea4de197929a3fad6c42bc9378908680a..8ba2fbfef96eb5a7c59bd896a2c1891d49d7c2dc 100644
--- a/xbob/io/include/xbob.io/api.h
+++ b/xbob/io/include/xbob.io/api.h
@@ -19,6 +19,7 @@
 #include <bob/config.h>
 #include <bob/io/File.h>
 #include <bob/io/HDF5File.h>
+#include <bob/io/CodecRegistry.h>
 
 #if WITH_FFMPEG
 #include <bob/io/VideoReader.h>
@@ -45,6 +46,11 @@ enum _PyBobIo_ENUM{
   PyBobIoHDF5File_Type_NUM,
   PyBobIoHDF5File_Check_NUM,
   PyBobIoHDF5File_Converter_NUM,
+  // Codec registration and de-registration
+  PyBobIoCodec_Register_NUM,
+  PyBobIoCodec_Deregister_NUM,
+  PyBobIoCodec_IsRegistered_NUM,
+  PyBobIoCodec_GetDescription_NUM,
 #if WITH_FFMPEG
   PyBobIoVideoReader_Type_NUM,
   PyBobIoVideoReaderIterator_Type_NUM,
@@ -119,6 +125,22 @@ typedef struct {
 #define PyBobIoHDF5File_Converter_RET int
 #define PyBobIoHDF5File_Converter_PROTO (PyObject* o, PyBobIoHDF5FileObject** a)
 
+/*****************************************
+ * Code Registration and De-registration *
+ *****************************************/
+
+#define PyBobIoCodec_Register_RET int
+#define PyBobIoCodec_Register_PROTO (const char* extension, const char* description, bob::io::file_factory_t factory)
+
+#define PyBobIoCodec_Deregister_RET int
+#define PyBobIoCodec_Deregister_PROTO (const char* extension)
+
+#define PyBobIoCodec_IsRegistered_RET int
+#define PyBobIoCodec_IsRegistered_PROTO (const char* extension)
+
+#define PyBobIoCodec_GetDescription_RET const char*
+#define PyBobIoCodec_GetDescription_PROTO (const char* extension)
+
 #if WITH_FFMPEG
 
 /******************
@@ -196,6 +218,18 @@ typedef struct {
 
   PyBobIoHDF5File_Converter_RET PyBobIoHDF5File_Converter PyBobIoHDF5File_Converter_PROTO;
 
+/*****************************************
+ * Code Registration and De-registration *
+ *****************************************/
+
+ PyBobIoCodec_Register_RET PyBobIoCodec_Register PyBobIoCodec_Register_PROTO;
+
+ PyBobIoCodec_Deregister_RET PyBobIoCodec_Deregister PyBobIoCodec_Deregister_PROTO;
+
+ PyBobIoCodec_IsRegistered_RET PyBobIoCodec_IsRegistered PyBobIoCodec_IsRegistered_PROTO;
+
+ PyBobIoCodec_GetDescription_RET PyBobIoCodec_GetDescription PyBobIoCodec_GetDescription_PROTO;
+
 #if WITH_FFMPEG
   /******************
    * Video bindings *
@@ -255,6 +289,18 @@ typedef struct {
 
 # define PyBobIoHDF5File_Converter (*(PyBobIoHDF5File_Converter_RET (*)PyBobIoHDF5File_Converter_PROTO) PyXbobIo_API[PyBobIoHDF5File_Converter_NUM])
 
+/*****************************************
+ * Code Registration and De-registration *
+ *****************************************/
+
+# define PyBobIoCodec_Register (*(PyBobIoCodec_Register_RET (*)PyBobIoCodec_Register_PROTO) PyXbobIo_API[PyBobIoCodec_Register_NUM])
+
+# define PyBobIoCodec_Deregister (*(PyBobIoCodec_Deregister_RET (*)PyBobIoCodec_Deregister_PROTO) PyXbobIo_API[PyBobIoCodec_Deregister_NUM])
+
+# define PyBobIoCodec_IsRegistered (*(PyBobIoCodec_IsRegistered_RET (*)PyBobIoCodec_IsRegistered_PROTO) PyXbobIo_API[PyBobIoCodec_IsRegistered_NUM])
+
+# define PyBobIoCodec_GetDescription (*(PyBobIoCodec_GetDescription_RET (*)PyBobIoCodec_GetDescription_PROTO) PyXbobIo_API[PyBobIoCodec_GetDescription_NUM])
+
 #if WITH_FFMPEG
   /******************
    * Video bindings *
diff --git a/xbob/io/main.cpp b/xbob/io/main.cpp
index 36a54b137b8a5acf4b61e825d757858f13faff23..2374c2895b0cb5b736c19942a6f6c33495449f6c 100644
--- a/xbob/io/main.cpp
+++ b/xbob/io/main.cpp
@@ -28,7 +28,7 @@ static PyModuleDef module_definition = {
   XBOB_EXT_MODULE_NAME,
   module_docstr,
   -1,
-  module_methods, 
+  module_methods,
   0, 0, 0, 0
 };
 #endif
@@ -109,7 +109,7 @@ static PyObject* create_module (void) {
   /************************
    * I/O generic bindings *
    ************************/
-  
+
   PyXbobIo_API[PyBobIo_AsTypenum_NUM] = (void *)PyBobIo_AsTypenum;
 
   PyXbobIo_API[PyBobIo_TypeInfoAsTuple_NUM] = (void *)PyBobIo_TypeInfoAsTuple;
@@ -121,11 +121,23 @@ static PyObject* create_module (void) {
    *****************/
 
   PyXbobIo_API[PyBobIoHDF5File_Type_NUM] = (void *)&PyBobIoHDF5File_Type;
-  
+
   PyXbobIo_API[PyBobIoHDF5File_Check_NUM] = (void *)&PyBobIoHDF5File_Check;
 
   PyXbobIo_API[PyBobIoHDF5File_Converter_NUM] = (void *)&PyBobIoHDF5File_Converter;
 
+/*****************************************
+ * Code Registration and De-registration *
+ *****************************************/
+
+  PyXbobIo_API[PyBobIoCodec_Register_NUM] = (void *)&PyBobIoCodec_Register;
+
+  PyXbobIo_API[PyBobIoCodec_Deregister_NUM] = (void *)&PyBobIoCodec_Deregister;
+
+  PyXbobIo_API[PyBobIoCodec_IsRegistered_NUM] = (void *)&PyBobIoCodec_IsRegistered;
+
+  PyXbobIo_API[PyBobIoCodec_GetDescription_NUM] = (void *)&PyBobIoCodec_GetDescription;
+
 #if WITH_FFMPEG
   /******************
    * Video bindings *
diff --git a/xbob/io/version.cpp b/xbob/io/version.cpp
index 59a2e860af58f182d7c7b3f8815df6060503157a..9fcd9524fe4014c8446716b70cf614f51667ab89 100644
--- a/xbob/io/version.cpp
+++ b/xbob/io/version.cpp
@@ -838,7 +838,7 @@ static PyObject* PyBobIo_Extensions(PyObject*) {
 
 PyDoc_STRVAR(s_extensions_str, "extensions");
 PyDoc_STRVAR(s_extensions_doc,
-"as_blitz(x) -> dict\n\
+"extensions() -> dict\n\
 \n\
 Returns a dictionary containing all extensions and descriptions\n\
 currently stored on the global codec registry\n\