diff --git a/xbob/io/test_video.py b/xbob/io/test_video.py index 29b0ccd01629da5afe0802ef986915f4d21be14e..b1bdba6598b4f1fc11faa91dfd9c2f3d4f3ee02d 100644 --- a/xbob/io/test_video.py +++ b/xbob/io/test_video.py @@ -8,6 +8,7 @@ """Runs some video tests """ +import os import numpy import nose.tools from . import test_utils @@ -228,3 +229,97 @@ def test_can_use_array_interface(): 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/videoreader.cpp b/xbob/io/videoreader.cpp index b6a92c585a522d8686ee3c22372e3f8fa5b17e82..6dae23fd17356075d800477e985f1f92481a77ee 100644 --- a/xbob/io/videoreader.cpp +++ b/xbob/io/videoreader.cpp @@ -135,8 +135,8 @@ PyDoc_STRVAR(s_width_str, "width"); PyDoc_STRVAR(s_width_doc, "[int] The width of each frame in the video (a multiple of 2)"); -Py_ssize_t PyBobIoVideoReader_Len(PyBobIoVideoReaderObject* self) { - return self->v->numberOfFrames(); +PyObject* PyBobIoVideoReader_NumberOfFrames(PyBobIoVideoReaderObject* self) { + return Py_BuildValue("n", self->v->numberOfFrames()); } PyDoc_STRVAR(s_number_of_frames_str, "number_of_frames"); @@ -239,7 +239,7 @@ static PyGetSetDef PyBobIoVideoReader_getseters[] = { }, { s_number_of_frames_str, - (getter)PyBobIoVideoReader_Len, + (getter)PyBobIoVideoReader_NumberOfFrames, 0, s_number_of_frames_doc, 0, @@ -458,7 +458,7 @@ static PyObject* PyBobIoVideoReader_GetSlice (PyBobIoVideoReaderObject* self, Py Py_ssize_t start, stop, step, slicelength; #if PY_VERSION_HEX < 0x03000000 - if (PySlice_GetIndicesEx(slice, + if (PySlice_GetIndicesEx(slice, #else if (PySlice_GetIndicesEx(reinterpret_cast<PyObject*>(slice), #endif @@ -541,6 +541,10 @@ static PyObject* PyBobIoVideoReader_GetItem (PyBobIoVideoReaderObject* self, PyO } } +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 diff --git a/xbob/io/videowriter.cpp b/xbob/io/videowriter.cpp index 2f54791cf2fbcba7b82a3e004312c2564d7868a3..c1603c6159dc7fbe355469ce81aaef2f9629bab3 100644 --- a/xbob/io/videowriter.cpp +++ b/xbob/io/videowriter.cpp @@ -131,8 +131,8 @@ static int PyBobIoVideoWriter_Init(PyBobIoVideoWriterObject* self, #endif try { - self->v = boost::make_shared<bob::io::VideoWriter>(c_filename, height, width, - framerate, bitrate, gop, codec_str, format_str, check); + 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()); @@ -170,8 +170,8 @@ PyDoc_STRVAR(s_width_str, "width"); PyDoc_STRVAR(s_width_doc, "[int] The width of each frame in the video (a multiple of 2)"); -Py_ssize_t PyBobIoVideoWriter_Len(PyBobIoVideoWriterObject* self) { - return self->v->numberOfFrames(); +PyObject* PyBobIoVideoWriter_NumberOfFrames(PyBobIoVideoWriterObject* self) { + return Py_BuildValue("n", self->v->numberOfFrames()); } PyDoc_STRVAR(s_number_of_frames_str, "number_of_frames"); @@ -187,6 +187,11 @@ 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()); } @@ -195,6 +200,11 @@ 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()); } @@ -203,6 +213,11 @@ 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()); } @@ -211,6 +226,11 @@ 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()); } @@ -264,6 +284,12 @@ 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()); } @@ -305,7 +331,7 @@ static PyGetSetDef PyBobIoVideoWriter_getseters[] = { }, { s_number_of_frames_str, - (getter)PyBobIoVideoWriter_Len, + (getter)PyBobIoVideoWriter_NumberOfFrames, 0, s_number_of_frames_doc, 0, @@ -398,6 +424,12 @@ static PyGetSetDef PyBobIoVideoWriter_getseters[] = { }; 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 @@ -409,6 +441,12 @@ static PyObject* PyBobIoVideoWriter_Repr(PyBobIoVideoWriterObject* self) { 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); @@ -497,6 +535,10 @@ static PyMethodDef PyBobIoVideoWriter_Methods[] = { {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 */