Commit 558c3c11 authored by André Anjos's avatar André Anjos 💬
Browse files

Package compiling; All tests passing

parent ec01a239
......@@ -16,3 +16,4 @@ dist
build
*.egg
src/
opsnr.stt
......@@ -60,6 +60,7 @@ setup(
"xbob/io/video/cpp/utils.cpp",
"xbob/io/video/cpp/reader.cpp",
"xbob/io/video/cpp/writer.cpp",
"xbob/io/video/bobskin.cpp",
"xbob/io/video/reader.cpp",
"xbob/io/video/writer.cpp",
"xbob/io/video/file.cpp",
......@@ -74,7 +75,7 @@ setup(
entry_points={
'console_scripts': [
'xbob_video_test.py = xbob.io.script.video_test:main',
'xbob_video_test.py = xbob.io.video.script.video_test:main',
],
},
......
from ._library import reader, writer
from ._library import *
from . import version
from .version import module as __version__
......
/**
* @author Andre Anjos <andre.anjos@idiap.ch>
* @date Wed 6 Nov 07:57:57 2013
*
* @brief Implementation of our bobskin class
*/
#include "bobskin.h"
#include <stdexcept>
bobskin::bobskin(PyArrayObject* array, bob::core::array::ElementType eltype) {
m_type.set<npy_intp>(eltype, PyArray_NDIM((PyArrayObject*)array),
PyArray_DIMS((PyArrayObject*)array),
PyArray_STRIDES((PyArrayObject*)array));
m_ptr = PyArray_DATA((PyArrayObject*)array);
}
bobskin::~bobskin() { }
void bobskin::set(const interface&) {
PyErr_SetString(PyExc_NotImplementedError, "setting C++ bobskin with (const interface&) is not implemented - DEBUG ME!");
throw std::runtime_error("error is already set");
}
void bobskin::set(boost::shared_ptr<interface>) {
PyErr_SetString(PyExc_NotImplementedError, "setting C++ bobskin with (boost::shared_ptr<interface>) is not implemented - DEBUG ME!");
throw std::runtime_error("error is already set");
}
void bobskin::set (const bob::core::array::typeinfo&) {
PyErr_SetString(PyExc_NotImplementedError, "setting C++ bobskin with (const typeinfo&) implemented - DEBUG ME!");
throw std::runtime_error("error is already set");
}
boost::shared_ptr<void> bobskin::owner() {
PyErr_SetString(PyExc_NotImplementedError, "acquiring non-const owner from C++ bobskin is not implemented - DEBUG ME!");
throw std::runtime_error("error is already set");
}
boost::shared_ptr<const void> bobskin::owner() const {
PyErr_SetString(PyExc_NotImplementedError, "acquiring const owner from C++ bobskin is not implemented - DEBUG ME!");
throw std::runtime_error("error is already set");
}
/**
* @author Andre Anjos <andre.anjos@idiap.ch>
* @date Tue 5 Nov 22:09:07 2013
*
* @brief A pythonic version of bob::core::array::interface, with minimal
* functionality.
*/
#ifndef PYTHON_BOB_IO_BOBSKIN_H
#define PYTHON_BOB_IO_BOBSKIN_H
#include <Python.h>
#include <bob/core/array.h>
extern "C" {
#include <xbob.blitz/capi.h>
}
/**
* Wraps a PyArrayObject such that we can access it from bob::io
*/
class bobskin: public bob::core::array::interface {
public: //api
/**
* @brief Builds a new skin from a numpy array object
*/
bobskin(PyArrayObject* array, bob::core::array::ElementType eltype);
/**
* @brief By default, the interface is never freed. You must override
* this method to do something special for your class type.
*/
virtual ~bobskin();
/**
* @brief Copies the data from another interface.
*/
virtual void set(const interface& other);
/**
* @brief Refers to the data of another interface.
*/
virtual void set(boost::shared_ptr<interface> other);
/**
* @brief Re-allocates this interface taking into consideration new
* requirements. The internal memory should be considered uninitialized.
*/
virtual void set (const bob::core::array::typeinfo& req);
/**
* @brief Type information for this interface.
*/
virtual const bob::core::array::typeinfo& type() const { return m_type; }
/**
* @brief Borrows a reference from the underlying memory. This means
* this object continues to be responsible for deleting the memory and
* you should make sure that it outlives the usage of the returned
* pointer.
*/
virtual void* ptr() { return m_ptr; }
virtual const void* ptr() const { return m_ptr; }
/**
* @brief Returns a representation of the internal cache using shared
* pointers.
*/
virtual boost::shared_ptr<void> owner();
virtual boost::shared_ptr<const void> owner() const;
private: //representation
bob::core::array::typeinfo m_type; ///< type information
void* m_ptr; ///< pointer to the data
};
#endif /* PYTHON_BOB_IO_BOBSKIN_H */
......@@ -23,7 +23,7 @@
#define AV_PIX_FMT_RGB24 PIX_FMT_RGB24
#endif
namespace bob::io::video {
namespace bob { namespace io { namespace video {
Reader::Reader(const std::string& filename, bool check) {
open(filename, check);
......
This diff is collapsed.
......@@ -30,19 +30,19 @@ class VideoFile: public bob::io::File {
m_newfile(true) {
if (mode == 'r') {
m_reader = boost::make_shared<bob::io::VideoReader>(m_filename);
m_reader = boost::make_shared<bob::io::video::Reader>(m_filename);
m_newfile = false;
}
else if (mode == 'a' && boost::filesystem::exists(path)) {
// to be able to append must load all data and save in VideoWriter
m_reader = boost::make_shared<bob::io::VideoReader>(m_filename);
// to be able to append must load all data and save in video::Writer
m_reader = boost::make_shared<bob::io::video::Reader>(m_filename);
bob::core::array::blitz_array data(m_reader->video_type());
m_reader->load(data);
size_t height = m_reader->height();
size_t width = m_reader->width();
m_reader.reset(); ///< cleanup before truncating the file
m_writer =
boost::make_shared<bob::io::VideoWriter>(m_filename, height, width);
boost::make_shared<bob::io::video::Writer>(m_filename, height, width);
m_writer->append(data); ///< we are now ready to append
m_newfile = false;
}
......@@ -54,8 +54,8 @@ class VideoFile: public bob::io::File {
virtual ~VideoFile() { }
virtual const std::string& filename() const {
return m_filename;
virtual const char* filename() const {
return m_filename.c_str();
}
virtual const bob::core::array::typeinfo& type_all() const {
......@@ -70,8 +70,8 @@ class VideoFile: public bob::io::File {
return (m_reader)? 1:(!m_newfile);
}
virtual const std::string& name() const {
return s_codecname;
virtual const char* name() const {
return s_codecname.c_str();
}
virtual void read_all(bob::core::array::interface& buffer) {
......@@ -102,7 +102,7 @@ class VideoFile: public bob::io::File {
if(m_newfile) {
size_t height = (type.nd==3)? type.shape[1]:type.shape[2];
size_t width = (type.nd==3)? type.shape[2]:type.shape[3];
m_writer = boost::make_shared<bob::io::VideoWriter>(m_filename, height, width);
m_writer = boost::make_shared<bob::io::video::Writer>(m_filename, height, width);
}
if(!m_writer)
......@@ -121,8 +121,8 @@ class VideoFile: public bob::io::File {
private: //representation
std::string m_filename;
bool m_newfile;
boost::shared_ptr<bob::io::VideoReader> m_reader;
boost::shared_ptr<bob::io::VideoWriter> m_writer;
boost::shared_ptr<bob::io::video::Reader> m_reader;
boost::shared_ptr<bob::io::video::Writer> m_writer;
static std::string s_codecname;
......@@ -159,49 +159,3 @@ std::string VideoFile::s_codecname = "bob.video";
boost::shared_ptr<bob::io::File> make_file (const char* path, char mode) {
return boost::make_shared<VideoFile>(path, mode);
}
/**
* Arranges a listing of input and output file formats
*/
static void list_formats(std::map<std::string, std::string>& formats) {
std::map<std::string, AVInputFormat*> iformat;
bob::io::detail::ffmpeg::iformats_supported(iformat);
std::map<std::string, AVOutputFormat*> oformat;
bob::io::detail::ffmpeg::oformats_supported(oformat);
for (auto k=iformat.begin(); k!=iformat.end(); ++k) {
auto o=oformat.find(k->first);
if (o!=oformat.end()) {
//format can be used for input and output
std::vector<std::string> extensions;
bob::io::detail::ffmpeg::tokenize_csv(o->second->extensions, extensions);
for (auto e=extensions.begin(); e!=extensions.end(); ++e) {
std::string key = ".";
key += *e;
std::string value = k->second->long_name;
value += " (video/ffmpeg)";
formats[key] = value;
}
}
}
}
/**
* Takes care of codec registration per se.
*/
static bool register_codec() {
boost::shared_ptr<bob::io::CodecRegistry> instance =
bob::io::CodecRegistry::instance();
std::map<std::string, std::string> formats;
list_formats(formats);
for (auto k=formats.begin(); k!=formats.end(); ++k) {
if (!instance->isRegistered(k->first)) {
instance->registerExtension(k->first, k->second, &make_file);
}
}
return true;
}
static bool codec_registered = register_codec();
......@@ -14,6 +14,7 @@
#include <xbob.io.base/api.h>
#include "file.h"
#include "cpp/utils.h"
extern "C" {
......@@ -25,12 +26,101 @@ extern "C" {
#endif
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
#if !HAVE_FFMPEG_AVCODEC_AVCODECID
#if LIBAVCODEC_VERSION_INT < 0x363b64 //54.59.100 @ ffmpeg-1.0
# define AVCodecID CodecID
#endif
}
static int dict_set(PyObject* d, const char* key, const char* value) {
PyObject* v = Py_BuildValue("s", value);
if (!v) return 0;
auto v_ = make_safe(v);
int retval = PyDict_SetItemString(d, key, v);
if (retval == 0) return 1; //all good
return 0; //a problem occurred
}
static int dict_steal(PyObject* d, const char* key, PyObject* value) {
if (!value) return 0;
auto value_ = make_safe(value);
int retval = PyDict_SetItemString(d, key, value);
if (retval == 0) return 1; //all good
return 0; //a problem occurred
}
/**
* Creates an str object, from a C or C++ string. Returns a **new
* reference**.
*/
static PyObject* make_object(const char* s) {
return Py_BuildValue("s", s);
}
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
}
/**
* Describes a given codec. We return a **new reference** to a dictionary
* containing the codec properties.
......@@ -255,11 +345,11 @@ static PyObject* get_video_codecs(void (*f)(std::map<std::string, const AVCodec*
}
static PyObject* PyBobIoVideo_SupportedCodecs(PyObject*) {
return get_video_codecs(&bob::io::detail::ffmpeg::codecs_supported);
return get_video_codecs(&bob::io::video::codecs_supported);
}
static PyObject* PyBobIoVideo_AvailableCodecs(PyObject*) {
return get_video_codecs(&bob::io::detail::ffmpeg::codecs_installed);
return get_video_codecs(&bob::io::video::codecs_installed);
}
PyDoc_STRVAR(s_supported_codecs_str, "supported_video_codecs");
......@@ -304,7 +394,7 @@ static PyObject* get_video_iformats(void (*f)(std::map<std::string, AVInputForma
// get extensions
std::vector<std::string> exts;
bob::io::detail::ffmpeg::tokenize_csv(k->second->extensions, exts);
bob::io::video::tokenize_csv(k->second->extensions, exts);
PyObject* ext_list = PyList_New(0);
if (!ext_list) return 0;
......@@ -328,11 +418,11 @@ static PyObject* get_video_iformats(void (*f)(std::map<std::string, AVInputForma
}
static PyObject* PyBobIoVideo_SupportedInputFormats(PyObject*) {
return get_video_iformats(&bob::io::detail::ffmpeg::iformats_supported);
return get_video_iformats(&bob::io::video::iformats_supported);
}
static PyObject* PyBobIoVideo_AvailableInputFormats(PyObject*) {
return get_video_iformats(&bob::io::detail::ffmpeg::iformats_installed);
return get_video_iformats(&bob::io::video::iformats_installed);
}
PyDoc_STRVAR(s_supported_iformats_str, "supported_videoreader_formats");
......@@ -359,8 +449,8 @@ 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);
if (supported) bob::io::video::oformats_supported(m);
else bob::io::video::oformats_installed(m);
PyObject* retval = PyDict_New();
if (!retval) return 0;
......@@ -380,7 +470,7 @@ static PyObject* get_video_oformats(bool supported) {
// get extensions
std::vector<std::string> exts;
bob::io::detail::ffmpeg::tokenize_csv(k->second->extensions, exts);
bob::io::video::tokenize_csv(k->second->extensions, exts);
PyObject* ext_list = PyList_New(0);
if (!ext_list) return 0;
......@@ -413,7 +503,7 @@ static PyObject* get_video_oformats(bool supported) {
/** get supported codec list **/
if (supported) {
std::vector<const AVCodec*> codecs;
bob::io::detail::ffmpeg::oformat_supported_codecs(k->second->name, codecs);
bob::io::video::oformat_supported_codecs(k->second->name, codecs);
PyObject* supported_codecs = PyDict_New();
if (!supported_codecs) return 0;
......@@ -475,16 +565,16 @@ necessarily supported** by this library.\n\
*/
static void list_formats(std::map<std::string, std::string>& formats) {
std::map<std::string, AVInputFormat*> iformat;
bob::io::detail::ffmpeg::iformats_supported(iformat);
bob::io::video::iformats_supported(iformat);
std::map<std::string, AVOutputFormat*> oformat;
bob::io::detail::ffmpeg::oformats_supported(oformat);
bob::io::video::oformats_supported(oformat);
for (auto k=iformat.begin(); k!=iformat.end(); ++k) {
auto o=oformat.find(k->first);
if (o!=oformat.end()) {
//format can be used for input and output
std::vector<std::string> extensions;
bob::io::detail::ffmpeg::tokenize_csv(o->second->extensions, extensions);
bob::io::video::tokenize_csv(o->second->extensions, extensions);
for (auto e=extensions.begin(); e!=extensions.end(); ++e) {
std::string key = ".";
key += *e;
......@@ -561,6 +651,10 @@ static PyModuleDef module_definition = {
};
#endif
extern PyTypeObject PyBobIoVideoReader_Type;
extern PyTypeObject PyBobIoVideoReaderIterator_Type;
extern PyTypeObject PyBobIoVideoWriter_Type;
static PyObject* create_module (void) {
PyBobIoVideoReader_Type.tp_new = PyType_GenericNew;
......@@ -610,7 +704,7 @@ static PyObject* create_module (void) {
std::map<std::string, std::string> formats;
list_formats(formats);
for (auto k=formats.begin(); k!=formats.end(); ++k) {
if (!PyBobIoCodec_Register(k->first, k->second, &make_file)) {
if (!PyBobIoCodec_Register(k->first.c_str(), k->second.c_str(), &make_file)) {
PyErr_Print();
//do not return 0, or we may crash badly
}
......
......@@ -5,15 +5,14 @@
* @brief Bindings to bob::io::video::Reader
*/
#define XBOB_IO_BASE_MODULE
#include "cpp/reader.h"
#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 <xbob.io.base/api.h>
#include <stdexcept>
#define VIDEOREADER_NAME "reader"
......@@ -41,7 +40,7 @@ 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\
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\
......@@ -53,6 +52,13 @@ meaning pure black and 255, pure white (color).\n\
\n\
");
typedef struct {
PyObject_HEAD
boost::shared_ptr<bob::io::video::Reader> v;
} PyBobIoVideoReaderObject;
extern PyTypeObject PyBobIoVideoReader_Type;
/* How to create a new PyBobIoVideoReaderObject */
static PyObject* PyBobIoVideoReader_New(PyTypeObject* type, PyObject*, PyObject*) {
......@@ -555,9 +561,17 @@ static PyMappingMethods PyBobIoVideoReader_Mapping = {
* Definition of Iterator to VideoReader *
*****************************************/
#define VIDEOITERTYPE_NAME "VideoReader.iter"
#define VIDEOITERTYPE_NAME "reader.iter"
PyDoc_STRVAR(s_videoreaderiterator_str, XBOB_EXT_MODULE_PREFIX "." VIDEOITERTYPE_NAME);
typedef struct {
PyObject_HEAD
PyBobIoVideoReaderObject* pyreader;
boost::shared_ptr<bob::io::video::Reader::const_iterator> iter;
} PyBobIoVideoReaderIteratorObject;
extern PyTypeObject PyBobIoVideoReaderIterator_Type;
static PyObject* PyBobIoVideoReaderIterator_New(PyTypeObject* type, PyObject*, PyObject*) {
/* Allocates the python object itself */
......@@ -699,5 +713,3 @@ PyTypeObject PyBobIoVideoReader_Type = {
0, /* tp_alloc */
PyBobIoVideoReader_New, /* tp_new */
};
#endif /* WITH_FFMPEG */
......@@ -22,14 +22,17 @@ import sys
import argparse
import numpy
# from bob
from xbob.io.base import save as save_to_file
from xbob.io.base import create_directories_save
# internal
from .. import utils, create_directories_save
from .. import save as save_to_file
from .. import test_utils
from .. import utils, test_utils
from .. import supported_video_codecs, available_video_codecs
from .. import supported_videowriter_formats, available_videowriter_formats
def list_codecs(*args, **kwargs):
from ..version import supported_video_codecs, available_video_codecs
CODECS = supported_video_codecs()
ALL_CODECS = available_video_codecs()
......@@ -44,7 +47,6 @@ def list_codecs(*args, **kwargs):
def list_all_codecs(*args, **kwargs):
from ..version import supported_video_codecs, available_video_codecs
CODECS = supported_video_codecs()
ALL_CODECS = available_video_codecs()
......@@ -60,7 +62,6 @@ def list_all_codecs(*args, **kwargs):
def list_formats(*args, **kwargs):
from ..version import supported_videowriter_formats, available_videowriter_formats
FORMATS = supported_videowriter_formats()
ALL_FORMATS = available_videowriter_formats()
......@@ -75,7 +76,6 @@ def list_formats(*args, **kwargs):
def list_all_formats(*args, **kwargs):
from ..version import supported_videowriter_formats, available_videowriter_formats
FORMATS = supported_videowriter_formats()
ALL_FORMATS = available_videowriter_formats()
......@@ -143,8 +143,8 @@ def user_video(original, max_frames, format, codec, filename):
The name (path) of the file to use for encoding the test
"""
from .. import VideoReader, VideoWriter
vreader = VideoReader(original, check=True)
from .. import reader, writer
vreader = reader(original, check=True)