diff --git a/setup.py b/setup.py
index ff76ba9621da17adb041922d5be3f30f1b33f6d1..9daf8a8622298318dbfb6a1819519fff63407406 100644
--- a/setup.py
+++ b/setup.py
@@ -15,15 +15,6 @@ include_dirs = [package_dir]
 packages = ['bob-io >= 2.0.0a2']
 version = '2.0.0a0'
 
-# Check if python-imaging means pil or pillow
-pil_or_pillow = []
-try:
-  import pkg_resources
-  pkg_resources.require('PIL')
-  pil_or_pillow.append('pil')
-except pkg_resources.DistributionNotFound as e:
-  pil_or_pillow.append('pillow')
-
 setup(
 
     name='xbob.io.base',
@@ -42,7 +33,7 @@ setup(
     install_requires=[
       'setuptools',
       'xbob.blitz',
-    ] + pil_or_pillow,
+    ],
 
     namespace_packages=[
       "xbob",
@@ -57,31 +48,21 @@ setup(
         packages = packages,
         include_dirs = include_dirs,
         version = version,
-        define_macros = [('__STDC_CONSTANT_MACROS', None)],
         ),
       Extension("xbob.io.base._library",
         [
           "xbob/io/base/bobskin.cpp",
           "xbob/io/base/codec.cpp",
           "xbob/io/base/file.cpp",
-          "xbob/io/base/videoreader.cpp",
-          "xbob/io/base/videowriter.cpp",
           "xbob/io/base/hdf5.cpp",
           "xbob/io/base/main.cpp",
           ],
         packages = packages,
         include_dirs = include_dirs,
         version = version,
-        define_macros = [('__STDC_CONSTANT_MACROS', None)],
         ),
       ],
 
-    entry_points={
-      'console_scripts': [
-        'xbob_video_test.py = xbob.io.script.video_test:main',
-        ],
-      },
-
     classifiers = [
       'Development Status :: 3 - Alpha',
       'Intended Audience :: Developers',
diff --git a/xbob/io/base/__init__.py b/xbob/io/base/__init__.py
index 62541ea13993e7a737d5a101894c5df065b2c3c3..436943a423aeada364f7558392b7dda0ad95219e 100644
--- a/xbob/io/base/__init__.py
+++ b/xbob/io/base/__init__.py
@@ -1,10 +1,22 @@
-from ._library import File, VideoReader, VideoWriter, HDF5File
+from ._library import File, HDF5File
 from . import version
 from .version import module as __version__
 from .version import api as __api_version__
 
 import os
 
+def __is_string__(s):
+  """Returns ``True`` if the given object is a string
+
+  This method can be used with Python-2.x or 3.x and returns a string
+  respecting each environment's constraints.
+  """
+
+  from sys import version_info
+
+  return (version_info[0] < 3 and isinstance(s, (str, unicode))) or \
+    isinstance(s, (bytes, str))
+
 def create_directories_save(directory, dryrun=False):
   """Creates a directory if it does not exists, with concurrent access support.
   This function will also create any parent directories that might be required.
@@ -59,13 +71,12 @@ def load(inputs):
 
   from collections import Iterable
   import numpy
-  from .utils import is_string
-  if is_string(inputs):
+  if __is_string__(inputs):
     return File(inputs, 'r').read()
   elif isinstance(inputs, Iterable):
     retval = []
     for obj in inputs:
-      if is_string(obj):
+      if __is_string__(obj):
         retval.append(load(obj))
       elif isinstance(obj, File):
         retval.append(obj.read())
diff --git a/xbob/io/base/data/img_indexed_color.png b/xbob/io/base/data/img_indexed_color.png
deleted file mode 100644
index c21427b328350a26155841013e461fa46e406be5..0000000000000000000000000000000000000000
Binary files a/xbob/io/base/data/img_indexed_color.png and /dev/null differ
diff --git a/xbob/io/base/data/test.jpg b/xbob/io/base/data/test.jpg
deleted file mode 100644
index 0bf2deb6a8f29793c1ae15a880aef370c43d01fc..0000000000000000000000000000000000000000
Binary files a/xbob/io/base/data/test.jpg and /dev/null differ
diff --git a/xbob/io/base/data/test.mov b/xbob/io/base/data/test.mov
deleted file mode 100644
index 29288925be1751b12c8c4fb10079a6b49e64fa7e..0000000000000000000000000000000000000000
Binary files a/xbob/io/base/data/test.mov and /dev/null differ
diff --git a/xbob/io/base/data/test.pbm b/xbob/io/base/data/test.pbm
deleted file mode 100644
index 0902b226f358f3b4703342c59f93200c3263d880..0000000000000000000000000000000000000000
--- a/xbob/io/base/data/test.pbm
+++ /dev/null
@@ -1,3 +0,0 @@
-P4
-4 6
-€@  @
\ No newline at end of file
diff --git a/xbob/io/base/data/test.pgm b/xbob/io/base/data/test.pgm
deleted file mode 100644
index 32cd7fae38dc8850cb7ce244908ba749eb364327..0000000000000000000000000000000000000000
Binary files a/xbob/io/base/data/test.pgm and /dev/null differ
diff --git a/xbob/io/base/data/test.ppm b/xbob/io/base/data/test.ppm
deleted file mode 100644
index a5baf843114a68f76cdc36e96658bfbcd782b3eb..0000000000000000000000000000000000000000
Binary files a/xbob/io/base/data/test.ppm and /dev/null differ
diff --git a/xbob/io/base/data/test_h264.mov b/xbob/io/base/data/test_h264.mov
deleted file mode 100644
index a7de9a3ca48dad544104d14ec162811c1a81c23e..0000000000000000000000000000000000000000
Binary files a/xbob/io/base/data/test_h264.mov and /dev/null differ
diff --git a/xbob/io/base/fonts/bold.ttf b/xbob/io/base/fonts/bold.ttf
deleted file mode 100644
index 8f5a1d3f1edd49cf7a630887f2f61dfe6ebd9fc2..0000000000000000000000000000000000000000
Binary files a/xbob/io/base/fonts/bold.ttf and /dev/null differ
diff --git a/xbob/io/base/fonts/bold_italic.ttf b/xbob/io/base/fonts/bold_italic.ttf
deleted file mode 100644
index 916e9b351d985581d728574bb8f4766e64f7ffde..0000000000000000000000000000000000000000
Binary files a/xbob/io/base/fonts/bold_italic.ttf and /dev/null differ
diff --git a/xbob/io/base/fonts/font_license.txt b/xbob/io/base/fonts/font_license.txt
deleted file mode 100644
index 69399804ca6c71fd61ed0ae47535baad3bb55e79..0000000000000000000000000000000000000000
--- a/xbob/io/base/fonts/font_license.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
-Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
-
-Bitstream Vera Fonts Copyright
-------------------------------
-
-Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
-a trademark of Bitstream, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of the fonts accompanying this license ("Fonts") and associated
-documentation files (the "Font Software"), to reproduce and distribute the
-Font Software, including without limitation the rights to use, copy, merge,
-publish, distribute, and/or sell copies of the Font Software, and to permit
-persons to whom the Font Software is furnished to do so, subject to the
-following conditions:
-
-The above copyright and trademark notices and this permission notice shall
-be included in all copies of one or more of the Font Software typefaces.
-
-The Font Software may be modified, altered, or added to, and in particular
-the designs of glyphs or characters in the Fonts may be modified and
-additional glyphs or characters may be added to the Fonts, only if the fonts
-are renamed to names not containing either the words "Bitstream" or the word
-"Vera".
-
-This License becomes null and void to the extent applicable to Fonts or Font
-Software that has been modified and is distributed under the "Bitstream
-Vera" names.
-
-The Font Software may be sold as part of a larger software package but no
-copy of one or more of the Font Software typefaces may be sold by itself.
-
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
-TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
-FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
-ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
-FONT SOFTWARE.
-
-Except as contained in this notice, the names of Gnome, the Gnome
-Foundation, and Bitstream Inc., shall not be used in advertising or
-otherwise to promote the sale, use or other dealings in this Font Software
-without prior written authorization from the Gnome Foundation or Bitstream
-Inc., respectively. For further information, contact: fonts at gnome dot
-org. 
-
-Arev Fonts Copyright
-------------------------------
-
-Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the fonts accompanying this license ("Fonts") and
-associated documentation files (the "Font Software"), to reproduce
-and distribute the modifications to the Bitstream Vera Font Software,
-including without limitation the rights to use, copy, merge, publish,
-distribute, and/or sell copies of the Font Software, and to permit
-persons to whom the Font Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright and trademark notices and this permission notice
-shall be included in all copies of one or more of the Font Software
-typefaces.
-
-The Font Software may be modified, altered, or added to, and in
-particular the designs of glyphs or characters in the Fonts may be
-modified and additional glyphs or characters may be added to the
-Fonts, only if the fonts are renamed to names not containing either
-the words "Tavmjong Bah" or the word "Arev".
-
-This License becomes null and void to the extent applicable to Fonts
-or Font Software that has been modified and is distributed under the 
-"Tavmjong Bah Arev" names.
-
-The Font Software may be sold as part of a larger software package but
-no copy of one or more of the Font Software typefaces may be sold by
-itself.
-
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
-TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
-
-Except as contained in this notice, the name of Tavmjong Bah shall not
-be used in advertising or otherwise to promote the sale, use or other
-dealings in this Font Software without prior written authorization
-from Tavmjong Bah. For further information, contact: tavmjong @ free
-. fr.
\ No newline at end of file
diff --git a/xbob/io/base/fonts/italic.ttf b/xbob/io/base/fonts/italic.ttf
deleted file mode 100644
index 7b8b787525dd555b0c0144d0a8db84f9f317e268..0000000000000000000000000000000000000000
Binary files a/xbob/io/base/fonts/italic.ttf and /dev/null differ
diff --git a/xbob/io/base/fonts/regular.ttf b/xbob/io/base/fonts/regular.ttf
deleted file mode 100644
index ea0bfd8c276fd20bc0f121bf28c9facbda430905..0000000000000000000000000000000000000000
Binary files a/xbob/io/base/fonts/regular.ttf and /dev/null differ
diff --git a/xbob/io/base/main.cpp b/xbob/io/base/main.cpp
index b00c088718efdab595ba2eff916019af8fb6cae2..6d3b5c1ae17cdab66a0f4ceea6a8c0a50038f6be 100644
--- a/xbob/io/base/main.cpp
+++ b/xbob/io/base/main.cpp
@@ -18,7 +18,7 @@ static PyMethodDef module_methods[] = {
     {0}  /* Sentinel */
 };
 
-PyDoc_STRVAR(module_docstr, "bob::io classes and methods");
+PyDoc_STRVAR(module_docstr, "Core bob::io classes and methods");
 
 int PyXbobIo_APIVersion = XBOB_IO_BASE_API_VERSION;
 
@@ -44,17 +44,6 @@ static PyObject* create_module (void) {
   PyBobIoHDF5File_Type.tp_new = PyType_GenericNew;
   if (PyType_Ready(&PyBobIoHDF5File_Type) < 0) return 0;
 
-#if WITH_FFMPEG
-  PyBobIoVideoReader_Type.tp_new = PyType_GenericNew;
-  if (PyType_Ready(&PyBobIoVideoReader_Type) < 0) return 0;
-
-  PyBobIoVideoReaderIterator_Type.tp_new = PyType_GenericNew;
-  if (PyType_Ready(&PyBobIoVideoReaderIterator_Type) < 0) return 0;
-
-  PyBobIoVideoWriter_Type.tp_new = PyType_GenericNew;
-  if (PyType_Ready(&PyBobIoVideoWriter_Type) < 0) return 0;
-#endif /* WITH_FFMPEG */
-
 # if PY_VERSION_HEX >= 0x03000000
   PyObject* m = PyModule_Create(&module_definition);
 # else
@@ -77,17 +66,6 @@ static PyObject* create_module (void) {
   Py_INCREF(&PyBobIoHDF5File_Type);
   if (PyModule_AddObject(m, "HDF5File", (PyObject *)&PyBobIoHDF5File_Type) < 0) return 0;
 
-#if WITH_FFMPEG
-  Py_INCREF(&PyBobIoVideoReader_Type);
-  if (PyModule_AddObject(m, "VideoReader", (PyObject *)&PyBobIoVideoReader_Type) < 0) return 0;
-
-  Py_INCREF(&PyBobIoVideoReaderIterator_Type);
-  if (PyModule_AddObject(m, "VideoReader.iter", (PyObject *)&PyBobIoVideoReaderIterator_Type) < 0) return 0;
-
-  Py_INCREF(&PyBobIoVideoWriter_Type);
-  if (PyModule_AddObject(m, "VideoWriter", (PyObject *)&PyBobIoVideoWriter_Type) < 0) return 0;
-#endif /* WITH_FFMPEG */
-
   static void* PyXbobIo_API[PyXbobIo_API_pointers];
 
   /* exhaustive list of C APIs */
@@ -138,18 +116,6 @@ static PyObject* create_module (void) {
 
   PyXbobIo_API[PyBobIoCodec_GetDescription_NUM] = (void *)&PyBobIoCodec_GetDescription;
 
-#if WITH_FFMPEG
-  /******************
-   * Video bindings *
-   ******************/
-
-  PyXbobIo_API[PyBobIoVideoReader_Type_NUM] = (void *)&PyBobIoVideoReader_Type;
-
-  PyXbobIo_API[PyBobIoVideoReaderIterator_Type_NUM] = (void *)&PyBobIoVideoReaderIterator_Type;
-
-  PyXbobIo_API[PyBobIoVideoWriter_Type_NUM] = (void *)&PyBobIoVideoWriter_Type;
-#endif /* WITH_FFMPEG */
-
 #if PY_VERSION_HEX >= 0x02070000
 
   /* defines the PyCapsule */
diff --git a/xbob/io/base/script/__init__.py b/xbob/io/base/script/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/xbob/io/base/script/video_test.py b/xbob/io/base/script/video_test.py
deleted file mode 100644
index 130d29f0d24e7497cb08a6499c8142a59147d452..0000000000000000000000000000000000000000
--- a/xbob/io/base/script/video_test.py
+++ /dev/null
@@ -1,520 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-# Andre Anjos <andre.dos.anjos@gmail.com>
-# Thu 14 Mar 17:53:16 2013
-
-"""This program can run manual tests using any video codec available in Bob. It
-can report standard distortion figures and build video test sequences for
-manual inspection. It tries to help identifying problems with:
-
-  1. Color distortion
-  2. Frame skipping or delay
-  3. Encoding or decoding quality
-  4. User test (with a user provided video sample)
-
-You can parameterize the program with the type of file, (FFmpeg) codec and a
-few other parameters. The program then generates artificial input signals to
-test for each of the parameters above.
-"""
-
-import os
-import sys
-import argparse
-import numpy
-
-# internal
-from .. import utils, create_directories_save
-from .. import save as save_to_file
-from .. import test_utils
-
-def list_codecs(*args, **kwargs):
-
-  from ..version import supported_video_codecs, available_video_codecs
-  CODECS = supported_video_codecs()
-  ALL_CODECS = available_video_codecs()
-
-  retval = """\
-  Supported Codecs:
-  -----------------\n"""
-
-  for k in sorted(CODECS.keys()):
-    retval += ("  %-20s  %s\n" % (k, CODECS[k]['long_name']))[:80]
-
-  return retval[:-1]
-
-def list_all_codecs(*args, **kwargs):
-
-  from ..version import supported_video_codecs, available_video_codecs
-
-  CODECS = supported_video_codecs()
-  ALL_CODECS = available_video_codecs()
-
-  retval = """\
-  Available Codecs:
-  -----------------\n"""
-
-  for k in sorted(ALL_CODECS.keys()):
-    retval += ("  %-20s  %s\n" % (k, ALL_CODECS[k]['long_name']))[:80]
-
-  return retval[:-1]
-
-def list_formats(*args, **kwargs):
-
-  from ..version import supported_videowriter_formats, available_videowriter_formats
-  FORMATS = supported_videowriter_formats()
-  ALL_FORMATS = available_videowriter_formats()
-
-  retval = """\
-  Supported Formats:
-  ------------------\n"""
-
-  for k in sorted(FORMATS.keys()):
-    retval += ("  %-20s  %s\n" % (k, FORMATS[k]['long_name']))[:80]
-
-  return retval[:-1]
-
-def list_all_formats(*args, **kwargs):
-
-  from ..version import supported_videowriter_formats, available_videowriter_formats
-  FORMATS = supported_videowriter_formats()
-  ALL_FORMATS = available_videowriter_formats()
-
-  retval = """\
-  Available Formats:
-  ------------------\n"""
-
-  for k in sorted(ALL_FORMATS.keys()):
-    retval += ("  %-20s  %s\n" % (k, ALL_FORMATS[k]['long_name']))[:80]
-
-  return retval[:-1]
-
-__epilog__ = """Example usage:
-
-1. Check for color distortion using H.264 codec in a .mov video container:
-
-  $ %(prog)s --format='mov' --codec='h264' color
-
-2. Check for frame skipping using MJPEG codec in an .avi video container:
-
-  $ %(prog)s --format='avi' --codec='mjpeg' frameskip
-
-3. Check for encoding/decoding quality using a FFV1 codec in a '.flv' video
-container (not supported - note the usage of the '--force' flag):
-
-  $ %(prog)s --force --format='flv' --codec='ffv1' noise
-
-4. To run-only the user-video test and provide a test video:
-
-  $ %(prog)s --format='mov' --user-video=test_sample.avi user
-
-5. To list all available codecs:
-
-  $ %(prog)s --list-codecs
-
-6. To list all available formats:
-
-  $ %(prog)s --list-formats
-
-7. Run all tests for all **supported** codecs and formats:
-
-  $ %(prog)s
-""" % {
-    'prog': os.path.basename(sys.argv[0]),
-    }
-
-def user_video(original, max_frames, format, codec, filename):
-  """Returns distortion patterns for a set of frames with moving colors.
-
-  Keyword parameters:
-
-  original
-    The name (path) to the original user file that will be used for the test
-
-  max_frames
-    The maximum number of frames to read from user input
-
-  format
-    The string that identifies the format to be used for the output file
-
-  codec
-    The codec to be used for the output file
-
-  filename
-    The name (path) of the file to use for encoding the test
-  """
-
-  from .. import VideoReader, VideoWriter
-  vreader = VideoReader(original, check=True)
-  orig = vreader[:max_frames]
-
-  # rounding frame rate - some older codecs do not accept random frame rates
-  framerate = vreader.frame_rate
-  if codec in ('mpegvideo', 'mpeg1video', 'mpeg2video'):
-    import math
-    framerate = math.ceil(vreader.frame_rate)
-
-  vwriter = VideoWriter(filename, vreader.height, vreader.width,
-      framerate, codec=codec, format=format, check=False)
-  for k in orig: vwriter.append(k)
-  del vwriter
-  return orig, framerate, VideoReader(filename, check=False)
-
-def summarize(function, shape, framerate, format, codec, output=None):
-  """Summarizes distortion patterns for a given set of video settings and
-  for a given input function.
-
-  Keyword parameters:
-
-  function
-    The function that will be evaluated, summarized
-
-  shape (int, int, int)
-    The length (number of frames), height and width for the generated sequence
-
-  format
-    The string that identifies the format to be used for the output file
-
-  codec
-    The codec to be used for the output file
-
-  output
-    If set, the video is not created on the temporary directory, but it is
-    saved on the advised location. This must be a filename.
-
-  Returns a single a single string summarizing the distortion results
-  """
-
-  length, height, width = shape
-
-  if output:
-    fname = output
-  else:
-    fname = test_utils.temporary_filename(suffix='.%s' % format)
-
-  retval = "did not run"
-
-  try:
-    # Width and height should be powers of 2 as the encoded image is going
-    # to be approximated to the closest one, would not not be the case.
-    # In this case, the encoding is subject to more noise as the filtered,
-    # final image that is encoded will contain added noise on the extra
-    # borders.
-    orig, framerate, encoded = function(shape, framerate, format, codec, fname)
-
-    tmp = []
-    for k, of in enumerate(orig):
-      tmp.append(abs(of.astype('float64')-encoded[k].astype('float64')).sum())
-    size = numpy.prod(orig[0].shape)
-    S = sum(tmp)/size
-    M = S/len(tmp)
-    Min = min(tmp)/size
-    Max = max(tmp)/size
-    ArgMin = tmp.index(min(tmp))
-    ArgMax = tmp.index(max(tmp))
-    retval = "%.3f min=%.3f@%d max=%.3f@%d" % (M, Min, ArgMin, Max, ArgMax)
-    if abs(encoded.frame_rate - framerate) > 0.01:
-      retval += " !FR(%g)" % abs(encoded.frame_rate - framerate)
-    if len(encoded) != len(orig):
-      retval += " !LEN(%d)" % len(encoded)
-
-  finally:
-
-    if os.path.exists(fname) and output is None: os.unlink(fname)
-
-  if output:
-    return retval, orig, encoded
-  else:
-    return retval
-
-def detail(function, shape, framerate, format, codec, outdir):
-  """Summarizes distortion patterns for a given set of video settings and
-  for a given input function.
-
-  Keyword parameters:
-
-  shape (int, int, int)
-    The length (number of frames), height and width for the generated sequence
-
-  format
-    The string that identifies the format to be used for the output file
-
-  codec
-    The codec to be used for the output file
-
-  outdir
-    We will save all analysis for this sequence on the given output directory.
-
-  Returns a single a single string summarizing the distortion results.
-  """
-
-  length, height, width = shape
-
-  text_format = "%%0%dd" % len(str(length-1))
-
-  output = os.path.join(outdir, "video." + format)
-  retval, orig, encoded = summarize(function, shape, framerate,
-      format, codec, output)
-
-  length, _, height, width = orig.shape
-
-  # save original, reloaded and difference images on output directories
-  for i, orig_frame in enumerate(orig):
-    out = numpy.ndarray((3, height, 3*width), dtype='uint8')
-    out[:,:,:width] = orig_frame
-    out[:,:,width:(2*width)] = encoded[i]
-    diff = abs(encoded[i].astype('int64')-orig_frame.astype('int64'))
-    diff[diff>0] = 255 #binary output
-    out[:,:,(2*width):] = diff.astype('uint8')
-    save_to_file(out, os.path.join(outdir, 'frame-' + (text_format%i) + '.png'))
-
-  return retval
-
-def main(user_input=None):
-
-  from .._library import __version__
-  from ..version import supported_video_codecs, available_video_codecs, supported_videowriter_formats, available_videowriter_formats
-  from .. import test as io_test
-
-  parser = argparse.ArgumentParser(description=__doc__, epilog=__epilog__,
-      formatter_class=argparse.RawDescriptionHelpFormatter)
-
-  name = os.path.basename(os.path.splitext(sys.argv[0])[0])
-  version_info = 'Video Encoding/Decoding Test Tool v%s (%s)' % (__version__, name)
-  parser.add_argument('-V', '--version', action='version', version=version_info)
-
-  test_choices = [
-      'color',
-      'frameskip',
-      'noise',
-      'user',
-      ]
-
-  parser.add_argument("test", metavar='TEST', type=str, nargs='*',
-      default=test_choices, help="The name of the test or tests you want to run. Choose between `%s'. If none given, run through all." % ('|'.join(test_choices)))
-
-  CODECS = supported_video_codecs()
-  ALL_CODECS = available_video_codecs()
-
-  supported_codecs = sorted(CODECS.keys())
-  available_codecs = sorted(ALL_CODECS.keys())
-
-  parser.add_argument("-c", "--codec", metavar='CODEC', type=str, nargs='*',
-      default=supported_codecs, choices=available_codecs, help="The name of the codec you want to test with. For a list of available codecs, look below. If none given, run through all.")
-  parser.add_argument("--list-codecs", action="store_true", default=False,
-      help="List all supported codecs and exits")
-  parser.add_argument("--list-all-codecs", action="store_true", default=False,
-      help="List all available codecs and exits")
-
-  FORMATS = supported_videowriter_formats()
-  ALL_FORMATS = available_videowriter_formats()
-
-  supported_formats = sorted(FORMATS.keys())
-  available_formats = sorted(ALL_FORMATS.keys())
-  parser.add_argument("-f", "--format", metavar='FORMAT', type=str, nargs='*',
-      default=supported_formats, choices=available_formats, help="The name of the format you want to test with. For a list of available formats, look below. If none given, run through all.")
-  parser.add_argument("--list-formats", action="store_true", default=False,
-      help="List all supported formats and exits")
-  parser.add_argument("--list-all-formats", action="store_true", default=False,
-      help="List all available formats and exits")
-
-  parser.add_argument("-F", "--force", action="store_true", default=False,
-      help="Force command execution (possibly generating an error) even if the format or the combination of format+codec is not supported. This flag is needed in case you need to test new formats or combinations of formats and codecs which are unsupported by the build")
-
-  parser.add_argument("-t", "--height", metavar="INT", type=int,
-      default=128, help="Height of the test video (defaults to %(default)s pixels). Note this number has to be even.")
-
-  parser.add_argument("-w", "--width", metavar="INT", type=int,
-      default=128, help="Width of the test video (defaults to %(default)s pixels). Note this number has to be even.")
-
-  parser.add_argument("-l", "--length", metavar="INT", type=int,
-      default=30, help="Length of the test sequence (defaults to %(default)s frames). The longer, the more accurate the test becomes.")
-
-  parser.add_argument("-r", "--framerate", metavar="FLOAT", type=float,
-      default=30., help="Framerate to be used on the test videos (defaults to %(default)s Hz).")
-
-  parser.add_argument("-o", "--output", type=str,
-      help="If set, then videos created for the tests are stored on the given directory. By default this option is empty and videos are created on a temporary directory and deleted after tests are done. If you set it, we also produced detailed output analysis for manual inspection.")
-
-  parser.add_argument("-u", "--user-video", type=str, metavar="PATH",
-      help="Set the path to the user video that will be used for distortion tests (if not set use default test video)")
-
-  parser.add_argument("-n", "--user-frames", type=int, default=10, metavar="INT", help="Set the number of maximum frames to read from the user video (reads %(default)s by default)")
-
-  args = parser.parse_args(args=user_input)
-
-  # manual check because of argparse limitation
-  for t in args.test:
-    if t not in test_choices:
-      parser.error("invalid test choice: '%s' (choose from %s)" % \
-          (t, ", ".join(["'%s'" % k for k in test_choices])))
-
-  if not args.test: args.test = test_choices
-
-  if args.list_codecs:
-    print(list_codecs())
-    sys.exit(0)
-
-  if args.list_all_codecs:
-    print(list_all_codecs())
-    sys.exit(0)
-
-  if args.list_formats:
-    print(list_formats())
-    sys.exit(0)
-
-  if args.list_all_formats:
-    print(list_all_formats())
-    sys.exit(0)
-
-  if 'user' in args.test and args.user_video is None:
-    # in this case, take our standard video test
-    args.user_video = test_utils.datafile('test.mov', io_test.__name__)
-
-  def wrap_user_function(shape, framerate, format, codec, filename):
-    return user_video(args.user_video, args.user_frames, format, codec, filename)
-
-  # mapping between test name and function
-  test_function = {
-      'color': (utils.color_distortion, 'C'),
-      'frameskip': (utils.frameskip_detection, 'S'),
-      'noise': (utils.quality_degradation, 'N'),
-      'user': (wrap_user_function, 'U'),
-      }
-
-  # result table
-  table = {}
-
-  # report results in a readable way
-  print(version_info)
-  print("Settings:")
-  print("  Width    : %d pixels" % args.width)
-  print("  Height   : %d pixels" % args.height)
-  print("  Length   : %d frames" % args.length)
-  print("  Framerate: %f Hz"     % args.framerate)
-
-  print("Legend:")
-  for k, (f, code) in test_function.items():
-    print("  %s: %s test" % (code, k.capitalize()))
-
-  sys.stdout.write("Running %d test(s)..." %
-      (len(args.test)*len(args.format)*len(args.codec)))
-  sys.stdout.flush()
-
-  # run tests
-  need_notes = False
-  for test in args.test:
-    test_table = table.setdefault(test, {})
-    f, code = test_function[test]
-
-    for format in args.format:
-      format_table = test_table.setdefault(format, {})
-
-      for codec in args.codec:
-
-        # cautionary settings
-        notes = ""
-        if format not in FORMATS:
-          if args.force:
-            notes += "[!F] "
-            need_notes = True
-
-          else:
-            sys.stdout.write(code)
-            sys.stdout.flush()
-            format_table[codec] = "unsupported format"
-            continue
-
-        else:
-          if codec not in FORMATS[format]['supported_codecs']:
-            if args.force:
-              notes += "[!F+C] "
-              need_notes = True
-
-            else:
-              sys.stdout.write(code)
-              sys.stdout.flush()
-              format_table[codec] = "format+codec unsupported"
-              continue
-
-        if args.output:
-
-          size = '%dx%dx%d@%gHz' % (args.length, args.height, args.width,
-              args.framerate)
-          outdir = os.path.join(args.output, test, codec, size, format)
-          create_directories_save(outdir)
-
-          try:
-            result = detail(f, (args.length, args.height, args.width),
-                args.framerate, format, codec, outdir)
-            sys.stdout.write(code)
-            sys.stdout.flush()
-          except Exception as e:
-            result = str(e)
-            sys.stdout.write(code)
-            sys.stdout.flush()
-          finally:
-            format_table[codec] = notes + result
-
-        else:
-
-          try:
-            result = summarize(f, (args.length, args.height, args.width),
-                args.framerate, format, codec)
-            sys.stdout.write(code)
-            sys.stdout.flush()
-          except Exception as e:
-            result = str(e)
-            sys.stdout.write(code)
-            sys.stdout.flush()
-          finally:
-            format_table[codec] = notes + result
-
-  sys.stdout.write("\n")
-  sys.stdout.flush()
-
-  # builds a nicely organized dynamically sized table
-  test_size   = max([len(k) for k in args.test] + [len('test')])
-  fmt_size    = max([len(k) for k in args.format] + [len('fmt')])
-  codec_size  = max([len(k) for k in args.codec] + [len('codec')])
-  figure_size = 79 - (test_size + 3 + fmt_size + 3 + codec_size + 3 + 2)
-  if figure_size <= 0: figure_size = 40
-
-  test_cover   = (test_size + 2) * '='
-  fmt_cover    = (fmt_size + 2) * '='
-  codec_cover  = (codec_size + 2) * '='
-  figure_cover = (figure_size + 2) * '='
-
-  sep  = test_cover + ' ' + fmt_cover + ' ' + codec_cover + ' ' + figure_cover
-  line = " %s   %s   %s   %s"
-
-  print("")
-  print(sep)
-  print(line % (
-      'test'.ljust(test_size),
-      'fmt'.center(fmt_size),
-      'codec'.center(codec_size),
-      'figure (lower means better quality)'.ljust(figure_size),
-      ))
-  print(sep)
-
-  for test in sorted(table.keys()):
-    test_table = table[test]
-    for format in sorted(test_table.keys()):
-      format_table = test_table[format]
-      for codec in sorted(format_table.keys()):
-        figure = format_table[codec]
-        print(line % (
-            test.ljust(test_size),
-            format.center(fmt_size),
-            codec.ljust(codec_size),
-            figure.ljust(figure_size),
-            ))
-
-  print(sep)
-
-  # only printed if unsupported combinations of formats and codecs are used
-  if need_notes:
-    print("")
-    print("Notes:")
-    print("  [!F] Format is available, but not supported by this build")
-    print("  [!F+C] Format is supported, but not in combination with this codec")
diff --git a/xbob/io/base/test_file.py b/xbob/io/base/test_file.py
index 431e32430f4ce94c4706bd991cc8feb8bb6b7747..372fab6aef2e2af8a84bff291e48ad0975956a06 100644
--- a/xbob/io/base/test_file.py
+++ b/xbob/io/base/test_file.py
@@ -291,35 +291,6 @@ def test_tensorfile():
   # complete transcoding test
   transcode(test_utils.datafile('torch.tensor', __name__))
 
-@test_utils.extension_available('.pgm')
-@test_utils.extension_available('.pbm')
-@test_utils.extension_available('.ppm')
-def test_netpbm():
-
-  def image_transcode(filename):
-
-    tmpname = test_utils.temporary_filename(suffix=os.path.splitext(filename)[1])
-
-    try:
-      # complete transcoding test
-      image = load(filename)
-
-      # save with the same extension
-      write(image, tmpname)
-
-      # reload the image from the file
-      image2 = load(tmpname)
-
-      assert numpy.array_equal(image, image2)
-
-    finally:
-      if os.path.exists(tmpname): os.unlink(tmpname)
-
-  image_transcode(test_utils.datafile('test.pgm', __name__)) #indexed, works fine
-  image_transcode(test_utils.datafile('test.pbm', __name__)) #indexed, works fine
-  image_transcode(test_utils.datafile('test.ppm', __name__)) #indexed, works fine
-  #image_transcode(test_utils.datafile('test.jpg', __name__)) #does not work because of re-compression
-
 @test_utils.extension_available('.csv')
 def test_csv():
 
diff --git a/xbob/io/base/test_image.py b/xbob/io/base/test_image.py
deleted file mode 100644
index 84f6e981ec96de28f7f997d1c027be830bf3cdfd..0000000000000000000000000000000000000000
--- a/xbob/io/base/test_image.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-# Laurent El Shafey <laurent.el-shafey@idiap.ch>
-# Wed Aug 14 12:27:57 CEST 2013
-#
-# Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland
-
-"""Runs some image tests
-"""
-
-from . import load, test_utils
-
-# These are some global parameters for the test.
-PNG_INDEXED_COLOR = test_utils.datafile('img_indexed_color.png', __name__)
-
-def test_png_indexed_color():
-
-  # Read an indexed color PNG image, and compared with hardcoded values
-  img = load(PNG_INDEXED_COLOR)
-  assert img.shape == (3,22,32)
-  assert img[0,0,0] == 255
-  assert img[0,17,17] == 117
diff --git a/xbob/io/base/test_utils.py b/xbob/io/base/test_utils.py
index 103b9e7700e541999bd29a4895cc192cfa3a8f46..2ba6d1908acf6653be2439453d9c16041a2eb7cd 100644
--- a/xbob/io/base/test_utils.py
+++ b/xbob/io/base/test_utils.py
@@ -49,74 +49,6 @@ def temporary_filename(prefix='bobtest_', suffix='.hdf5'):
   os.unlink(name)
   return name
 
-# Here is a table of ffmpeg versions against libavcodec, libavformat and
-# libavutil versions
-ffmpeg_versions = {
-    '0.5':  [ SV('52.20.0'),   SV('52.31.0'),   SV('49.15.0')   ],
-    '0.6':  [ SV('52.72.2'),   SV('52.64.2'),   SV('50.15.1')   ],
-    '0.7':  [ SV('52.122.0'),  SV('52.110.0'),  SV('50.43.0')   ],
-    '0.8':  [ SV('53.7.0'),    SV('53.4.0'),    SV('51.9.1')    ],
-    '0.9':  [ SV('53.42.0'),   SV('53.24.0'),   SV('51.32.0')   ],
-    '0.10': [ SV('53.60.100'), SV('53.31.100'), SV('51.34.101') ],
-    '0.11': [ SV('54.23.100'), SV('54.6.100'),  SV('51.54.100') ],
-    '1.0':  [ SV('54.59.100'), SV('54.29.104'), SV('51.73.101') ],
-    '1.1':  [ SV('54.86.100'), SV('54.59.106'), SV('52.13.100') ],
-    '1.2':  [ SV('54.92.100'), SV('54.63.104'), SV('52.18.100') ],
-    '2.0':  [ SV('55.18.102'), SV('55.12.100'), SV('52.38.100') ],
-    '2.1':  [ SV('55.39.100'), SV('55.19.104'), SV('52.48.100') ],
-    }
-
-def ffmpeg_version_lessthan(v):
-  '''Returns true if the version of ffmpeg compiled-in is at least the version
-  indicated as a string parameter.'''
-
-  from .version import externals
-  if externals['FFmpeg']['ffmpeg'] == 'unavailable': return False
-  avcodec_inst= SV(externals['FFmpeg']['avcodec'])
-  avcodec_req = ffmpeg_versions[v][0]
-  return avcodec_inst < avcodec_req
-
-def ffmpeg_found(version_geq=None):
-  '''Decorator to check if a codec is available before enabling a test
-
-  To use this, decorate your test routine with something like:
-
-  .. code-block:: python
-
-    @ffmpeg_found()
-
-  You can pass an optional string to require that the FFMpeg version installed
-  is greater or equal that version identifier. For example:
-
-  .. code-block:: python
-
-    @ffmpeg_found('0.10') #requires at least version 0.10
-
-  Versions you can test for are set in the ``ffmpeg_versions`` dictionary in
-  this module.
-  '''
-
-  def test_wrapper(test):
-
-    @functools.wraps(test)
-    def wrapper(*args, **kwargs):
-      try:
-        from .version import externals
-        avcodec_inst = SV(externals['FFmpeg']['avcodec'])
-        avformat_inst = SV(externals['FFmpeg']['avformat'])
-        avutil_inst = SV(externals['FFmpeg']['avutil'])
-        if version_geq is not None:
-          avcodec_req,avformat_req,avutil_req = ffmpeg_versions[version_geq]
-          if avcodec_inst < avcodec_req:
-            raise nose.plugins.skip.SkipTest('FFMpeg/libav version installed (%s) is smaller than required for this test (%s)' % (externals['FFmpeg']['ffmpeg'], version_geq))
-        return test(*args, **kwargs)
-      except KeyError:
-        raise nose.plugins.skip.SkipTest('FFMpeg was not available at compile time')
-
-    return wrapper
-
-  return test_wrapper
-
 def bob_at_least(version_geq):
   '''Decorator to check if at least a certain version of Bob is installed
 
@@ -142,24 +74,6 @@ def bob_at_least(version_geq):
 
   return test_wrapper
 
-def codec_available(codec):
-  '''Decorator to check if a codec is available before enabling a test'''
-
-  def test_wrapper(test):
-
-    @functools.wraps(test)
-    def wrapper(*args, **kwargs):
-      from .version import supported_video_codecs
-      d = supported_video_codecs()
-      if codec in d and d[codec]['encode'] and d[codec]['decode']:
-        return test(*args, **kwargs)
-      else:
-        raise nose.plugins.skip.SkipTest('A functional codec for "%s" is not installed with FFmpeg' % codec)
-
-    return wrapper
-
-  return test_wrapper
-
 def extension_available(extension):
   '''Decorator to check if a extension is available before enabling a test'''
 
diff --git a/xbob/io/base/test_video.py b/xbob/io/base/test_video.py
deleted file mode 100644
index cec068cd8ea735718f393f333e23db52c490e96b..0000000000000000000000000000000000000000
--- a/xbob/io/base/test_video.py
+++ /dev/null
@@ -1,324 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-# Andre Anjos <andre.anjos@idiap.ch>
-# Wed Jun 22 17:50:08 2011 +0200
-#
-# Copyright (C) 2011-2013 Idiap Research Institute, Martigny, Switzerland
-
-"""Runs some video tests
-"""
-
-import os
-import numpy
-import nose.tools
-from . import test_utils
-
-# These are some global parameters for the test.
-INPUT_VIDEO = test_utils.datafile('test.mov', __name__)
-
-def test_codec_support():
-
-  # Describes all encoders
-  from .version import describe_encoder, describe_decoder, supported_video_codecs
-
-  supported = supported_video_codecs()
-
-  for k,v in supported.items():
-    # note: searching by name (using `k') will not always work
-    if v['decode']: assert describe_decoder(v['id'])
-    if v['encode']: assert describe_encoder(v['id'])
-
-  # Assert we support, at least, some known codecs
-  for codec in ('ffv1', 'wmv2', 'mpeg4', 'mjpeg'):
-    assert codec in supported
-    assert supported[codec]['encode']
-    assert supported[codec]['decode']
-
-@test_utils.ffmpeg_found()
-def test_input_format_support():
-
-  # Describes all encoders
-  from .version import supported_videoreader_formats
-
-  supported = supported_videoreader_formats()
-
-  # Assert we support, at least, some known codecs
-  for fmt in ('avi', 'mov', 'mp4'):
-    assert fmt in supported
-
-@test_utils.ffmpeg_found()
-def test_output_format_support():
-
-  # Describes all encoders
-  from .version import supported_videowriter_formats
-
-  supported = supported_videowriter_formats()
-
-  # Assert we support, at least, some known codecs
-  for fmt in ('avi', 'mov', 'mp4'):
-    assert fmt in supported
-
-@test_utils.ffmpeg_found()
-def test_video_reader_attributes():
-
-  from . import VideoReader
-
-  iv = VideoReader(INPUT_VIDEO)
-
-  assert isinstance(iv.filename, str)
-  assert isinstance(iv.height, int)
-  assert isinstance(iv.width, int)
-  assert iv.height != iv.width
-  assert isinstance(iv.duration, int)
-  assert isinstance(iv.format_name, str)
-  assert isinstance(iv.format_long_name, str)
-  assert isinstance(iv.codec_name, str)
-  assert isinstance(iv.codec_long_name, str)
-  assert isinstance(iv.frame_rate, float)
-  assert isinstance(iv.video_type, tuple)
-  assert len(iv.video_type) == 3
-  assert isinstance(iv.video_type[0], numpy.dtype)
-  assert isinstance(iv.video_type[1], tuple)
-  assert isinstance(iv.video_type[2], tuple)
-  assert isinstance(iv.frame_type, tuple)
-  assert len(iv.frame_type) == 3
-  assert iv.frame_type[0] == iv.video_type[0]
-  assert isinstance(iv.video_type[1], tuple)
-  nose.tools.eq_(len(iv.video_type[1]), len(iv.frame_type[1])+1)
-  nose.tools.eq_(len(iv.video_type[2]), len(iv.frame_type[2])+1)
-  assert isinstance(iv.info, str)
-
-@test_utils.ffmpeg_found()
-def test_video_reader_str():
-
-  from . import VideoReader
-
-  iv = VideoReader(INPUT_VIDEO)
-  assert repr(iv)
-  assert str(iv)
-
-@test_utils.ffmpeg_found()
-def test_can_iterate():
-
-  from . import VideoReader
-  video = VideoReader(INPUT_VIDEO)
-  counter = 0
-  for frame in video:
-    assert isinstance(frame, numpy.ndarray)
-    assert len(frame.shape) == 3
-    assert frame.shape[0] == 3 #color-bands (RGB)
-    assert frame.shape[1] == 240 #height
-    assert frame.shape[2] == 320 #width
-    counter += 1
-
-  assert counter == len(video) #we have gone through all frames
-
-@test_utils.ffmpeg_found()
-def test_iteration():
-
-  from . import load, VideoReader
-  f = VideoReader(INPUT_VIDEO)
-  objs = load(INPUT_VIDEO)
-
-  nose.tools.eq_(len(f), len(objs))
-  for l, i in zip(objs, f):
-    assert numpy.allclose(l, i)
-
-@test_utils.ffmpeg_found()
-def test_indexing():
-
-  from . import VideoReader
-  f = VideoReader(INPUT_VIDEO)
-
-  nose.tools.eq_(len(f), 375)
-
-  objs = f[:10]
-  nose.tools.eq_(len(objs), 10)
-  obj0 = f[0]
-  obj1 = f[1]
-
-  # simple indexing
-  assert numpy.allclose(objs[0], obj0)
-  assert numpy.allclose(objs[1], obj1)
-  assert numpy.allclose(f[len(f)-1], f[-1])
-  assert numpy.allclose(f[len(f)-2], f[-2])
-
-@test_utils.ffmpeg_found()
-def test_slicing_empty():
-
-  from . import load, VideoReader
-  f = VideoReader(INPUT_VIDEO)
-
-  objs = f[1:1]
-  assert objs.shape == tuple()
-  assert objs.dtype == numpy.uint8
-
-@test_utils.ffmpeg_found()
-def test_slicing_0():
-
-  from . import load, VideoReader
-  f = VideoReader(INPUT_VIDEO)
-
-  objs = f[:]
-  for i, k in enumerate(load(INPUT_VIDEO)):
-    assert numpy.allclose(k, objs[i])
-
-@test_utils.ffmpeg_found()
-def test_slicing_1():
-
-  from . import VideoReader
-  f = VideoReader(INPUT_VIDEO)
-
-  s = f[3:10:2]
-  nose.tools.eq_(len(s), 4)
-  assert numpy.allclose(s[0], f[3])
-  assert numpy.allclose(s[1], f[5])
-  assert numpy.allclose(s[2], f[7])
-  assert numpy.allclose(s[3], f[9])
-
-@test_utils.ffmpeg_found()
-def test_slicing_2():
-
-  from . import VideoReader
-  f = VideoReader(INPUT_VIDEO)
-
-  s = f[-10:-2:3]
-  nose.tools.eq_(len(s), 3)
-  assert numpy.allclose(s[0], f[len(f)-10])
-  assert numpy.allclose(s[1], f[len(f)-7])
-  assert numpy.allclose(s[2], f[len(f)-4])
-
-@test_utils.ffmpeg_found()
-def test_slicing_3():
-
-  from . import VideoReader
-  f = VideoReader(INPUT_VIDEO)
-  objs = f.load()
-
-  # get negative stepping slice
-  s = f[20:10:-3]
-  nose.tools.eq_(len(s), 4)
-  assert numpy.allclose(s[0], f[20])
-  assert numpy.allclose(s[1], f[17])
-  assert numpy.allclose(s[2], f[14])
-  assert numpy.allclose(s[3], f[11])
-
-@test_utils.ffmpeg_found()
-def test_slicing_4():
-
-  from . import VideoReader
-  f = VideoReader(INPUT_VIDEO)
-  objs = f[:21]
-
-  # get all negative slice
-  s = f[-10:-20:-3]
-  nose.tools.eq_(len(s), 4)
-  assert numpy.allclose(s[0], f[len(f)-10])
-  assert numpy.allclose(s[1], f[len(f)-13])
-  assert numpy.allclose(s[2], f[len(f)-16])
-  assert numpy.allclose(s[3], f[len(f)-19])
-
-
-@test_utils.ffmpeg_found()
-def test_can_use_array_interface():
-
-  from . import load, VideoReader
-  array = load(INPUT_VIDEO)
-  iv = VideoReader(INPUT_VIDEO)
-
-  for frame_id, frame in zip(range(array.shape[0]), iv.__iter__()):
-    assert numpy.array_equal(array[frame_id,:,:,:], frame)
-
-@test_utils.ffmpeg_found()
-def test_video_reading_after_writing():
-
-  from . import test_utils
-  tmpname = test_utils.temporary_filename(suffix='.avi')
-
-  from . import VideoWriter, VideoReader
-
-  try:
-
-    width = 20
-    height = 20
-    framerate = 24
-
-    outv = VideoWriter(tmpname, height, width, framerate)
-    for i in range(0, 3):
-      newframe = (numpy.random.random_integers(0,255,(3,height,width)))
-      outv.append(newframe.astype('uint8'))
-    outv.close()
-
-    # this should not crash
-    i = VideoReader(tmpname)
-    nose.tools.eq_(i.number_of_frames, 3)
-    nose.tools.eq_(i.width, width)
-    nose.tools.eq_(i.height, height)
-
-  finally:
-    # And we erase both files after this
-    if os.path.exists(tmpname): os.unlink(tmpname)
-
-@test_utils.ffmpeg_found()
-def test_video_writer_close():
-
-  from . import test_utils
-  tmpname = test_utils.temporary_filename(suffix='.avi')
-
-  from . import VideoWriter, VideoReader
-
-  try:
-
-    width = 20
-    height = 20
-    framerate = 24
-
-    outv = VideoWriter(tmpname, height, width, framerate)
-    for i in range(0, 3):
-      newframe = (numpy.random.random_integers(0,255,(3,height,width)))
-      outv.append(newframe.astype('uint8'))
-    outv.close()
-
-    # this should not crash
-    nose.tools.eq_(outv.filename, tmpname)
-    nose.tools.eq_(outv.width, width)
-    nose.tools.eq_(outv.height, height)
-    nose.tools.eq_(len(outv), 3)
-    nose.tools.eq_(outv.number_of_frames, len(outv))
-    nose.tools.eq_(outv.frame_rate, framerate)
-    assert outv.bit_rate
-    assert outv.gop
-
-  finally:
-    # And we erase both files after this
-    if os.path.exists(tmpname): os.unlink(tmpname)
-
-@test_utils.ffmpeg_found()
-def test_closed_video_writer_raises():
-
-  from . import test_utils
-  tmpname = test_utils.temporary_filename(suffix='.avi')
-
-  from . import VideoWriter
-
-  try:
-
-    width = 20
-    height = 20
-    framerate = 24
-
-    outv = VideoWriter(tmpname, height, width, framerate)
-    for i in range(0, 3):
-      newframe = (numpy.random.random_integers(0,255,(3,height,width)))
-      outv.append(newframe.astype('uint8'))
-    outv.close()
-
-    nose.tools.assert_raises(RuntimeError, outv.__str__)
-    nose.tools.assert_raises(RuntimeError, outv.__repr__)
-    nose.tools.assert_raises(RuntimeError, outv.append, newframe)
-
-    del outv
-
-  finally:
-    # And we erase both files after this
-    if os.path.exists(tmpname): os.unlink(tmpname)
diff --git a/xbob/io/base/test_video_codec.py b/xbob/io/base/test_video_codec.py
deleted file mode 100644
index 90a3e392eb6835e9b6dec6c28a1529ba03690f11..0000000000000000000000000000000000000000
--- a/xbob/io/base/test_video_codec.py
+++ /dev/null
@@ -1,192 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-# Andre Anjos <andre.anjos@idiap.ch>
-# Tue 12 Nov 09:25:56 2013
-
-"""Runs quality tests on video codecs supported
-"""
-
-import os
-import numpy
-import nose.tools
-from . import test_utils
-from .utils import color_distortion, frameskip_detection, quality_degradation
-
-# These are some global parameters for the test.
-INPUT_VIDEO = test_utils.datafile('test.mov', __name__)
-
-@test_utils.ffmpeg_found()
-def check_format_codec(function, shape, framerate, format, codec, maxdist):
-
-  length, height, width = shape
-  fname = test_utils.temporary_filename(suffix='.%s' % format)
-
-  try:
-    orig, framerate, encoded = function(shape, framerate, format, codec, fname)
-    reloaded = encoded.load()
-
-    # test number of frames is correct
-    assert len(orig) == len(encoded), "original length %d != %d encoded" % (len(orig), len(encoded))
-    assert len(orig) == len(reloaded), "original length %d != %d reloaded" % (len(orig), len(reloaded))
-
-    # test distortion patterns (quick sequential check)
-    dist = []
-    for k, of in enumerate(orig):
-      dist.append(abs(of.astype('float64')-reloaded[k].astype('float64')).mean())
-    assert max(dist) <= maxdist, "max(distortion) %g > %g allowed" % (max(dist), maxdist)
-
-    # assert we can randomly access any frame (choose 3 at random)
-    for k in numpy.random.randint(length, size=(3,)):
-      rdist = abs(orig[k].astype('float64')-encoded[k].astype('float64')).mean()
-      assert rdist <= maxdist, "distortion(frame[%d]) %g > %g allowed" % (k, rdist, maxdist)
-
-    # make sure that the encoded frame rate is not off by a big amount
-    assert abs(framerate - encoded.frame_rate) <= (1.0/length), "reloaded framerate %g differs from original %g by more than %g" % (encoded.frame_rate, framerate, 1.0/length)
-
-  finally:
-
-    if os.path.exists(fname): os.unlink(fname)
-
-def test_format_codecs():
-
-  length = 30
-  width = 128
-  height = 128
-  framerate = 30.
-  shape = (length, height, width)
-  methods = dict(
-      frameskip = frameskip_detection,
-      color     = color_distortion,
-      noise     = quality_degradation,
-      )
-
-  # distortion patterns for specific codecs
-  distortions = dict(
-      # we require high standards by default
-      default    = dict(frameskip=0.1,  color=9.0,  noise=45.),
-
-      # high-quality encoders
-      zlib       = dict(frameskip=0.0,  color=0.0, noise=0.0),
-      ffv1       = dict(frameskip=0.05, color=9.,  noise=46.),
-      vp8        = dict(frameskip=0.3,  color=9.0, noise=65.),
-      libvpx     = dict(frameskip=0.3,  color=9.0, noise=65.),
-      h264       = dict(frameskip=0.4,  color=9.0, noise=50.),
-      libx264    = dict(frameskip=0.4,  color=9.0, noise=50.),
-      theora     = dict(frameskip=0.5,  color=9.0, noise=70.),
-      libtheora  = dict(frameskip=0.5,  color=9.0, noise=70.),
-      mpeg4      = dict(frameskip=1.0,  color=9.0, noise=55.),
-
-      # older, but still good quality encoders
-      mjpeg      = dict(frameskip=1.2,  color=9.0, noise=50.),
-      mpegvideo  = dict(frameskip=1.3,  color=9.0, noise=55.),
-      mpeg2video = dict(frameskip=1.3,  color=9.0, noise=55.),
-      mpeg1video = dict(frameskip=1.4,  color=9.0, noise=50.),
-
-      # low quality encoders - avoid using - available for compatibility
-      wmv2       = dict(frameskip=3.0,  color=10., noise=50.),
-      wmv1       = dict(frameskip=2.5,  color=10., noise=50.),
-      msmpeg4    = dict(frameskip=5.,   color=10., noise=50.),
-      msmpeg4v2  = dict(frameskip=5.,   color=10., noise=50.),
-      )
-
-  # some exceptions
-  if test_utils.ffmpeg_version_lessthan('0.6'):
-    distortions['ffv1']['frameskip'] = 0.55
-    distortions['mpeg1video']['frameskip'] = 1.5
-    distortions['mpegvideo']['color'] = 9.0
-    distortions['mpegvideo']['frameskip'] = 1.4
-    distortions['mpeg2video']['color'] = 9.0
-    distortions['mpeg2video']['frameskip'] = 1.4
-
-  from .version import externals
-  if externals['FFmpeg']['ffmpeg'] != 'unavailable':
-    from .version import supported_videowriter_formats
-    SUPPORTED = supported_videowriter_formats()
-    for format in SUPPORTED:
-      for codec in SUPPORTED[format]['supported_codecs']:
-        for method in methods:
-          check_format_codec.description = "%s.test_%s_format_%s_codec_%s" % (__name__, method, format, codec)
-          distortion = distortions.get(codec, distortions['default'])[method]
-          yield check_format_codec, methods[method], shape, framerate, format, codec, distortion
-
-@test_utils.ffmpeg_found()
-def check_user_video(format, codec, maxdist):
-
-  from . import VideoReader, VideoWriter
-  fname = test_utils.temporary_filename(suffix='.%s' % format)
-  MAXLENTH = 10 #use only the first 10 frames
-
-  try:
-
-    orig_vreader = VideoReader(INPUT_VIDEO)
-    orig = orig_vreader[:MAXLENTH]
-    (olength, _, oheight, owidth) = orig.shape
-    assert len(orig) == MAXLENTH, "original length %d != %d MAXLENTH" % (len(orig), MAXLENTH)
-
-    # encode the input video using the format and codec provided by the user
-    outv = VideoWriter(fname, oheight, owidth, orig_vreader.frame_rate,
-        codec=codec, format=format)
-    for k in orig: outv.append(k)
-    outv.close()
-
-    # reload from saved file
-    encoded = VideoReader(fname)
-    reloaded = encoded.load()
-
-    # test number of frames is correct
-    assert len(orig) == len(encoded), "original length %d != %d encoded" % (len(orig), len(encoded))
-    assert len(orig) == len(reloaded), "original length %d != %d reloaded" % (len(orig), len(reloaded))
-
-    # test distortion patterns (quick sequential check)
-    dist = []
-    for k, of in enumerate(orig):
-      dist.append(abs(of.astype('float64')-reloaded[k].astype('float64')).mean())
-    assert max(dist) <= maxdist, "max(distortion) %g > %g allowed" % (max(dist), maxdist)
-
-    # make sure that the encoded frame rate is not off by a big amount
-    assert abs(orig_vreader.frame_rate - encoded.frame_rate) <= (1.0/MAXLENTH), "original video framerate %g differs from encoded %g by more than %g" % (encoded.frame_rate, framerate, 1.0/MAXLENTH)
-
-  finally:
-
-    if os.path.exists(fname): os.unlink(fname)
-
-def test_user_video():
-
-  # distortion patterns for specific codecs
-  distortions = dict(
-      # we require high standards by default
-      default    = 1.5,
-
-      # high-quality encoders
-      zlib       = 0.0,
-      ffv1       = 1.7,
-      vp8        = 2.7,
-      libvpx     = 2.7,
-      h264       = 2.5,
-      libx264    = 2.5,
-      theora     = 2.0,
-      libtheora  = 2.0,
-      mpeg4      = 2.3,
-
-      # older, but still good quality encoders
-      mjpeg      = 1.8,
-      mpegvideo  = 2.3,
-      mpeg2video = 2.3,
-      mpeg1video = 2.3,
-
-      # low quality encoders - avoid using - available for compatibility
-      wmv2       = 2.3,
-      wmv1       = 2.3,
-      msmpeg4    = 2.3,
-      msmpeg4v2  = 2.3,
-      )
-
-  from .version import externals
-  if externals['FFmpeg']['ffmpeg'] != 'unavailable':
-    from .version import supported_videowriter_formats
-    SUPPORTED = supported_videowriter_formats()
-    for format in SUPPORTED:
-      for codec in SUPPORTED[format]['supported_codecs']:
-        check_user_video.description = "%s.test_user_video_format_%s_codec_%s" % (__name__, format, codec)
-        distortion = distortions.get(codec, distortions['default'])
-        yield check_user_video, format, codec, distortion
diff --git a/xbob/io/base/utils.py b/xbob/io/base/utils.py
deleted file mode 100644
index 9e3d67b7f83120050dab2bf357cc72489bd4b5c7..0000000000000000000000000000000000000000
--- a/xbob/io/base/utils.py
+++ /dev/null
@@ -1,200 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-# Andre Anjos <andre.dos.anjos@gmail.com>
-# Thu 14 Mar 17:00:58 2013
-#
-# Copyright (C) 2011-2013 Idiap Research Institute, Martigny, Switzerland
-
-"""Some utilities to generate fake patterns
-"""
-
-import numpy
-
-DEFAULT_FONT = __import__('pkg_resources').resource_filename(__name__,
-    __import__('os').path.join("fonts", "regular.ttf"))
-
-def estimate_fontsize(height, width, format):
-  """Estimates the best fontsize to fit into a image that is (height, width)"""
-
-  try:
-    # if PIL is installed this works:
-    import Image, ImageFont, ImageDraw
-  except ImportError:
-    # if Pillow is installed, this works better:
-    from PIL import Image, ImageFont, ImageDraw
-
-  best_size = min(height, width)
-  fit = False
-  while best_size > 0:
-    font = ImageFont.truetype(DEFAULT_FONT, best_size)
-    (text_width, text_height) = font.getsize(format % 0)
-    if text_width < width and text_height < height: break
-    best_size -= 1
-
-  if best_size <= 0:
-    raise RuntimeError("Cannot find best size for font")
-
-  return best_size
-
-def print_numbers(frame, counter, format, fontsize):
-  """Generates an image that serves as a test pattern for encoding/decoding and
-  accuracy tests."""
-
-  try:
-    # if PIL is installed this works:
-    import Image, ImageFont, ImageDraw
-  except ImportError:
-    # if Pillow is installed, this works better:
-    from PIL import Image, ImageFont, ImageDraw
-
-  _, height, width = frame.shape
-
-  # text at the center, indicating the frame number
-  text = format % counter
-  dim = min(width, height)
-  font = ImageFont.truetype(DEFAULT_FONT, fontsize)
-  (text_width, text_height) = font.getsize(text)
-  x_pos = int((width - text_width) / 2)
-  y_pos = int((height - text_height) / 2)
-  # this is buggy in Pillow-2.0.0, so we do it manually
-  #img = Image.fromarray(frame.transpose(1,2,0))
-  img = Image.fromstring('RGB', (frame.shape[1], frame.shape[2]), frame.transpose(1,2,0).tostring())
-  draw = ImageDraw.Draw(img)
-  draw.text((x_pos, y_pos), text, font=font, fill=(255,255,255))
-  return numpy.asarray(img).transpose(2,0,1)
-
-def generate_colors(height, width, shift):
-  """Generates an image that serves as a test pattern for encoding/decoding and
-  accuracy tests."""
-
-  retval = numpy.ndarray((3, height, width), dtype='uint8')
-
-  # standard color test pattern
-  w = width / 7; w2 = 2*w; w3 = 3*w; w4 = 4*w; w5 = 5*w; w6 = 6*w
-  retval[0,:,0:w]   = 255; retval[1,:,0:w]   = 255; retval[2,:,0:w]   = 255;
-  retval[0,:,w:w2]  = 255; retval[1,:,w:w2]  = 255; retval[2,:,w:w2]  = 0;
-  retval[0,:,w2:w3] = 0;   retval[1,:,w2:w3] = 255; retval[2,:,w2:w3] = 255;
-  retval[0,:,w3:w4] = 0;   retval[1,:,w3:w4] = 255; retval[2,:,w3:w4] = 0;
-  retval[0,:,w4:w5] = 255; retval[1,:,w4:w5] = 0;   retval[2,:,w4:w5] = 255;
-  retval[0,:,w5:w6] = 255; retval[1,:,w5:w6] = 0;   retval[2,:,w5:w6] = 0;
-  retval[0,:,w6:]   = 0;   retval[1,:,w6:]  = 0;   retval[2,:,w6:]   = 255;
-
-  # rotate by 'shift'
-  retval = numpy.roll(retval, shift, axis=2)
-  return retval
-
-def color_distortion(shape, framerate, format, codec, filename):
-  """Returns distortion patterns for a set of frames with moving colors.
-
-  Keyword parameters:
-
-  shape (int, int, int)
-    The length (number of frames), height and width for the generated sequence
-
-  format
-    The string that identifies the format to be used for the output file
-
-  codec
-    The codec to be used for the output file
-
-  filename
-    The name of the file to use for encoding the test
-  """
-
-  length, height, width = shape
-  from . import VideoReader, VideoWriter
-  outv = VideoWriter(filename, height, width, framerate, codec=codec,
-      format=format, check=False)
-  orig = []
-  text_format = "%%0%dd" % len(str(length-1))
-  fontsize = estimate_fontsize(height, width, text_format)
-  fontsize = int(fontsize/4)
-  for i in range(0, length):
-    newframe = generate_colors(height, width, i%width)
-    newframe = print_numbers(newframe, i, text_format, fontsize)
-    outv.append(newframe)
-    orig.append(newframe)
-  outv.close()
-  orig = numpy.array(orig, dtype='uint8')
-  return orig, framerate, VideoReader(filename, check=False)
-
-def frameskip_detection(shape, framerate, format, codec, filename):
-  """Returns distortion patterns for a set of frames with big numbers.
-
-  Keyword parameters:
-
-  shape (int, int, int)
-    The length (number of frames), height and width for the generated sequence
-
-  format
-    The string that identifies the format to be used for the output file
-
-  codec
-    The codec to be used for the output file
-
-  filename
-    The name of the file to use for encoding the test
-  """
-
-  length, height, width = shape
-  from . import VideoReader, VideoWriter
-  text_format = "%%0%dd" % len(str(length-1))
-  fontsize = estimate_fontsize(height, width, text_format)
-  outv = VideoWriter(filename, height, width, framerate, codec=codec,
-      format=format, check=False)
-  orig = []
-  for i in range(0, length):
-    newframe = numpy.zeros((3, height, width), dtype='uint8')
-    newframe = print_numbers(newframe, i, text_format, fontsize)
-    outv.append(newframe)
-    orig.append(newframe)
-  outv.close()
-  orig = numpy.array(orig, dtype='uint8')
-  return orig, framerate, VideoReader(filename, check=False)
-
-def quality_degradation(shape, framerate, format, codec, filename):
-  """Returns noise patterns for a set of frames.
-
-  Keyword parameters:
-
-  shape (int, int, int)
-    The length (number of frames), height and width for the generated sequence
-
-  format
-    The string that identifies the format to be used for the output file
-
-  codec
-    The codec to be used for the output file
-
-  filename
-    The name of the file to use for encoding the test
-  """
-
-  length, height, width = shape
-  from . import VideoReader, VideoWriter
-  text_format = "%%0%dd" % len(str(length-1))
-  fontsize = estimate_fontsize(height, width, text_format)
-  fontsize = int(fontsize/4)
-  outv = VideoWriter(filename, height, width, framerate, codec=codec,
-      format=format, check=False)
-  orig = []
-  for i in range(0, length):
-    newframe = numpy.random.randint(0, 256, (3, height, width)).astype('uint8')
-    newframe = print_numbers(newframe, i, text_format, fontsize)
-    outv.append(newframe)
-    orig.append(newframe)
-  outv.close()
-  orig = numpy.array(orig, dtype='uint8')
-  return orig, framerate, VideoReader(filename, check=False)
-
-def is_string(s):
-  """Returns ``True`` if the given object is a string
-
-  This method can be used with Python-2.x or 3.x and returns a string
-  respecting each environment's constraints.
-  """
-
-  from sys import version_info
-
-  return (version_info[0] < 3 and isinstance(s, (str, unicode))) or \
-    isinstance(s, (bytes, str))
diff --git a/xbob/io/base/version.cpp b/xbob/io/base/version.cpp
index 7602399c2758f15617a95b86a8f4b8c2fe6e2075..e5458f98d6e14ad8fa0b32ff40ac846ec6637114 100644
--- a/xbob/io/base/version.cpp
+++ b/xbob/io/base/version.cpp
@@ -21,51 +21,10 @@
 
 #include <bob/config.h>
 #include <bob/io/CodecRegistry.h>
-#include <bob/io/VideoUtilities.h>
 
 #include <xbob.blitz/capi.h>
 #include <xbob.blitz/cleanup.h>
-
-extern "C" {
-
-#ifdef NO_IMPORT_ARRAY
-#undef NO_IMPORT_ARRAY
-#endif
-#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
-#include <numpy/arrayobject.h>
-
 #include <hdf5.h>
-#include <jpeglib.h>
-
-#define PNG_SKIP_SETJMP_CHECK
-// #define requires because of the problematic pngconf.h.
-// Look at the thread here:
-// https://bugs.launchpad.net/ubuntu/+source/libpng/+bug/218409
-#include <png.h>
-
-#if WITH_FFMPEG
-#  include <libavformat/avformat.h>
-#  include <libavcodec/avcodec.h>
-#  if LIBAVUTIL_VERSION_INT >= 0x320f01 //50.15.1 @ ffmpeg-0.6
-#    include <libavutil/opt.h>
-#    include <libavutil/pixdesc.h>
-#  endif
-#  include <libavutil/avutil.h>
-#  include <libswscale/swscale.h>
-#  if !HAVE_FFMPEG_AVCODEC_AVCODECID
-#    define AVCodecID CodecID
-#  endif
-#endif
-
-#include <gif_lib.h>
-
-#if WITH_MATIO
-#include <matio.h>
-#endif
-
-#include <tiffio.h>
-
-}
 
 static int dict_set(PyObject* d, const char* key, const char* value) {
   PyObject* v = Py_BuildValue("s", value);
@@ -92,74 +51,6 @@ static PyObject* make_object(const char* s) {
   return Py_BuildValue("s", s);
 }
 
-#if WITH_FFMPEG
-
-static PyObject* make_object(bool v) {
-  if (v) Py_RETURN_TRUE;
-  Py_RETURN_FALSE;
-}
-
-static PyObject* make_object(unsigned int v) {
-  return Py_BuildValue("n", v);
-}
-
-static PyObject* make_object(double v) {
-  return PyFloat_FromDouble(v);
-}
-
-static PyObject* make_object(PyObject* v) {
-  Py_INCREF(v);
-  return v;
-}
-
-/**
- * Sets a dictionary entry using a string as key and another one as value.
- * Returns 1 in case of success, 0 in case of failure.
- */
-template <typename T>
-int dict_set_string(boost::shared_ptr<PyObject> d, const char* key, T value) {
-  PyObject* pyvalue = make_object(value);
-  if (!pyvalue) return 0;
-  int retval = PyDict_SetItemString(d.get(), key, pyvalue);
-  Py_DECREF(pyvalue);
-  if (retval == 0) return 1; //all good
-  return 0; //a problem occurred
-}
-
-/**
- * Sets a dictionary entry using a string as key and another one as value.
- * Returns 1 in case of success, 0 in case of faiulre.
- */
-template <typename T>
-int list_append(PyObject* l, T value) {
-  PyObject* pyvalue = make_object(value);
-  if (!pyvalue) return 0;
-  int retval = PyList_Append(l, pyvalue);
-  Py_DECREF(pyvalue);
-  if (retval == 0) return 1; //all good
-  return 0; //a problem occurred
-}
-
-/**
- * A deleter, for shared_ptr's
- */
-void pyobject_deleter(PyObject* o) {
-  Py_XDECREF(o);
-}
-
-/**
- * Checks if it is a Python string for Python 2.x or 3.x
- */
-int check_string(PyObject* o) {
-#     if PY_VERSION_HEX >= 0x03000000
-      return PyUnicode_Check(o);
-#     else
-      return PyString_Check(o);
-#     endif
-}
-
-#endif /* WITH_FFMPEG */
-
 /***********************************************************
  * Version number generation
  ***********************************************************/
@@ -172,111 +63,6 @@ static PyObject* hdf5_version() {
   return Py_BuildValue("s", f.str().c_str());
 }
 
-/**
- * FFmpeg version
- */
-static PyObject* ffmpeg_version() {
-  PyObject* retval = PyDict_New();
-  if (!retval) return 0;
-  auto retval_ = make_safe(retval);
-
-#if WITH_FFMPEG
-# if defined(FFMPEG_VERSION)
-  if (std::strlen(FFMPEG_VERSION)) {
-    if (!dict_set(retval, "ffmpeg", FFMPEG_VERSION)) return 0;
-  }
-# endif
-  if (!dict_set(retval, "avformat", BOOST_PP_STRINGIZE(LIBAVFORMAT_VERSION))) {
-    return 0;
-  }
-  if (!dict_set(retval, "avcodec", BOOST_PP_STRINGIZE(LIBAVCODEC_VERSION))) {
-    return 0;
-  }
-  if (!dict_set(retval, "avutil", BOOST_PP_STRINGIZE(LIBAVUTIL_VERSION))) {
-    return 0;
-  }
-  if (!dict_set(retval, "swscale", BOOST_PP_STRINGIZE(LIBSWSCALE_VERSION))) {
-    return 0;
-  }
-#else
-  if (!dict_set(retval, "ffmpeg", "unavailable")) {
-    return 0;
-  }
-#endif
-  Py_INCREF(retval);
-  return retval;
-}
-
-/**
- * LibJPEG version
- */
-static PyObject* libjpeg_version() {
-  boost::format f("%d (compiled with %d bits depth)");
-  f % JPEG_LIB_VERSION;
-  f % BITS_IN_JSAMPLE;
-  return Py_BuildValue("s", f.str().c_str());
-}
-
-/**
- * Libpng version
- */
-static PyObject* libpng_version() {
-  return Py_BuildValue("s", PNG_LIBPNG_VER_STRING);
-}
-
-/**
- * Libtiff version
- */
-static PyObject* libtiff_version() {
-
-  static const std::string beg_str("LIBTIFF, Version ");
-  static const size_t beg_len = beg_str.size();
-  std::string vtiff(TIFFGetVersion());
-
-  // Remove first part if it starts with "LIBTIFF, Version "
-  if(vtiff.compare(0, beg_len, beg_str) == 0)
-    vtiff = vtiff.substr(beg_len);
-
-  // Remove multiple (copyright) lines if any
-  size_t end_line = vtiff.find("\n");
-  if(end_line != std::string::npos)
-    vtiff = vtiff.substr(0,end_line);
-
-  return Py_BuildValue("s", vtiff.c_str());
-
-}
-
-/**
- * Version of giflib support
- */
-static PyObject* giflib_version() {
-#ifdef GIF_LIB_VERSION
- return Py_BuildValue("s", GIF_LIB_VERSION);
-#else
-  boost::format f("%s.%s.%s");
-  f % BOOST_PP_STRINGIZE(GIFLIB_MAJOR);
-  f % BOOST_PP_STRINGIZE(GIFLIB_MINOR);
-  f % BOOST_PP_STRINGIZE(GIFLIB_RELEASE);
-  return Py_BuildValue("s", f.str().c_str());
-#endif
-}
-
-
-/**
- * Matio, if compiled with such support
- */
-static PyObject* matio_version() {
-#if WITH_MATIO
-  boost::format f("%s.%s.%s");
-  f % BOOST_PP_STRINGIZE(MATIO_MAJOR_VERSION);
-  f % BOOST_PP_STRINGIZE(MATIO_MINOR_VERSION);
-  f % BOOST_PP_STRINGIZE(MATIO_RELEASE_LEVEL);
-  return Py_BuildValue("s", f.str().c_str());
-#else
-  return Py_BuildValue("s", "unavailable");
-#endif
-}
-
 /**
  * Bob version, API version and platform
  */
@@ -348,13 +134,6 @@ static PyObject* build_version_dictionary() {
 
   if (!dict_steal(retval, "Bob", bob_version())) return 0;
   if (!dict_steal(retval, "HDF5", hdf5_version())) return 0;
-  if (!dict_steal(retval, "FFmpeg", ffmpeg_version())) return 0;
-  if (!dict_steal(retval, "libjpeg", libjpeg_version())) return 0;
-  if (!dict_set(retval, "libnetpbm", "Unknown version")) return 0;
-  if (!dict_steal(retval, "libpng", libpng_version())) return 0;
-  if (!dict_steal(retval, "libtiff", libtiff_version())) return 0;
-  if (!dict_steal(retval, "giflib", giflib_version())) return 0;
-  if (!dict_steal(retval, "MatIO", matio_version())) return 0;
   if (!dict_steal(retval, "Boost", boost_version())) return 0;
   if (!dict_steal(retval, "Compiler", compiler_version())) return 0;
   if (!dict_steal(retval, "Python", python_version())) return 0;
@@ -367,453 +146,6 @@ static PyObject* build_version_dictionary() {
   return retval;
 }
 
-/***********************************************************
- * FFmpeg information
- ***********************************************************/
-
-#if WITH_FFMPEG
-
-/**
- * Describes a given codec. We return a **new reference** to a dictionary
- * containing the codec properties.
- */
-static PyObject* describe_codec(const AVCodec* codec) {
-
-  /**
-   * We wrap the returned object into a smart pointer until we
-   * are absolutely sure all went good. At this point, we free
-   * the PyObject* from the boost encapsulation and return it.
-   */
-  boost::shared_ptr<PyObject> retval(PyDict_New(), &pyobject_deleter);
-  if (!retval) return 0;
-
-  /* Sets basic properties for the codec */
-  if (!dict_set_string(retval, "name", codec->name)) return 0;
-  if (!dict_set_string(retval, "long_name", codec->long_name)) return 0;
-  if (!dict_set_string(retval, "id", (unsigned int)codec->id)) return 0;
-
-  /**
-   * If pixel formats are available, creates and attaches a
-   * list with all their names
-   */
-
-  boost::shared_ptr<PyObject> pixfmt;
-  if (codec->pix_fmts) {
-    pixfmt.reset(PyList_New(0), &pyobject_deleter);
-    if (!pixfmt) return 0;
-
-    unsigned int i=0;
-    while(codec->pix_fmts[i] != -1) {
-      if (!list_append(pixfmt.get(),
-#if LIBAVUTIL_VERSION_INT >= 0x320f01 //50.15.1 @ ffmpeg-0.6
-            av_get_pix_fmt_name
-#else
-            avcodec_get_pix_fmt_name
-#endif
-            (codec->pix_fmts[i++]))) return 0;
-    }
-    pixfmt.reset(PySequence_Tuple(pixfmt.get()), &pyobject_deleter);
-  }
-  else {
-    Py_INCREF(Py_None);
-    pixfmt.reset(Py_None, &pyobject_deleter);
-  }
-
-  if (!dict_set_string(retval, "pixfmts", pixfmt.get())) return 0;
-
-  /* Get specific framerates for the codec, if any */
-  const AVRational* rate = codec->supported_framerates;
-  boost::shared_ptr<PyObject> rates(PyList_New(0), &pyobject_deleter);
-  if (!rates) return 0;
-
-  while (rate && rate->num && rate->den) {
-    list_append(rates.get(), ((double)rate->num)/((double)rate->den));
-    ++rate;
-  }
-  rates.reset(PySequence_Tuple(rates.get()), &pyobject_deleter);
-  if (!rates) return 0;
-
-  if (!dict_set_string(retval, "specific_framerates_hz", rates.get())) return 0;
-
-  /* Other codec capabilities */
-# ifdef CODEC_CAP_LOSSLESS
-  if (!dict_set_string(retval, "lossless", (bool)(codec->capabilities & CODEC_CAP_LOSSLESS))) return 0;
-# endif
-# ifdef CODEC_CAP_EXPERIMENTAL
-  if (!dict_set_string(retval, "experimental", (bool)(codec->capabilities & CODEC_CAP_EXPERIMENTAL))) return 0;
-# endif
-# ifdef CODEC_CAP_DELAY
-  if (!dict_set_string(retval, "delay", (bool)(codec->capabilities & CODEC_CAP_DELAY))) return 0;
-# endif
-# ifdef CODEC_CAP_HWACCEL
-  if (!dict_set_string(retval, "hardware_accelerated", (bool)(codec->capabilities & CODEC_CAP_HWACCEL))) return 0;
-# endif
-  if (!dict_set_string(retval, "encode", (bool)(avcodec_find_encoder(codec->id)))) return 0;
-  if (!dict_set_string(retval, "decode", (bool)(avcodec_find_decoder(codec->id)))) return 0;
-
-  /* If all went OK, detach the returned value from the smart pointer **/
-  Py_INCREF(retval.get());
-  return retval.get();
-
-}
-
-/**
- * Describes a given codec or raises, in case the codec cannot be accessed
- */
-static PyObject* PyBobIo_DescribeEncoder(PyObject*, PyObject *args, PyObject* kwds) {
-
-  /* Parses input arguments in a single shot */
-  static const char* const_kwlist[] = {"key", 0};
-  static char** kwlist = const_cast<char**>(const_kwlist);
-
-  PyObject* key = 0;
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &key)) return 0;
-
-  if (!PyNumber_Check(key) && !check_string(key)) {
-    PyErr_SetString(PyExc_TypeError, "input `key' must be a number identifier or a string with the codec name");
-    return 0;
-  }
-
-  if (PyNumber_Check(key)) {
-
-    /* If you get to this point, the user passed a number - re-parse */
-    int id = 0;
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &id)) return 0;
-
-    AVCodec* codec = avcodec_find_encoder((AVCodecID)id);
-    if (!codec) {
-      PyErr_Format(PyExc_RuntimeError, "ffmpeg::avcodec_find_encoder(%d == 0x%x) did not return a valid codec", id, id);
-      return 0;
-    }
-
-    return describe_codec(codec);
-  }
-
-  /* If you get to this point, the user passed a string - re-parse */
-  const char* name = 0;
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &name)) return 0;
-
-  AVCodec* codec = avcodec_find_encoder_by_name(name);
-  if (!codec) {
-    PyErr_Format(PyExc_RuntimeError, "ffmpeg::avcodec_find_encoder_by_name(`%s') did not return a valid codec", name);
-    return 0;
-  }
-
-  return describe_codec(codec);
-}
-
-PyDoc_STRVAR(s_describe_encoder_str, "describe_encoder");
-PyDoc_STRVAR(s_describe_encoder_doc,
-"describe_encoder([key]) -> dict\n\
-\n\
-Parameters:\n\
-\n\
-key\n\
-  [int|str, optional] A key which can be either the encoder\n\
-  name or its numerical identifier.\n\
-\n\
-Returns a dictionary containing a description of properties in\n\
-the given encoder.\n\
-");
-
-/**
- * Describes a given codec or raises, in case the codec cannot be accessed
- */
-static PyObject* PyBobIo_DescribeDecoder(PyObject*, PyObject *args, PyObject* kwds) {
-
-  /* Parses input arguments in a single shot */
-  static const char* const_kwlist[] = {"key", 0};
-  static char** kwlist = const_cast<char**>(const_kwlist);
-
-  PyObject* key = 0;
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &key)) return 0;
-
-  if (!PyNumber_Check(key) && !check_string(key)) {
-    PyErr_SetString(PyExc_TypeError, "input `key' must be a number identifier or a string with the codec name");
-    return 0;
-  }
-
-  if (PyNumber_Check(key)) {
-
-    /* If you get to this point, the user passed a number - re-parse */
-    int id = 0;
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &id)) return 0;
-
-    AVCodec* codec = avcodec_find_decoder((AVCodecID)id);
-    if (!codec) {
-      PyErr_Format(PyExc_RuntimeError, "ffmpeg::avcodec_find_decoder(%d == 0x%x) did not return a valid codec", id, id);
-      return 0;
-    }
-
-    return describe_codec(codec);
-  }
-
-  /* If you get to this point, the user passed a string - re-parse */
-  const char* name = 0;
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &name)) return 0;
-
-  AVCodec* codec = avcodec_find_decoder_by_name(name);
-  if (!codec) {
-    PyErr_Format(PyExc_RuntimeError, "ffmpeg::avcodec_find_decoder_by_name(`%s') did not return a valid codec", name);
-    return 0;
-  }
-
-  return describe_codec(codec);
-}
-
-PyDoc_STRVAR(s_describe_decoder_str, "describe_decoder");
-PyDoc_STRVAR(s_describe_decoder_doc,
-"describe_decoder([key]) -> dict\n\
-\n\
-Parameters:\n\
-\n\
-key\n\
-  [int|str, optional] A key which can be either the decoder\n\
-  name or its numerical identifier.\n\
-\n\
-Returns a dictionary containing a description of properties in\n\
-the given decoder.\n\
-");
-
-static PyObject* get_video_codecs(void (*f)(std::map<std::string, const AVCodec*>&)) {
-
-  std::map<std::string, const AVCodec*> m;
-  f(m);
-
-  PyObject* retval = PyDict_New();
-  if (!retval) return 0;
-  auto retval_ = make_safe(retval);
-
-  for (auto k=m.begin(); k!=m.end(); ++k) {
-    PyObject* pyvalue = describe_codec(k->second);
-    if (!pyvalue) return 0;
-    auto pyvalue_ = make_safe(pyvalue);
-    if (PyDict_SetItemString(retval, k->first.c_str(), pyvalue) != 0) return 0;
-  }
-
-  Py_INCREF(retval);
-  return retval;
-
-}
-
-static PyObject* PyBobIo_SupportedCodecs(PyObject*) {
-  return get_video_codecs(&bob::io::detail::ffmpeg::codecs_supported);
-}
-
-static PyObject* PyBobIo_AvailableCodecs(PyObject*) {
-  return get_video_codecs(&bob::io::detail::ffmpeg::codecs_installed);
-}
-
-PyDoc_STRVAR(s_supported_codecs_str, "supported_video_codecs");
-PyDoc_STRVAR(s_supported_codecs_doc,
-"supported_video_codecs() -> dict\n\
-\n\
-Returns a dictionary with currently supported video codec properties.\n\
-\n\
-Returns a dictionary containing a detailed description of the\n\
-built-in codecs for videos that are fully supported.\n\
-");
-
-PyDoc_STRVAR(s_available_codecs_str, "available_video_codecs");
-PyDoc_STRVAR(s_available_codecs_doc,
-"available_video_codecs() -> dict\n\
-\n\
-Returns a dictionary with all available video codec properties.\n\
-\n\
-Returns a dictionary containing a detailed description of the\n\
-built-in codecs for videos that are available but **not necessarily\n\
-supported**.\n\
-");
-
-static PyObject* get_video_iformats(void (*f)(std::map<std::string, AVInputFormat*>&)) {
-
-  std::map<std::string, AVInputFormat*> m;
-  f(m);
-
-  PyObject* retval = PyDict_New();
-  if (!retval) return 0;
-  auto retval_ = make_safe(retval);
-
-  for (auto k=m.begin(); k!=m.end(); ++k) {
-
-    PyObject* property = PyDict_New();
-    if (!property) return 0;
-    auto property_ = make_safe(property);
-
-    if (!dict_set(property, "name", k->second->name)) return 0;
-
-    if (!dict_set(property, "long_name", k->second->long_name)) return 0;
-
-    // get extensions
-    std::vector<std::string> exts;
-    bob::io::detail::ffmpeg::tokenize_csv(k->second->extensions, exts);
-
-    PyObject* ext_list = PyList_New(0);
-    if (!ext_list) return 0;
-    auto ext_list_ = make_safe(ext_list);
-
-    for (auto ext=exts.begin(); ext!=exts.end(); ++ext) {
-      if (!list_append(ext_list, ext->c_str())) return 0;
-    }
-
-    Py_INCREF(ext_list);
-    if (!dict_steal(property, "extensions", ext_list)) return 0;
-
-    Py_INCREF(property);
-    if (!dict_steal(retval, k->first.c_str(), property)) return 0;
-
-  }
-
-  Py_INCREF(retval);
-  return retval;
-
-}
-
-static PyObject* PyBobIo_SupportedInputFormats(PyObject*) {
-  return get_video_iformats(&bob::io::detail::ffmpeg::iformats_supported);
-}
-
-static PyObject* PyBobIo_AvailableInputFormats(PyObject*) {
-  return get_video_iformats(&bob::io::detail::ffmpeg::iformats_installed);
-}
-
-PyDoc_STRVAR(s_supported_iformats_str, "supported_videoreader_formats");
-PyDoc_STRVAR(s_supported_iformats_doc,
-"supported_videoreader_formats() -> dict\n\
-\n\
-Returns a dictionary with currently supported video input formats.\n\
-\n\
-Returns a dictionary containing a detailed description of the\n\
-built-in input formats for videos that are fully supported.\n\
-");
-
-PyDoc_STRVAR(s_available_iformats_str, "available_videoreader_formats");
-PyDoc_STRVAR(s_available_iformats_doc,
-"available_videoreader_formats() -> dict\n\
-\n\
-Returns a dictionary with currently available video input formats.\n\
-\n\
-Returns a dictionary containing a detailed description of the\n\
-built-in input formats for videos that are available, but **not\n\
-necessarily supported** by this library.\n\
-");
-
-static PyObject* get_video_oformats(bool supported) {
-
-  std::map<std::string, AVOutputFormat*> m;
-  if (supported) bob::io::detail::ffmpeg::oformats_supported(m);
-  else bob::io::detail::ffmpeg::oformats_installed(m);
-
-  PyObject* retval = PyDict_New();
-  if (!retval) return 0;
-  auto retval_ = make_safe(retval);
-
-  for (auto k=m.begin(); k!=m.end(); ++k) {
-
-    PyObject* property = PyDict_New();
-    if (!property) return 0;
-    auto property_ = make_safe(property);
-
-    if (!dict_set(property, "name", k->second->name)) return 0;
-
-    if (!dict_set(property, "long_name", k->second->long_name)) return 0;
-
-    if (!dict_set(property, "mime_type", k->second->mime_type)) return 0;
-
-    // get extensions
-    std::vector<std::string> exts;
-    bob::io::detail::ffmpeg::tokenize_csv(k->second->extensions, exts);
-
-    PyObject* ext_list = PyList_New(0);
-    if (!ext_list) return 0;
-    auto ext_list_ = make_safe(ext_list);
-
-    for (auto ext=exts.begin(); ext!=exts.end(); ++ext) {
-      if (!list_append(ext_list, ext->c_str())) return 0;
-    }
-
-    Py_INCREF(ext_list);
-    if (!dict_steal(property, "extensions", ext_list)) return 0;
-
-    /**  get recommended codec **/
-    PyObject* default_codec = 0;
-    if (k->second->video_codec) {
-      AVCodec* codec = avcodec_find_encoder(k->second->video_codec);
-      if (codec) {
-        default_codec = describe_codec(codec);
-        if (!default_codec) return 0;
-      }
-    }
-
-    if (!default_codec) {
-      Py_INCREF(Py_None);
-      default_codec = Py_None;
-    }
-
-    if (!dict_steal(property, "default_codec", default_codec)) return 0;
-
-    /** get supported codec list **/
-    if (supported) {
-      std::vector<const AVCodec*> codecs;
-      bob::io::detail::ffmpeg::oformat_supported_codecs(k->second->name, codecs);
-
-      PyObject* supported_codecs = PyDict_New();
-      if (!supported_codecs) return 0;
-      auto supported_codecs_ = make_safe(supported_codecs);
-
-      for (auto c=codecs.begin(); c!=codecs.end(); ++c) {
-        PyObject* codec_descr = describe_codec(*c);
-        auto codec_descr_ = make_safe(codec_descr);
-        if (!codec_descr) return 0;
-        Py_INCREF(codec_descr);
-        if (!dict_steal(supported_codecs, (*c)->name, codec_descr)) return 0;
-      }
-
-      Py_INCREF(supported_codecs);
-      if (!dict_steal(property, "supported_codecs", supported_codecs)) return 0;
-    }
-
-    Py_INCREF(property);
-    if (!dict_steal(retval, k->first.c_str(), property)) return 0;
-
-  }
-
-  Py_INCREF(retval);
-  return retval;
-
-}
-
-static PyObject* PyBobIo_SupportedOutputFormats(PyObject*) {
-  return get_video_oformats(true);
-}
-
-static PyObject* PyBobIo_AvailableOutputFormats(PyObject*) {
-  return get_video_oformats(false);
-}
-
-PyDoc_STRVAR(s_supported_oformats_str, "supported_videowriter_formats");
-PyDoc_STRVAR(s_supported_oformats_doc,
-"supported_videowriter_formats() -> dict\n\
-\n\
-Returns a dictionary with currently supported video output formats.\n\
-\n\
-Returns a dictionary containing a detailed description of the\n\
-built-in output formats for videos that are fully supported.\n\
-");
-
-PyDoc_STRVAR(s_available_oformats_str, "available_videowriter_formats");
-PyDoc_STRVAR(s_available_oformats_doc,
-"available_videowriter_formats() -> dict\n\
-\n\
-Returns a dictionary with currently available video output formats.\n\
-\n\
-Returns a dictionary containing a detailed description of the\n\
-built-in output formats for videos that are available, but **not\n\
-necessarily supported** by this library.\n\
-");
-
-#endif /* WITH_FFMPEG */
-
 static PyObject* PyBobIo_Extensions(PyObject*) {
 
   typedef std::map<std::string, std::string> map_type;
@@ -851,58 +183,6 @@ static PyMethodDef module_methods[] = {
       METH_NOARGS,
       s_extensions_doc,
     },
-
-#if WITH_FFMPEG
-    {
-      s_describe_encoder_str,
-      (PyCFunction)PyBobIo_DescribeEncoder,
-      METH_VARARGS|METH_KEYWORDS,
-      s_describe_encoder_doc,
-    },
-    {
-      s_describe_decoder_str,
-      (PyCFunction)PyBobIo_DescribeDecoder,
-      METH_VARARGS|METH_KEYWORDS,
-      s_describe_decoder_doc,
-    },
-    {
-      s_supported_codecs_str,
-      (PyCFunction)PyBobIo_SupportedCodecs,
-      METH_NOARGS,
-      s_supported_codecs_doc,
-    },
-    {
-      s_available_codecs_str,
-      (PyCFunction)PyBobIo_AvailableCodecs,
-      METH_NOARGS,
-      s_available_codecs_doc,
-    },
-    {
-      s_supported_iformats_str,
-      (PyCFunction)PyBobIo_SupportedInputFormats,
-      METH_NOARGS,
-      s_supported_iformats_doc,
-    },
-    {
-      s_available_iformats_str,
-      (PyCFunction)PyBobIo_AvailableInputFormats,
-      METH_NOARGS,
-      s_available_iformats_doc,
-    },
-    {
-      s_supported_oformats_str,
-      (PyCFunction)PyBobIo_SupportedOutputFormats,
-      METH_NOARGS,
-      s_supported_oformats_doc,
-    },
-    {
-      s_available_oformats_str,
-      (PyCFunction)PyBobIo_AvailableOutputFormats,
-      METH_NOARGS,
-      s_available_oformats_doc,
-    },
-#endif /* WITH_FFMPEG */
-
     {0}  /* Sentinel */
 };
 
diff --git a/xbob/io/base/videoreader.cpp b/xbob/io/base/videoreader.cpp
deleted file mode 100644
index 837d0f62c51102a2f75889d57e14ff4c98be14b3..0000000000000000000000000000000000000000
--- a/xbob/io/base/videoreader.cpp
+++ /dev/null
@@ -1,703 +0,0 @@
-/**
- * @author Andre Anjos <andre.anjos@idiap.ch>
- * @date Wed  6 Nov 21:44:34 2013
- *
- * @brief Bindings to bob::io::VideoReader
- */
-
-#define XBOB_IO_BASE_MODULE
-#include "bobskin.h"
-#include <xbob.io.base/api.h>
-
-#if WITH_FFMPEG
-#include <boost/make_shared.hpp>
-#include <numpy/arrayobject.h>
-#include <xbob.blitz/capi.h>
-#include <xbob.blitz/cleanup.h>
-#include <stdexcept>
-
-#define VIDEOREADER_NAME "VideoReader"
-PyDoc_STRVAR(s_videoreader_str, XBOB_EXT_MODULE_PREFIX "." VIDEOREADER_NAME);
-
-PyDoc_STRVAR(s_videoreader_doc,
-"VideoReader(filename, [check=True]) -> new bob::io::VideoReader\n\
-\n\
-Use this object to read frames from video files.\n\
-\n\
-Constructor parameters:\n\
-\n\
-filename\n\
-  [str] The file path to the file you want to read data from\n\
-\n\
-check\n\
-  [bool] Format and codec will be extracted from the video metadata.\n\
-  By default, if the format and/or the codec are not\n\
-  supported by this version of Bob, an exception will be raised.\n\
-  You can (at your own risk) set this flag to ``False`` to\n\
-  avoid this check.\n\
-\n\
-VideoReader objects can read data from video files. The current\n\
-implementation uses `FFmpeg <http://ffmpeg.org>`_ (or\n\
-`libav <http://libav.org>`_ if FFmpeg is not available) which is\n\
-a stable freely available video encoding and decoding library,\n\
-designed specifically for these tasks. You can read an entire\n\
-video in memory by using the :py:meth:`xbob.io.video.Reader.load`\n\
-method or use iterators to read it frame by frame and avoid\n\
-overloading your machine\'s memory. The maximum precision data\n\
-`FFmpeg`_ will yield is a 24-bit (8-bit per band) representation\n\
-of each pixel (32-bit depths are also supported by `FFmpeg`_, but\n\
-not by this extension presently). So, the output of data is done\n\
-with ``uint8`` as data type. Output will be colored using the RGB\n\
-standard, with each band varying between 0 and 255, with zero\n\
-meaning pure black and 255, pure white (color).\n\
-\n\
-");
-
-/* How to create a new PyBobIoVideoReaderObject */
-static PyObject* PyBobIoVideoReader_New(PyTypeObject* type, PyObject*, PyObject*) {
-
-  /* Allocates the python object itself */
-  PyBobIoVideoReaderObject* self = (PyBobIoVideoReaderObject*)type->tp_alloc(type, 0);
-
-  self->v.reset();
-
-  return reinterpret_cast<PyObject*>(self);
-}
-
-static void PyBobIoVideoReader_Delete (PyBobIoVideoReaderObject* o) {
-
-  o->v.reset();
-  Py_TYPE(o)->tp_free((PyObject*)o);
-
-}
-
-/* The __init__(self) method */
-static int PyBobIoVideoReader_Init(PyBobIoVideoReaderObject* self,
-    PyObject *args, PyObject* kwds) {
-
-  /* Parses input arguments in a single shot */
-  static const char* const_kwlist[] = {"filename", "check", 0};
-  static char** kwlist = const_cast<char**>(const_kwlist);
-
-  PyObject* filename = 0;
-
-  PyObject* pycheck = 0;
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O", kwlist,
-        &PyBobIo_FilenameConverter, &filename, &pycheck)) return -1;
-
-  auto filename_ = make_safe(filename);
-
-  bool check = false;
-  if (pycheck && PyObject_IsTrue(pycheck)) check = true;
-
-#if PY_VERSION_HEX >= 0x03000000
-  const char* c_filename = PyBytes_AS_STRING(filename);
-#else
-  const char* c_filename = PyString_AS_STRING(filename);
-#endif
-
-  try {
-    self->v = boost::make_shared<bob::io::VideoReader>(c_filename, check);
-  }
-  catch (std::exception& e) {
-    PyErr_SetString(PyExc_RuntimeError, e.what());
-    return -1;
-  }
-  catch (...) {
-    PyErr_Format(PyExc_RuntimeError, "cannot open video file `%s' for reading: unknown exception caught", c_filename);
-    return -1;
-  }
-
-  return 0; ///< SUCCESS
-}
-
-PyObject* PyBobIoVideoReader_Filename(PyBobIoVideoReaderObject* self) {
-  return Py_BuildValue("s", self->v->filename().c_str());
-}
-
-PyDoc_STRVAR(s_filename_str, "filename");
-PyDoc_STRVAR(s_filename_doc,
-"[str] The full path to the file that will be decoded by this object");
-
-PyObject* PyBobIoVideoReader_Height(PyBobIoVideoReaderObject* self) {
-  return Py_BuildValue("n", self->v->height());
-}
-
-PyDoc_STRVAR(s_height_str, "height");
-PyDoc_STRVAR(s_height_doc,
-"[int] The height of each frame in the video (a multiple of 2)");
-
-PyObject* PyBobIoVideoReader_Width(PyBobIoVideoReaderObject* self) {
-  return Py_BuildValue("n", self->v->width());
-}
-
-PyDoc_STRVAR(s_width_str, "width");
-PyDoc_STRVAR(s_width_doc,
-"[int] The width of each frame in the video (a multiple of 2)");
-
-PyObject* PyBobIoVideoReader_NumberOfFrames(PyBobIoVideoReaderObject* self) {
-  return Py_BuildValue("n", self->v->numberOfFrames());
-}
-
-PyDoc_STRVAR(s_number_of_frames_str, "number_of_frames");
-PyDoc_STRVAR(s_number_of_frames_doc,
-"[int] The number of frames in this video file");
-
-PyObject* PyBobIoVideoReader_Duration(PyBobIoVideoReaderObject* self) {
-  return Py_BuildValue("n", self->v->duration());
-}
-
-PyDoc_STRVAR(s_duration_str, "duration");
-PyDoc_STRVAR(s_duration_doc,
-"[int] Total duration of this video file in microseconds (long)");
-
-PyObject* PyBobIoVideoReader_FormatName(PyBobIoVideoReaderObject* self) {
-  return Py_BuildValue("s", self->v->formatName().c_str());
-}
-
-PyDoc_STRVAR(s_format_name_str, "format_name");
-PyDoc_STRVAR(s_format_name_doc,
-"[str] Short name of the format in which this video file was recorded in");
-
-PyObject* PyBobIoVideoReader_FormatLongName(PyBobIoVideoReaderObject* self) {
-  return Py_BuildValue("s", self->v->formatLongName().c_str());
-}
-
-PyDoc_STRVAR(s_format_long_name_str, "format_long_name");
-PyDoc_STRVAR(s_format_long_name_doc,
-"[str] Full name of the format in which this video file was recorded in");
-
-PyObject* PyBobIoVideoReader_CodecName(PyBobIoVideoReaderObject* self) {
-  return Py_BuildValue("s", self->v->codecName().c_str());
-}
-
-PyDoc_STRVAR(s_codec_name_str, "codec_name");
-PyDoc_STRVAR(s_codec_name_doc,
-"[str] Short name of the codec in which this video file was recorded in");
-
-PyObject* PyBobIoVideoReader_CodecLongName(PyBobIoVideoReaderObject* self) {
-  return Py_BuildValue("s", self->v->codecLongName().c_str());
-}
-
-PyDoc_STRVAR(s_codec_long_name_str, "codec_long_name");
-PyDoc_STRVAR(s_codec_long_name_doc,
-"[str] Full name of the codec in which this video file was recorded in");
-
-PyObject* PyBobIoVideoReader_FrameRate(PyBobIoVideoReaderObject* self) {
-  return PyFloat_FromDouble(self->v->frameRate());
-}
-
-PyDoc_STRVAR(s_frame_rate_str, "frame_rate");
-PyDoc_STRVAR(s_frame_rate_doc,
-"[float] Video's announced frame rate (note there are video formats with variable frame rates)");
-
-PyObject* PyBobIoVideoReader_VideoType(PyBobIoVideoReaderObject* self) {
-  return PyBobIo_TypeInfoAsTuple(self->v->video_type());
-}
-
-PyDoc_STRVAR(s_video_type_str, "video_type");
-PyDoc_STRVAR(s_video_type_doc,
-"[tuple] Typing information to load all of the file at once");
-
-PyObject* PyBobIoVideoReader_FrameType(PyBobIoVideoReaderObject* self) {
-  return PyBobIo_TypeInfoAsTuple(self->v->frame_type());
-}
-
-PyDoc_STRVAR(s_frame_type_str, "frame_type");
-PyDoc_STRVAR(s_frame_type_doc,
-"[tuple] Typing information to load each frame separatedly");
-
-static PyObject* PyBobIoVideoReader_Print(PyBobIoVideoReaderObject* self) {
-  return Py_BuildValue("s", self->v->info().c_str());
-}
-
-PyDoc_STRVAR(s_info_str, "info");
-PyDoc_STRVAR(s_info_doc,
-"[str] A string with lots of video information (same as ``str(x)``)");
-
-static PyGetSetDef PyBobIoVideoReader_getseters[] = {
-    {
-      s_filename_str,
-      (getter)PyBobIoVideoReader_Filename,
-      0,
-      s_filename_doc,
-      0,
-    },
-    {
-      s_height_str,
-      (getter)PyBobIoVideoReader_Height,
-      0,
-      s_height_doc,
-      0,
-    },
-    {
-      s_width_str,
-      (getter)PyBobIoVideoReader_Width,
-      0,
-      s_width_doc,
-      0,
-    },
-    {
-      s_number_of_frames_str,
-      (getter)PyBobIoVideoReader_NumberOfFrames,
-      0,
-      s_number_of_frames_doc,
-      0,
-    },
-    {
-      s_duration_str,
-      (getter)PyBobIoVideoReader_Duration,
-      0,
-      s_duration_doc,
-      0,
-    },
-    {
-      s_format_name_str,
-      (getter)PyBobIoVideoReader_FormatName,
-      0,
-      s_format_name_doc,
-      0,
-    },
-    {
-      s_format_long_name_str,
-      (getter)PyBobIoVideoReader_FormatLongName,
-      0,
-      s_format_long_name_doc,
-      0,
-    },
-    {
-      s_codec_name_str,
-      (getter)PyBobIoVideoReader_CodecName,
-      0,
-      s_codec_name_doc,
-      0,
-    },
-    {
-      s_codec_long_name_str,
-      (getter)PyBobIoVideoReader_CodecLongName,
-      0,
-      s_codec_long_name_doc,
-      0,
-    },
-    {
-      s_frame_rate_str,
-      (getter)PyBobIoVideoReader_FrameRate,
-      0,
-      s_frame_rate_doc,
-      0,
-    },
-    {
-      s_video_type_str,
-      (getter)PyBobIoVideoReader_VideoType,
-      0,
-      s_video_type_doc,
-      0,
-    },
-    {
-      s_frame_type_str,
-      (getter)PyBobIoVideoReader_FrameType,
-      0,
-      s_frame_type_doc,
-      0,
-    },
-    {
-      s_info_str,
-      (getter)PyBobIoVideoReader_Print,
-      0,
-      s_info_doc,
-      0,
-    },
-    {0}  /* Sentinel */
-};
-
-static PyObject* PyBobIoVideoReader_Repr(PyBobIoVideoReaderObject* self) {
-  return
-# if PY_VERSION_HEX >= 0x03000000
-  PyUnicode_FromFormat
-# else
-  PyString_FromFormat
-# endif
-  ("%s(filename='%s')", Py_TYPE(self)->tp_name, self->v->filename().c_str());
-}
-
-/**
- * If a keyboard interruption occurs, then it is translated into a C++
- * exception that makes the loop stops.
- */
-static void Check_Interrupt() {
-  if(PyErr_CheckSignals() == -1) {
-    if (!PyErr_Occurred()) PyErr_SetInterrupt();
-    throw std::runtime_error("error is already set");
-  }
-}
-
-static PyObject* PyBobIoVideoReader_Load(PyBobIoVideoReaderObject* self, PyObject *args, PyObject* kwds) {
-
-  /* Parses input arguments in a single shot */
-  static const char* const_kwlist[] = {"raise_on_error", 0};
-  static char** kwlist = const_cast<char**>(const_kwlist);
-
-  PyObject* raise = 0;
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &raise)) return 0;
-
-  bool raise_on_error = false;
-  if (raise && PyObject_IsTrue(raise)) raise_on_error = true;
-
-  const bob::core::array::typeinfo& info = self->v->video_type();
-
-  npy_intp shape[NPY_MAXDIMS];
-  for (size_t k=0; k<info.nd; ++k) shape[k] = info.shape[k];
-
-  int type_num = PyBobIo_AsTypenum(info.dtype);
-  if (type_num == NPY_NOTYPE) return 0; ///< failure
-
-  PyObject* retval = PyArray_SimpleNew(info.nd, shape, type_num);
-  if (!retval) return 0;
-  auto retval_ = make_safe(retval);
-
-  Py_ssize_t frames_read = 0;
-
-  try {
-    bobskin skin((PyArrayObject*)retval, info.dtype);
-    frames_read = self->v->load(skin, raise_on_error, &Check_Interrupt);
-  }
-  catch (std::exception& e) {
-    if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-    return 0;
-  }
-  catch (...) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading video from file `%s'", self->v->filename().c_str());
-    return 0;
-  }
-
-  if (frames_read != shape[0]) {
-    //resize
-    shape[0] = frames_read;
-    PyArray_Dims newshape;
-    newshape.ptr = shape;
-    newshape.len = info.nd;
-    PyArray_Resize((PyArrayObject*)retval, &newshape, 1, NPY_ANYORDER);
-  }
-
-  Py_INCREF(retval);
-  return retval;
-
-}
-
-PyDoc_STRVAR(s_load_str, "load");
-PyDoc_STRVAR(s_load_doc,
-"x.load([raise_on_error=False] -> numpy.ndarray\n\
-\n\
-Loads all of the video stream in a numpy ndarray organized\n\
-in this way: (frames, color-bands, height, width). I'll dynamically\n\
-allocate the output array and return it to you.\n\
-\n\
-The flag ``raise_on_error``, which is set to ``False`` by default\n\
-influences the error reporting in case problems are found with the\n\
-video file. If you set it to ``True``, we will report problems\n\
-raising exceptions. If you either don't set it or set it to\n\
-``False``, we will truncate the file at the frame with problems\n\
-and will not report anything. It is your task to verify if the\n\
-number of frames returned matches the expected number of frames as\n\
-reported by the property ``number_of_frames`` (or ``len``) of this\n\
-object.\n\
-");
-
-static PyMethodDef PyBobIoVideoReader_Methods[] = {
-    {
-      s_load_str,
-      (PyCFunction)PyBobIoVideoReader_Load,
-      METH_VARARGS|METH_KEYWORDS,
-      s_load_doc,
-    },
-    {0}  /* Sentinel */
-};
-
-static PyObject* PyBobIoVideoReader_GetIndex (PyBobIoVideoReaderObject* self, Py_ssize_t i) {
-
-  if (i < 0) i += self->v->numberOfFrames(); ///< adjust for negative indexing
-
-  if (i < 0 || (size_t)i >= self->v->numberOfFrames()) {
-    PyErr_Format(PyExc_IndexError, "video frame index out of range - `%s' only contains %" PY_FORMAT_SIZE_T "d frame(s)", self->v->filename().c_str(), self->v->numberOfFrames());
-    return 0;
-  }
-
-  const bob::core::array::typeinfo& info = self->v->frame_type();
-
-  npy_intp shape[NPY_MAXDIMS];
-  for (size_t k=0; k<info.nd; ++k) shape[k] = info.shape[k];
-
-  int type_num = PyBobIo_AsTypenum(info.dtype);
-  if (type_num == NPY_NOTYPE) return 0; ///< failure
-
-  PyObject* retval = PyArray_SimpleNew(info.nd, shape, type_num);
-  if (!retval) return 0;
-  auto retval_ = make_safe(retval);
-
-  try {
-    auto it = self->v->begin();
-    it += i;
-    bobskin skin((PyArrayObject*)retval, info.dtype);
-    it.read(skin);
-  }
-  catch (std::exception& e) {
-    if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-    return 0;
-  }
-  catch (...) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading frame #%" PY_FORMAT_SIZE_T "d from file `%s'", i, self->v->filename().c_str());
-    return 0;
-  }
-
-  Py_INCREF(retval);
-  return retval;
-
-}
-
-static PyObject* PyBobIoVideoReader_GetSlice (PyBobIoVideoReaderObject* self, PySliceObject* slice) {
-
-  Py_ssize_t start, stop, step, slicelength;
-#if PY_VERSION_HEX < 0x03000000
-  if (PySlice_GetIndicesEx(slice,
-#else
-  if (PySlice_GetIndicesEx(reinterpret_cast<PyObject*>(slice),
-#endif
-        self->v->numberOfFrames(), &start, &stop, &step, &slicelength) < 0) return 0;
-
-  //creates the return array
-  const bob::core::array::typeinfo& info = self->v->frame_type();
-
-  int type_num = PyBobIo_AsTypenum(info.dtype);
-  if (type_num == NPY_NOTYPE) return 0; ///< failure
-
-  if (slicelength <= 0) return PyArray_SimpleNew(0, 0, type_num);
-
-  npy_intp shape[NPY_MAXDIMS];
-  shape[0] = slicelength;
-  for (size_t k=0; k<info.nd; ++k) shape[k+1] = info.shape[k];
-
-  PyObject* retval = PyArray_SimpleNew(info.nd+1, shape, type_num);
-  if (!retval) return 0;
-  auto retval_ = make_safe(retval);
-
-  Py_ssize_t counter;
-  Py_ssize_t lo, hi, st;
-  auto it = self->v->begin();
-  if (start <= stop) {
-    lo = start, hi = stop, st = step;
-    it += lo, counter = 0;
-  }
-  else {
-    lo = stop, hi = start, st = -step;
-    it += lo + (hi-lo)%st, counter = slicelength - 1;
-  }
-
-  for (auto i=lo; i<hi; i+=st) {
-
-    //get slice to fill
-    PyObject* islice = Py_BuildValue("n", counter);
-    counter = (st == -step)? counter-1 : counter+1;
-    if (!islice) return 0;
-    auto islice_ = make_safe(islice);
-
-    PyObject* item = PyObject_GetItem(retval, islice);
-    if (!item) return 0;
-    auto item_ = make_safe(item);
-
-    try {
-      bobskin skin((PyArrayObject*)item, info.dtype);
-      it.read(skin);
-      it += (st-1);
-    }
-    catch (std::exception& e) {
-      if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-      return 0;
-    }
-    catch (...) {
-      if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading frame #%" PY_FORMAT_SIZE_T "d from file `%s'", i, self->v->filename().c_str());
-      return 0;
-    }
-
-  }
-
-  Py_INCREF(retval);
-  return retval;
-
-}
-
-static PyObject* PyBobIoVideoReader_GetItem (PyBobIoVideoReaderObject* self, PyObject* item) {
-   if (PyIndex_Check(item)) {
-     Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
-     if (i == -1 && PyErr_Occurred()) return 0;
-     return PyBobIoVideoReader_GetIndex(self, i);
-   }
-   if (PySlice_Check(item)) {
-     return PyBobIoVideoReader_GetSlice(self, (PySliceObject*)item);
-   }
-   else {
-     PyErr_Format(PyExc_TypeError, "VideoReader indices must be integers, not `%s'",
-         Py_TYPE(item)->tp_name);
-     return 0;
-   }
-}
-
-Py_ssize_t PyBobIoVideoReader_Len(PyBobIoVideoReaderObject* self) {
-  return self->v->numberOfFrames();
-}
-
-static PyMappingMethods PyBobIoVideoReader_Mapping = {
-    (lenfunc)PyBobIoVideoReader_Len, //mp_lenght
-    (binaryfunc)PyBobIoVideoReader_GetItem, //mp_subscript
-    0 /* (objobjargproc)PyBobIoVideoReader_SetItem //mp_ass_subscript */
-};
-
-/*****************************************
- * Definition of Iterator to VideoReader *
- *****************************************/
-
-#define VIDEOITERTYPE_NAME "VideoReader.iter"
-PyDoc_STRVAR(s_videoreaderiterator_str, XBOB_EXT_MODULE_PREFIX "." VIDEOITERTYPE_NAME);
-
-static PyObject* PyBobIoVideoReaderIterator_New(PyTypeObject* type, PyObject*, PyObject*) {
-
-  /* Allocates the python object itself */
-  PyBobIoVideoReaderIteratorObject* self = (PyBobIoVideoReaderIteratorObject*)type->tp_alloc(type, 0);
-
-  self->iter.reset();
-
-  return reinterpret_cast<PyObject*>(self);
-}
-
-static PyObject* PyBobIoVideoReaderIterator_Iter (PyBobIoVideoReaderIteratorObject* self) {
-  Py_INCREF(self);
-  return reinterpret_cast<PyObject*>(self);
-}
-
-static PyObject* PyBobIoVideoReaderIterator_Next (PyBobIoVideoReaderIteratorObject* self) {
-
-  if ((*self->iter == self->pyreader->v->end()) ||
-      (self->iter->cur() == self->pyreader->v->numberOfFrames())) {
-    self->iter->reset();
-    self->iter.reset();
-    Py_XDECREF((PyObject*)self->pyreader);
-    return 0;
-  }
-
-  const bob::core::array::typeinfo& info = self->pyreader->v->frame_type();
-
-  npy_intp shape[NPY_MAXDIMS];
-  for (size_t k=0; k<info.nd; ++k) shape[k] = info.shape[k];
-
-  int type_num = PyBobIo_AsTypenum(info.dtype);
-  if (type_num == NPY_NOTYPE) return 0; ///< failure
-
-  PyObject* retval = PyArray_SimpleNew(info.nd, shape, type_num);
-  if (!retval) return 0;
-  auto retval_ = make_safe(retval);
-
-  try {
-    bobskin skin((PyArrayObject*)retval, info.dtype);
-    self->iter->read(skin);
-  }
-  catch (std::exception& e) {
-    if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-    return 0;
-  }
-  catch (...) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading frame #%" PY_FORMAT_SIZE_T "d from file `%s'", self->iter->cur(), self->pyreader->v->filename().c_str());
-    return 0;
-  }
-
-  Py_INCREF(retval);
-  return retval;
-
-}
-
-#if PY_VERSION_HEX >= 0x03000000
-#  define Py_TPFLAGS_HAVE_ITER 0
-#endif
-
-PyTypeObject PyBobIoVideoReaderIterator_Type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    s_videoreaderiterator_str,                  /* tp_name */
-    sizeof(PyBobIoVideoReaderIteratorObject),   /* tp_basicsize */
-    0,                                          /* tp_itemsize */
-    0,                                          /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_compare */
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /* tp_flags */
-    0,                                          /* tp_doc */
-    0,		                                      /* tp_traverse */
-    0,		                                      /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,		                                      /* tp_weaklistoffset */
-    (getiterfunc)PyBobIoVideoReaderIterator_Iter,      /* tp_iter */
-    (iternextfunc)PyBobIoVideoReaderIterator_Next      /* tp_iternext */
-};
-
-static PyObject* PyBobIoVideoReader_Iter (PyBobIoVideoReaderObject* self) {
-
-  /* Allocates the python object itself */
-  PyBobIoVideoReaderIteratorObject* retval = (PyBobIoVideoReaderIteratorObject*)PyBobIoVideoReaderIterator_New(&PyBobIoVideoReaderIterator_Type, 0, 0);
-  if (!retval) return 0;
-
-  Py_INCREF(self);
-  retval->pyreader = self;
-  retval->iter.reset(new bob::io::VideoReader::const_iterator(self->v->begin()));
-  return reinterpret_cast<PyObject*>(retval);
-}
-
-PyTypeObject PyBobIoVideoReader_Type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    s_videoreader_str,                          /*tp_name*/
-    sizeof(PyBobIoVideoReaderObject),           /*tp_basicsize*/
-    0,                                          /*tp_itemsize*/
-    (destructor)PyBobIoVideoReader_Delete,      /*tp_dealloc*/
-    0,                                          /*tp_print*/
-    0,                                          /*tp_getattr*/
-    0,                                          /*tp_setattr*/
-    0,                                          /*tp_compare*/
-    (reprfunc)PyBobIoVideoReader_Repr,          /*tp_repr*/
-    0,                                          /*tp_as_number*/
-    0,                                          /*tp_as_sequence*/
-    &PyBobIoVideoReader_Mapping,                /*tp_as_mapping*/
-    0,                                          /*tp_hash */
-    0,                                          /*tp_call*/
-    (reprfunc)PyBobIoVideoReader_Print,         /*tp_str*/
-    0,                                          /*tp_getattro*/
-    0,                                          /*tp_setattro*/
-    0,                                          /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /*tp_flags*/
-    s_videoreader_doc,                          /* tp_doc */
-    0,		                                      /* tp_traverse */
-    0,		                                      /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,		                                      /* tp_weaklistoffset */
-    (getiterfunc)PyBobIoVideoReader_Iter,       /* tp_iter */
-    0,		                                      /* tp_iternext */
-    PyBobIoVideoReader_Methods,                 /* tp_methods */
-    0,                                          /* tp_members */
-    PyBobIoVideoReader_getseters,               /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    (initproc)PyBobIoVideoReader_Init,          /* tp_init */
-    0,                                          /* tp_alloc */
-    PyBobIoVideoReader_New,                     /* tp_new */
-};
-
-#endif /* WITH_FFMPEG */
diff --git a/xbob/io/base/videowriter.cpp b/xbob/io/base/videowriter.cpp
deleted file mode 100644
index 2261774c6fb39627f6659c13085c92f1689dedd7..0000000000000000000000000000000000000000
--- a/xbob/io/base/videowriter.cpp
+++ /dev/null
@@ -1,589 +0,0 @@
-/**
- * @author Andre Anjos <andre.anjos@idiap.ch>
- * @date Wed  6 Nov 21:44:34 2013
- *
- * @brief Bindings to bob::io::VideoWriter
- */
-
-#define XBOB_IO_BASE_MODULE
-#include "bobskin.h"
-#include <xbob.io.base/api.h>
-
-#if WITH_FFMPEG
-#include <boost/make_shared.hpp>
-#include <numpy/arrayobject.h>
-#include <xbob.blitz/cppapi.h>
-#include <xbob.blitz/cleanup.h>
-#include <stdexcept>
-
-#define VIDEOWRITER_NAME "VideoWriter"
-PyDoc_STRVAR(s_videowriter_str, XBOB_EXT_MODULE_PREFIX "." VIDEOWRITER_NAME);
-
-PyDoc_STRVAR(s_videowriter_doc,
-"VideoWriter(filename, height, width, [framerate=25., [bitrate=1500000., [gop=12, [codec='', [format='', [check=True]) -> new bob::io::VideoWriter\n\
-\n\
-Use this object to write frames to video files.\n\
-\n\
-Constructor parameters:\n\
-\n\
-filename\n\
-  [str] The file path to the file you want to read data from\n\
-\n\
-height\n\
-  [int] The height of the video (must be a multiple of 2)\n\
-\n\
-width\n\
-  [int] The width of the video (must be a multiple of 2)\n\
-\n\
-framerate\n\
-  [float, optional] The number of frames per second\n\
-\n\
-bitrate\n\
-  [float, optional] The estimated bitrate of the output video\n\
-\n\
-gop\n\
-  [int, optional] Group-of-Pictures (emit one intra frame\n\
-  every ``gop`` frames at most).\n\
-\n\
-codec\n\
-  [str, optional] If you must, specify a valid FFmpeg codec\n\
-  name here and that will be used to encode the video stream\n\
-  on the output file.\n\
-\n\
-format\n\
-  [str, optional] If you must, specify a valid FFmpeg output\n\
-  format name and that will be used to encode the video on the\n\
-  output file. Leave it empty to guess from the filename extension.\n\
-\n\
-check\n\
-  [bool, optional] The video will be created if the combination\n\
-  of format and codec are known to work and have been tested,\n\
-  otherwise an exception is raised. If you set this parameter to\n\
-  ``False``, though, we will ignore this check.\n\
-\n\
-VideoWriter objects can write data to video files. The current\n\
-implementation uses `FFmpeg <http://ffmpeg.org>`_ (or\n\
-`libav <http://libav.org>`_ if FFmpeg is not available) which is\n\
-a stable freely available video encoding and decoding library,\n\
-designed specifically for these tasks. Videos are objects composed\n\
-of RGB colored frames. Each frame inserted should be a 3D\n\
-:py:class:`numpy.ndarray` composed of unsigned integers of 8 bits.\n\
-Each frame should have a shape equivalent to\n\
-``(plane, height, width)``.\n\
-");
-
-/* How to create a new PyBobIoVideoWriterObject */
-static PyObject* PyBobIoVideoWriter_New(PyTypeObject* type, PyObject*, PyObject*) {
-
-  /* Allocates the python object itself */
-  PyBobIoVideoWriterObject* self = (PyBobIoVideoWriterObject*)type->tp_alloc(type, 0);
-
-  self->v.reset();
-
-  return reinterpret_cast<PyObject*>(self);
-}
-
-static void PyBobIoVideoWriter_Delete (PyBobIoVideoWriterObject* o) {
-
-  o->v.reset();
-  Py_TYPE(o)->tp_free((PyObject*)o);
-
-}
-
-/* The __init__(self) method */
-static int PyBobIoVideoWriter_Init(PyBobIoVideoWriterObject* self,
-    PyObject *args, PyObject* kwds) {
-
-  /* Parses input arguments in a single shot */
-  static const char* const_kwlist[] = {
-    "filename", "height", "width", //mandatory
-    "framerate", "bitrate", "gop", "codec", "format", "check",  //optional
-    0};
-  static char** kwlist = const_cast<char**>(const_kwlist);
-
-  PyObject* filename = 0;
-
-  Py_ssize_t height = 0;
-  Py_ssize_t width = 0;
-
-  double framerate = 25.;
-  double bitrate = 1500000.;
-  Py_ssize_t gop = 12;
-  char* codec = 0;
-  char* format = 0;
-  PyObject* pycheck = Py_True;
-
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&nn|ddnssO", kwlist,
-        &PyBobIo_FilenameConverter, &filename,
-        &height, &width, &framerate, &bitrate, &gop, &codec,
-        &format, &pycheck)) return -1;
-
-  auto filename_ = make_safe(filename);
-
-  std::string codec_str = codec?codec:"";
-  std::string format_str = format?format:"";
-  bool check = PyObject_IsTrue(pycheck);
-
-#if PY_VERSION_HEX >= 0x03000000
-  const char* c_filename = PyBytes_AS_STRING(filename);
-#else
-  const char* c_filename = PyString_AS_STRING(filename);
-#endif
-
-  try {
-    self->v = boost::make_shared<bob::io::VideoWriter>(c_filename,
-        height, width, framerate, bitrate, gop, codec_str, format_str, check);
-  }
-  catch (std::exception& e) {
-    PyErr_SetString(PyExc_RuntimeError, e.what());
-    return -1;
-  }
-  catch (...) {
-    PyErr_Format(PyExc_RuntimeError, "cannot open video file `%s' for writing: unknown exception caught", c_filename);
-    return -1;
-  }
-
-  return 0; ///< SUCCESS
-}
-
-PyObject* PyBobIoVideoWriter_Filename(PyBobIoVideoWriterObject* self) {
-  return Py_BuildValue("s", self->v->filename().c_str());
-}
-
-PyDoc_STRVAR(s_filename_str, "filename");
-PyDoc_STRVAR(s_filename_doc,
-"[str] The full path to the file that will be decoded by this object");
-
-PyObject* PyBobIoVideoWriter_Height(PyBobIoVideoWriterObject* self) {
-  return Py_BuildValue("n", self->v->height());
-}
-
-PyDoc_STRVAR(s_height_str, "height");
-PyDoc_STRVAR(s_height_doc,
-"[int] The height of each frame in the video (a multiple of 2)");
-
-PyObject* PyBobIoVideoWriter_Width(PyBobIoVideoWriterObject* self) {
-  return Py_BuildValue("n", self->v->width());
-}
-
-PyDoc_STRVAR(s_width_str, "width");
-PyDoc_STRVAR(s_width_doc,
-"[int] The width of each frame in the video (a multiple of 2)");
-
-PyObject* PyBobIoVideoWriter_NumberOfFrames(PyBobIoVideoWriterObject* self) {
-  return Py_BuildValue("n", self->v->numberOfFrames());
-}
-
-PyDoc_STRVAR(s_number_of_frames_str, "number_of_frames");
-PyDoc_STRVAR(s_number_of_frames_doc,
-"[int] The number of frames in this video file");
-
-PyObject* PyBobIoVideoWriter_Duration(PyBobIoVideoWriterObject* self) {
-  return Py_BuildValue("n", self->v->duration());
-}
-
-PyDoc_STRVAR(s_duration_str, "duration");
-PyDoc_STRVAR(s_duration_doc,
-"[int] Total duration of this video file in microseconds (long)");
-
-PyObject* PyBobIoVideoWriter_FormatName(PyBobIoVideoWriterObject* self) {
-  if (!self->v->is_opened()) {
-    PyErr_Format(PyExc_RuntimeError, "`%s' for `%s' is closed",
-        Py_TYPE(self)->tp_name, self->v->filename().c_str());
-    return 0;
-  }
-  return Py_BuildValue("s", self->v->formatName().c_str());
-}
-
-PyDoc_STRVAR(s_format_name_str, "format_name");
-PyDoc_STRVAR(s_format_name_doc,
-"[str] Short name of the format in which this video file was recorded in");
-
-PyObject* PyBobIoVideoWriter_FormatLongName(PyBobIoVideoWriterObject* self) {
-  if (!self->v->is_opened()) {
-    PyErr_Format(PyExc_RuntimeError, "`%s' for `%s' is closed",
-        Py_TYPE(self)->tp_name, self->v->filename().c_str());
-    return 0;
-  }
-  return Py_BuildValue("s", self->v->formatLongName().c_str());
-}
-
-PyDoc_STRVAR(s_format_long_name_str, "format_long_name");
-PyDoc_STRVAR(s_format_long_name_doc,
-"[str] Full name of the format in which this video file was recorded in");
-
-PyObject* PyBobIoVideoWriter_CodecName(PyBobIoVideoWriterObject* self) {
-  if (!self->v->is_opened()) {
-    PyErr_Format(PyExc_RuntimeError, "`%s' for `%s' is closed",
-        Py_TYPE(self)->tp_name, self->v->filename().c_str());
-    return 0;
-  }
-  return Py_BuildValue("s", self->v->codecName().c_str());
-}
-
-PyDoc_STRVAR(s_codec_name_str, "codec_name");
-PyDoc_STRVAR(s_codec_name_doc,
-"[str] Short name of the codec in which this video file was recorded in");
-
-PyObject* PyBobIoVideoWriter_CodecLongName(PyBobIoVideoWriterObject* self) {
-  if (!self->v->is_opened()) {
-    PyErr_Format(PyExc_RuntimeError, "`%s' for `%s' is closed",
-        Py_TYPE(self)->tp_name, self->v->filename().c_str());
-    return 0;
-  }
-  return Py_BuildValue("s", self->v->codecLongName().c_str());
-}
-
-PyDoc_STRVAR(s_codec_long_name_str, "codec_long_name");
-PyDoc_STRVAR(s_codec_long_name_doc,
-"[str] Full name of the codec in which this video file was recorded in");
-
-PyObject* PyBobIoVideoWriter_FrameRate(PyBobIoVideoWriterObject* self) {
-  return PyFloat_FromDouble(self->v->frameRate());
-}
-
-PyDoc_STRVAR(s_frame_rate_str, "frame_rate");
-PyDoc_STRVAR(s_frame_rate_doc,
-"[float] Video's announced frame rate (note there are video formats\n\
-with variable frame rates)");
-
-PyObject* PyBobIoVideoWriter_BitRate(PyBobIoVideoWriterObject* self) {
-  return PyFloat_FromDouble(self->v->bitRate());
-}
-
-PyDoc_STRVAR(s_bit_rate_str, "bit_rate");
-PyDoc_STRVAR(s_bit_rate_doc,
-"[float] The indicative bit rate for this video file, given as a\n\
-hint to `FFmpeg` (compression levels are subject to the picture\n\
-textures)");
-
-PyObject* PyBobIoVideoWriter_GOP(PyBobIoVideoWriterObject* self) {
-  return Py_BuildValue("n", self->v->gop());
-}
-
-PyDoc_STRVAR(s_gop_str, "gop");
-PyDoc_STRVAR(s_gop_doc,
-"[int] Group of pictures setting (see the `Wikipedia entry\n\
-<http://en.wikipedia.org/wiki/Group_of_pictures>`_ for details\n\
-on this setting)");
-
-PyObject* PyBobIoVideoWriter_VideoType(PyBobIoVideoWriterObject* self) {
-  return PyBobIo_TypeInfoAsTuple(self->v->video_type());
-}
-
-PyDoc_STRVAR(s_video_type_str, "video_type");
-PyDoc_STRVAR(s_video_type_doc,
-"[tuple] Typing information to load all of the file at once");
-
-PyObject* PyBobIoVideoWriter_FrameType(PyBobIoVideoWriterObject* self) {
-  return PyBobIo_TypeInfoAsTuple(self->v->frame_type());
-}
-
-PyDoc_STRVAR(s_frame_type_str, "frame_type");
-PyDoc_STRVAR(s_frame_type_doc,
-"[tuple] Typing information to load each frame separatedly");
-
-static PyObject* PyBobIoVideoWriter_Print(PyBobIoVideoWriterObject* self) {
-  if (!self->v->is_opened()) {
-    PyErr_Format(PyExc_RuntimeError, "`%s' for `%s' is closed",
-        Py_TYPE(self)->tp_name, self->v->filename().c_str());
-    return 0;
-  }
-
-  return Py_BuildValue("s", self->v->info().c_str());
-}
-
-PyDoc_STRVAR(s_info_str, "info");
-PyDoc_STRVAR(s_info_doc,
-"[str] A string with lots of video information (same as ``str(x)``)");
-
-static PyObject* PyBobIoVideoWriter_IsOpened(PyBobIoVideoWriterObject* self) {
-  if (self->v->is_opened()) Py_RETURN_TRUE;
-  Py_RETURN_FALSE;
-}
-
-PyDoc_STRVAR(s_is_opened_str, "is_opened");
-PyDoc_STRVAR(s_is_opened_doc,
-"[bool] A flag, indicating if the video is still opened for writing\n\
-(or has already been closed by the user using ``close()``)");
-
-static PyGetSetDef PyBobIoVideoWriter_getseters[] = {
-    {
-      s_filename_str,
-      (getter)PyBobIoVideoWriter_Filename,
-      0,
-      s_filename_doc,
-      0,
-    },
-    {
-      s_height_str,
-      (getter)PyBobIoVideoWriter_Height,
-      0,
-      s_height_doc,
-      0,
-    },
-    {
-      s_width_str,
-      (getter)PyBobIoVideoWriter_Width,
-      0,
-      s_width_doc,
-      0,
-    },
-    {
-      s_number_of_frames_str,
-      (getter)PyBobIoVideoWriter_NumberOfFrames,
-      0,
-      s_number_of_frames_doc,
-      0,
-    },
-    {
-      s_duration_str,
-      (getter)PyBobIoVideoWriter_Duration,
-      0,
-      s_duration_doc,
-      0,
-    },
-    {
-      s_format_name_str,
-      (getter)PyBobIoVideoWriter_FormatName,
-      0,
-      s_format_name_doc,
-      0,
-    },
-    {
-      s_format_long_name_str,
-      (getter)PyBobIoVideoWriter_FormatLongName,
-      0,
-      s_format_long_name_doc,
-      0,
-    },
-    {
-      s_codec_name_str,
-      (getter)PyBobIoVideoWriter_CodecName,
-      0,
-      s_codec_name_doc,
-      0,
-    },
-    {
-      s_codec_long_name_str,
-      (getter)PyBobIoVideoWriter_CodecLongName,
-      0,
-      s_codec_long_name_doc,
-      0,
-    },
-    {
-      s_frame_rate_str,
-      (getter)PyBobIoVideoWriter_FrameRate,
-      0,
-      s_frame_rate_doc,
-      0,
-    },
-    {
-      s_bit_rate_str,
-      (getter)PyBobIoVideoWriter_BitRate,
-      0,
-      s_bit_rate_doc,
-      0,
-    },
-    {
-      s_gop_str,
-      (getter)PyBobIoVideoWriter_GOP,
-      0,
-      s_gop_doc,
-      0,
-    },
-    {
-      s_video_type_str,
-      (getter)PyBobIoVideoWriter_VideoType,
-      0,
-      s_video_type_doc,
-      0,
-    },
-    {
-      s_frame_type_str,
-      (getter)PyBobIoVideoWriter_FrameType,
-      0,
-      s_frame_type_doc,
-      0,
-    },
-    {
-      s_info_str,
-      (getter)PyBobIoVideoWriter_Print,
-      0,
-      s_info_doc,
-      0,
-    },
-    {
-      s_is_opened_str,
-      (getter)PyBobIoVideoWriter_IsOpened,
-      0,
-      s_is_opened_doc,
-      0,
-    },
-    {0}  /* Sentinel */
-};
-
-static PyObject* PyBobIoVideoWriter_Repr(PyBobIoVideoWriterObject* self) {
-  if (!self->v->is_opened()) {
-    PyErr_Format(PyExc_RuntimeError, "`%s' for `%s' is closed",
-        Py_TYPE(self)->tp_name, self->v->filename().c_str());
-    return 0;
-  }
-
-  return
-# if PY_VERSION_HEX >= 0x03000000
-  PyUnicode_FromFormat
-# else
-  PyString_FromFormat
-# endif
-  ("%s(filename='%s', height=%" PY_FORMAT_SIZE_T "d, width=%" PY_FORMAT_SIZE_T "d, framerate=%g, bitrate=%g, gop=%" PY_FORMAT_SIZE_T "d, codec='%s', format='%s')", Py_TYPE(self)->tp_name, self->v->filename().c_str(), self->v->height(), self->v->width(), self->v->frameRate(), self->v->bitRate(), self->v->gop(), self->v->codecName().c_str(), self->v->formatName().c_str());
-}
-
-static PyObject* PyBobIoVideoWriter_Append(PyBobIoVideoWriterObject* self, PyObject *args, PyObject* kwds) {
-
-  if (!self->v->is_opened()) {
-    PyErr_Format(PyExc_RuntimeError, "`%s' for `%s' is closed",
-        Py_TYPE(self)->tp_name, self->v->filename().c_str());
-    return 0;
-  }
-
-  /* Parses input arguments in a single shot */
-  static const char* const_kwlist[] = {"frame", 0};
-  static char** kwlist = const_cast<char**>(const_kwlist);
-
-  PyBlitzArrayObject* frame = 0;
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kwlist, &PyBlitzArray_BehavedConverter, &frame)) return 0;
-  auto frame_ = make_safe(frame);
-
-  if (frame->ndim != 3 && frame->ndim != 4) {
-    PyErr_Format(PyExc_ValueError, "input array should have 3 or 4 dimensions, but you passed an array with %" PY_FORMAT_SIZE_T "d dimensions", frame->ndim);
-    return 0;
-  }
-
-  if (frame->type_num != NPY_UINT8) {
-    PyErr_Format(PyExc_TypeError, "input array should have dtype `uint8', but you passed an array with dtype == `%s'", PyBlitzArray_TypenumAsString(frame->type_num));
-    return 0;
-  }
-
-  try {
-    if (frame->ndim == 3) {
-      self->v->append(*PyBlitzArrayCxx_AsBlitz<uint8_t,3>(frame));
-    }
-    else {
-      self->v->append(*PyBlitzArrayCxx_AsBlitz<uint8_t,4>(frame));
-    }
-  }
-  catch (std::exception& e) {
-    if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-    return 0;
-  }
-  catch (...) {
-    if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while writing frame #%" PY_FORMAT_SIZE_T "d to file `%s'", self->v->numberOfFrames(), self->v->filename().c_str());
-    return 0;
-  }
-
-  Py_RETURN_NONE;
-
-}
-
-PyDoc_STRVAR(s_append_str, "append");
-PyDoc_STRVAR(s_append_doc,
-"x.append(frame) -> None\n\
-\n\
-Writes a new frame or set of frames to the file.\n\
-\n\
-The frame should be setup as a array with 3 dimensions organized\n\
-in this way (RGB color-bands, height, width). Sets of frames should\n\
-be setup as a 4D array in this way: (frame-number, RGB color-bands,\n\
-height, width). Arrays should contain only unsigned integers of 8\n\
-bits.\n\
-\n\
-.. note::\n\
-  At present time we only support arrays that have C-style storages\n\
-  (if you pass reversed arrays or arrays with Fortran-style storage,\n\
-  the result is undefined).\n\
-\n\
-");
-
-static PyObject* PyBobIoVideoWriter_Close(PyBobIoVideoWriterObject* self) {
-  self->v->close();
-  Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(s_close_str, "close");
-PyDoc_STRVAR(s_close_doc,
-"x.close() -> None\n\
-\n\
-Closes the current video stream and forces writing the trailer.\n\
-After this point the video is finalized and cannot be written to\n\
-anymore.\n\
-");
-
-static PyMethodDef PyBobIoVideoWriter_Methods[] = {
-    {
-      s_append_str,
-      (PyCFunction)PyBobIoVideoWriter_Append,
-      METH_VARARGS|METH_KEYWORDS,
-      s_append_doc,
-    },
-    {
-      s_close_str,
-      (PyCFunction)PyBobIoVideoWriter_Close,
-      METH_NOARGS,
-      s_close_doc,
-    },
-    {0}  /* Sentinel */
-};
-
-Py_ssize_t PyBobIoVideoWriter_Len(PyBobIoVideoWriterObject* self) {
-  return self->v->numberOfFrames();
-}
-
-static PyMappingMethods PyBobIoVideoWriter_Mapping = {
-    (lenfunc)PyBobIoVideoWriter_Len, //mp_lenght
-    0, /* (binaryfunc)PyBobIoVideoWriter_GetItem, //mp_subscript */
-    0  /* (objobjargproc)PyBobIoVideoWriter_SetItem //mp_ass_subscript */
-};
-
-PyTypeObject PyBobIoVideoWriter_Type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    s_videowriter_str,                          /*tp_name*/
-    sizeof(PyBobIoVideoWriterObject),           /*tp_basicsize*/
-    0,                                          /*tp_itemsize*/
-    (destructor)PyBobIoVideoWriter_Delete,      /*tp_dealloc*/
-    0,                                          /*tp_print*/
-    0,                                          /*tp_getattr*/
-    0,                                          /*tp_setattr*/
-    0,                                          /*tp_compare*/
-    (reprfunc)PyBobIoVideoWriter_Repr,          /*tp_repr*/
-    0,                                          /*tp_as_number*/
-    0,                                          /*tp_as_sequence*/
-    &PyBobIoVideoWriter_Mapping,                /*tp_as_mapping*/
-    0,                                          /*tp_hash */
-    0,                                          /*tp_call*/
-    (reprfunc)PyBobIoVideoWriter_Print,         /*tp_str*/
-    0,                                          /*tp_getattro*/
-    0,                                          /*tp_setattro*/
-    0,                                          /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /*tp_flags*/
-    s_videowriter_doc,                          /* tp_doc */
-    0,		                                      /* tp_traverse */
-    0,		                                      /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,		                                      /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,		                                      /* tp_iternext */
-    PyBobIoVideoWriter_Methods,                 /* tp_methods */
-    0,                                          /* tp_members */
-    PyBobIoVideoWriter_getseters,               /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    (initproc)PyBobIoVideoWriter_Init,          /* tp_init */
-    0,                                          /* tp_alloc */
-    PyBobIoVideoWriter_New,                     /* tp_new */
-};
-
-#endif /* WITH_FFMPEG */