Commit 5959096d authored by André Anjos's avatar André Anjos 💬

Merge branch 'multiple-issues' into 'master'

Fixes to multiple issues

Closes #6, #8, and #9

See merge request !10
parents 6c48e835 b37f3f93
Pipeline #17586 passed with stages
in 23 minutes and 5 seconds
/**
* @file io/cxx/video::Reader.cc
* @date Wed Jun 22 17:50:08 2011 +0200
* @author Andre Anjos <andre.anjos@idiap.ch>
*
* @brief A class to help you read videos. This code originates from
* http://ffmpeg.org/doxygen/1.0/, "decoding & encoding example".
*
* Copyright (C) Idiap Research Institute, Martigny, Switzerland
*/
#include "reader.h" #include "reader.h"
#include <stdexcept> #include <stdexcept>
...@@ -18,12 +7,6 @@ ...@@ -18,12 +7,6 @@
#include <bob.io.base/blitz_array.h> #include <bob.io.base/blitz_array.h>
#if LIBAVUTIL_VERSION_INT < 0x371167 //55.17.103 @ ffmpeg-3.0
#ifndef AV_PIX_FMT_RGB24
#define AV_PIX_FMT_RGB24 PIX_FMT_RGB24
#endif
#endif
namespace bob { namespace io { namespace video { namespace bob { namespace io { namespace video {
Reader::Reader(const std::string& filename, bool check) { Reader::Reader(const std::string& filename, bool check) {
...@@ -72,8 +55,8 @@ namespace bob { namespace io { namespace video { ...@@ -72,8 +55,8 @@ namespace bob { namespace io { namespace video {
} }
boost::shared_ptr<AVCodecContext> codec_ctxt = boost::shared_ptr<AVCodecContext> codec_ctxt =
make_codec_context(m_filepath, make_decoder_context(m_filepath, format_ctxt->streams[stream_index],
format_ctxt->streams[stream_index], codec); codec);
/** /**
* Copies some information from the context just opened * Copies some information from the context just opened
...@@ -216,7 +199,7 @@ namespace bob { namespace io { namespace video { ...@@ -216,7 +199,7 @@ namespace bob { namespace io { namespace video {
m_format_context = make_input_format_context(filename); m_format_context = make_input_format_context(filename);
m_stream_index = find_video_stream(filename, m_format_context); m_stream_index = find_video_stream(filename, m_format_context);
m_codec = find_decoder(filename, m_format_context, m_stream_index); m_codec = find_decoder(filename, m_format_context, m_stream_index);
m_codec_context = make_codec_context(filename, m_codec_context = make_decoder_context(filename,
m_format_context->streams[m_stream_index], m_codec); m_format_context->streams[m_stream_index], m_codec);
m_swscaler = make_scaler(filename, m_codec_context, m_swscaler = make_scaler(filename, m_codec_context,
m_codec_context->pix_fmt, AV_PIX_FMT_RGB24); m_codec_context->pix_fmt, AV_PIX_FMT_RGB24);
......
/**
* @date Wed Jun 22 17:50:08 2011 +0200
* @author Andre Anjos <andre.anjos@idiap.ch>
*
* @brief A class to help you read videos. This code originates from
* http://ffmpeg.org/doxygen/1.0/, "decoding & encoding example".
*
* Copyright (C) Idiap Research Institute, Martigny, Switzerland
*/
#ifndef BOB_IO_VIDEO_READER_H #ifndef BOB_IO_VIDEO_READER_H
#define BOB_IO_VIDEO_READER_H #define BOB_IO_VIDEO_READER_H
......
This diff is collapsed.
/**
* @author Andre Anjos <andre.anjos@idiap.ch>
* @date Mon 26 Nov 17:33:19 2012
*
* @brief A simple set of utilities to query ffmpeg
*
* Copyright (C) Idiap Research Institute, Martigny, Switzerland
*/
#ifndef BOB_IO_VIDEO_UTILS_H #ifndef BOB_IO_VIDEO_UTILS_H
#define BOB_IO_VIDEO_UTILS_H #define BOB_IO_VIDEO_UTILS_H
...@@ -101,16 +92,29 @@ namespace bob { namespace io { namespace video { ...@@ -101,16 +92,29 @@ namespace bob { namespace io { namespace video {
************************************************************************/ ************************************************************************/
/** /**
* Creates a new codec context and verify all is good. * Creates a new codec encoding context and verify all is good.
* *
* @note The returned object knows how to correctly delete itself, freeing * @note The returned object knows how to correctly delete itself, freeing
* all acquired resources. Nonetheless, when this object is used in * all acquired resources. Nonetheless, when this object is used in
* conjunction with other objects required for file encoding, order must be * conjunction with other objects required for file decoding, order must be
* respected. * respected.
*/ */
boost::shared_ptr<AVCodecContext> make_codec_context( boost::shared_ptr<AVCodecContext> make_decoder_context(
const std::string& filename, AVStream* stream, AVCodec* codec); const std::string& filename, AVStream* stream, AVCodec* codec);
/**
* Creates a new codec encoding context and verify all is good.
*
* @note The returned object knows how to correctly delete itself, freeing
* all acquired resources. Nonetheless, when this object is used in
* conjunction with other objects required for file encoding, order must be
* respected.
*/
boost::shared_ptr<AVCodecContext> make_encoder_context(
const std::string& filename, AVFormatContext* fmtctxt, AVStream* stream,
AVCodec* codec, size_t height, size_t width, double framerate,
double bitrate, size_t gop);
/** /**
* Allocates the software scaler that handles size and pixel format * Allocates the software scaler that handles size and pixel format
* conversion. * conversion.
...@@ -119,16 +123,14 @@ namespace bob { namespace io { namespace video { ...@@ -119,16 +123,14 @@ namespace bob { namespace io { namespace video {
* all acquired resources. Nonetheless, when this object is used in * all acquired resources. Nonetheless, when this object is used in
* conjunction with other objects required for file encoding, order must be * conjunction with other objects required for file encoding, order must be
* respected. * respected.
*
* @note This scaler constructor is used both in encoding and decoding,
* therefore needs to know source and destination pixel formats, which may
* different in each circumstance.
*/ */
#if LIBAVUTIL_VERSION_INT >= 0x334A64 //51.74.100 @ ffmpeg-3.0
boost::shared_ptr<SwsContext> make_scaler(const std::string& filename, boost::shared_ptr<SwsContext> make_scaler(const std::string& filename,
boost::shared_ptr<AVCodecContext> stream, boost::shared_ptr<AVCodecContext> stream,
AVPixelFormat source_pixel_format, AVPixelFormat dest_pixel_format); AVPixelFormat source_pixel_format, AVPixelFormat dest_pixel_format);
#else
boost::shared_ptr<SwsContext> make_scaler(const std::string& filename,
boost::shared_ptr<AVCodecContext> stream,
PixelFormat source_pixel_format, PixelFormat dest_pixel_format);
#endif
/** /**
* Allocates a frame for a particular context. The frame space will be * Allocates a frame for a particular context. The frame space will be
...@@ -140,13 +142,8 @@ namespace bob { namespace io { namespace video { ...@@ -140,13 +142,8 @@ namespace bob { namespace io { namespace video {
* conjunction with other objects required for file encoding, order must be * conjunction with other objects required for file encoding, order must be
* respected. * respected.
*/ */
#if LIBAVUTIL_VERSION_INT >= 0x334A64 //51.74.100 @ ffmpeg-3.0
boost::shared_ptr<AVFrame> make_frame(const std::string& filename,
boost::shared_ptr<AVCodecContext> stream, AVPixelFormat pixfmt);
#else
boost::shared_ptr<AVFrame> make_frame(const std::string& filename, boost::shared_ptr<AVFrame> make_frame(const std::string& filename,
boost::shared_ptr<AVCodecContext> stream, PixelFormat pixfmt); boost::shared_ptr<AVCodecContext> stream);
#endif
/************************************************************************ /************************************************************************
* Video reading specific utilities * Video reading specific utilities
...@@ -238,7 +235,7 @@ namespace bob { namespace io { namespace video { ...@@ -238,7 +235,7 @@ namespace bob { namespace io { namespace video {
/** /**
* Creates a new AVStream on the output file given by the format context * Creates a new AVStream on the output file given by the format context
* pointer, with the given configurations. * pointer and the codec
* *
* @note The returned object knows how to correctly delete itself, freeing * @note The returned object knows how to correctly delete itself, freeing
* all acquired resources. Nonetheless, when this object is used in * all acquired resources. Nonetheless, when this object is used in
...@@ -246,15 +243,7 @@ namespace bob { namespace io { namespace video { ...@@ -246,15 +243,7 @@ namespace bob { namespace io { namespace video {
* respected. * respected.
*/ */
boost::shared_ptr<AVStream> make_stream(const std::string& filename, boost::shared_ptr<AVStream> make_stream(const std::string& filename,
boost::shared_ptr<AVFormatContext> fmtctxt, const std::string& codecname, boost::shared_ptr<AVFormatContext> fmtctxt, AVCodec* codec);
size_t height, size_t width, float framerate, float bitrate, size_t gop,
AVCodec* codec);
/**
* Allocates a video buffer (useful for ffmpeg < 0.11)
*/
boost::shared_array<uint8_t> make_buffer
(boost::shared_ptr<AVFormatContext> format_context, size_t size);
/** /**
* Opens the output file using the given context, writes a header, if the * Opens the output file using the given context, writes a header, if the
...@@ -271,14 +260,13 @@ namespace bob { namespace io { namespace video { ...@@ -271,14 +260,13 @@ namespace bob { namespace io { namespace video {
boost::shared_ptr<AVFormatContext> format_context); boost::shared_ptr<AVFormatContext> format_context);
/** /**
* Flushes frames which are buffered on the given encoder stream. This only * Flushes frames which are buffered on the given encoder stream. This is
* happens if (codec->capabilities & CODEC_CAP_DELAY) is true. * only required if (codec->capabilities & CODEC_CAP_DELAY) is true.
*/ */
void flush_encoder(const std::string& filename, void flush_encoder(const std::string& filename,
boost::shared_ptr<AVFormatContext> format_context, boost::shared_ptr<AVFormatContext> format_context,
boost::shared_ptr<AVStream> stream, AVCodec* codec, boost::shared_ptr<AVStream> stream,
boost::shared_array<uint8_t> buffer, boost::shared_ptr<AVCodecContext> codec_context);
size_t buffer_size);
/** /**
* Writes a data frame into the encoder stream. * Writes a data frame into the encoder stream.
...@@ -291,11 +279,10 @@ namespace bob { namespace io { namespace video { ...@@ -291,11 +279,10 @@ namespace bob { namespace io { namespace video {
const std::string& filename, const std::string& filename,
boost::shared_ptr<AVFormatContext> format_context, boost::shared_ptr<AVFormatContext> format_context,
boost::shared_ptr<AVStream> stream, boost::shared_ptr<AVStream> stream,
boost::shared_ptr<AVCodecContext> codec_context,
boost::shared_ptr<AVFrame> context_frame, boost::shared_ptr<AVFrame> context_frame,
boost::shared_ptr<AVFrame> tmp_frame, boost::shared_ptr<AVFrame> tmp_frame,
boost::shared_ptr<SwsContext> swscaler, boost::shared_ptr<SwsContext> swscaler);
boost::shared_array<uint8_t> buffer,
size_t buffer_size);
}}} }}}
......
/**
* @file io/cxx/video::Writer.cc
* @date Wed 28 Nov 2012 13:51:58 CET
* @author Andre Anjos <andre.anjos@idiap.ch>
*
* @brief A class to help you write videos. This code originates from
* http://ffmpeg.org/doxygen/1.0/, "muxing.c" example.
*
* Copyright (C) Idiap Research Institute, Martigny, Switzerland
*/
#include "writer.h" #include "writer.h"
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/preprocessor.hpp> #include <boost/preprocessor.hpp>
#if LIBAVFORMAT_VERSION_INT < 0x361764 /* 54.23.100 @ ffmpeg-0.11 */
#define FFMPEG_VIDEO_BUFFER_SIZE 200000
#else
#define FFMPEG_VIDEO_BUFFER_SIZE 0
#endif
#if LIBAVUTIL_VERSION_INT < 0x371167 //55.17.103 @ ffmpeg-3.0
#ifndef AV_PIX_FMT_RGB24
#define AV_PIX_FMT_RGB24 PIX_FMT_RGB24
#endif
#endif
namespace bob { namespace io { namespace video { namespace bob { namespace io { namespace video {
Writer::Writer( Writer::Writer(
...@@ -42,17 +19,12 @@ namespace bob { namespace io { namespace video { ...@@ -42,17 +19,12 @@ namespace bob { namespace io { namespace video {
m_opened(false), m_opened(false),
m_format_context(make_output_format_context(filename, format)), m_format_context(make_output_format_context(filename, format)),
m_codec(find_encoder(filename, m_format_context, codec)), m_codec(find_encoder(filename, m_format_context, codec)),
m_stream(make_stream(filename, m_format_context, codec, height, m_stream(make_stream(filename, m_format_context, m_codec)),
width, framerate, bitrate, gop, m_codec)), m_codec_context(make_encoder_context(filename, m_format_context.get(),
m_codec_context(make_codec_context(filename, m_stream.get(), m_codec)), m_stream.get(), m_codec, height, width, framerate, bitrate, gop)),
m_context_frame(make_frame(filename, m_codec_context, m_stream->codec->pix_fmt)), m_context_frame(make_frame(filename, m_codec_context)),
#if LIBAVCODEC_VERSION_INT >= 0x352a00 //53.42.0 @ ffmpeg-0.9 m_swscaler(make_scaler(filename, m_codec_context, AV_PIX_FMT_GBRP,
m_swscaler(make_scaler(filename, m_codec_context, AV_PIX_FMT_GBRP, m_stream->codec->pix_fmt)), m_codec_context->pix_fmt)),
#else
m_rgb24_frame(make_frame(filename, m_codec_context, AV_PIX_FMT_RGB24)),
m_swscaler(make_scaler(filename, m_codec_context, AV_PIX_FMT_RGB24, m_stream->codec->pix_fmt)),
#endif
m_buffer(make_buffer(m_format_context, FFMPEG_VIDEO_BUFFER_SIZE)),
m_height(height), m_height(height),
m_width(width), m_width(width),
m_framerate(framerate), m_framerate(framerate),
...@@ -110,15 +82,13 @@ namespace bob { namespace io { namespace video { ...@@ -110,15 +82,13 @@ namespace bob { namespace io { namespace video {
if (!m_opened) return; if (!m_opened) return;
flush_encoder(m_filename, m_format_context, m_stream, m_codec, flush_encoder(m_filename, m_format_context, m_stream, m_codec_context);
m_buffer, FFMPEG_VIDEO_BUFFER_SIZE);
close_output_file(m_filename, m_format_context); close_output_file(m_filename, m_format_context);
/* Destroyes resources in an orderly fashion */ /* Destroyes resources in an orderly fashion */
m_codec_context.reset(); m_codec_context.reset();
m_context_frame.reset(); m_context_frame.reset();
m_rgb24_frame.reset(); m_rgb24_frame.reset();
m_buffer.reset();
m_swscaler.reset(); m_swscaler.reset();
m_stream.reset(); m_stream.reset();
m_format_context.reset(); m_format_context.reset();
...@@ -139,8 +109,8 @@ namespace bob { namespace io { namespace video { ...@@ -139,8 +109,8 @@ namespace bob { namespace io { namespace video {
info % BOOST_PP_STRINGIZE(LIBSWSCALE_VERSION); info % BOOST_PP_STRINGIZE(LIBSWSCALE_VERSION);
info % m_format_context->oformat->name; info % m_format_context->oformat->name;
info % m_format_context->oformat->long_name; info % m_format_context->oformat->long_name;
info % m_stream->codec->codec->name; info % m_codec->name;
info % m_stream->codec->codec->long_name; info % m_codec->long_name;
info % (m_current_frame/m_framerate); info % (m_current_frame/m_framerate);
info % m_current_frame; info % m_current_frame;
info % m_framerate; info % m_framerate;
...@@ -168,8 +138,8 @@ namespace bob { namespace io { namespace video { ...@@ -168,8 +138,8 @@ namespace bob { namespace io { namespace video {
blitz::Range a = blitz::Range::all(); blitz::Range a = blitz::Range::all();
for(int i=data.lbound(0); i<(data.extent(0)+data.lbound(0)); ++i) { for(int i=data.lbound(0); i<(data.extent(0)+data.lbound(0)); ++i) {
write_video_frame(data(i, a, a, a), m_filename, m_format_context, write_video_frame(data(i, a, a, a), m_filename, m_format_context,
m_stream, m_context_frame, m_rgb24_frame, m_swscaler, m_buffer, m_stream, m_codec_context, m_context_frame, m_rgb24_frame,
FFMPEG_VIDEO_BUFFER_SIZE); m_swscaler);
++m_current_frame; ++m_current_frame;
m_typeinfo_video.shape[0] += 1; m_typeinfo_video.shape[0] += 1;
} }
...@@ -192,8 +162,7 @@ namespace bob { namespace io { namespace video { ...@@ -192,8 +162,7 @@ namespace bob { namespace io { namespace video {
} }
write_video_frame(data, m_filename, m_format_context, write_video_frame(data, m_filename, m_format_context,
m_stream, m_context_frame, m_rgb24_frame, m_swscaler, m_buffer, m_stream, m_codec_context, m_context_frame, m_rgb24_frame, m_swscaler);
FFMPEG_VIDEO_BUFFER_SIZE);
++m_current_frame; ++m_current_frame;
m_typeinfo_video.shape[0] += 1; m_typeinfo_video.shape[0] += 1;
} }
...@@ -229,8 +198,8 @@ namespace bob { namespace io { namespace video { ...@@ -229,8 +198,8 @@ namespace bob { namespace io { namespace video {
blitz::Array<uint8_t,3> tmp(const_cast<uint8_t*>(static_cast<const uint8_t*>(data.ptr())), shape, blitz::Array<uint8_t,3> tmp(const_cast<uint8_t*>(static_cast<const uint8_t*>(data.ptr())), shape,
blitz::neverDeleteData); blitz::neverDeleteData);
write_video_frame(tmp, m_filename, m_format_context, write_video_frame(tmp, m_filename, m_format_context,
m_stream, m_context_frame, m_rgb24_frame, m_swscaler, m_buffer, m_stream, m_codec_context, m_context_frame, m_rgb24_frame,
FFMPEG_VIDEO_BUFFER_SIZE); m_swscaler);
++m_current_frame; ++m_current_frame;
m_typeinfo_video.shape[0] += 1; m_typeinfo_video.shape[0] += 1;
} }
...@@ -253,8 +222,8 @@ namespace bob { namespace io { namespace video { ...@@ -253,8 +222,8 @@ namespace bob { namespace io { namespace video {
for(size_t i=0; i<type.shape[0]; ++i) { for(size_t i=0; i<type.shape[0]; ++i) {
blitz::Array<uint8_t,3> tmp(ptr, shape, blitz::neverDeleteData); blitz::Array<uint8_t,3> tmp(ptr, shape, blitz::neverDeleteData);
write_video_frame(tmp, m_filename, m_format_context, write_video_frame(tmp, m_filename, m_format_context,
m_stream, m_context_frame, m_rgb24_frame, m_swscaler, m_buffer, m_stream, m_codec_context, m_context_frame, m_rgb24_frame,
FFMPEG_VIDEO_BUFFER_SIZE); m_swscaler);
++m_current_frame; ++m_current_frame;
m_typeinfo_video.shape[0] += 1; m_typeinfo_video.shape[0] += 1;
ptr += frame_size; ptr += frame_size;
......
/**
* @date Wed 28 Nov 2012 13:52:08 CET
* @author Andre Anjos <andre.anjos@idiap.ch>
*
* @brief A class to help you write videos. This code originates from
* http://ffmpeg.org/doxygen/1.0/, "decoding & encoding example".
*
* Copyright (C) Idiap Research Institute, Martigny, Switzerland
*/
#ifndef BOB_IO_VIDEO_WRITER_H #ifndef BOB_IO_VIDEO_WRITER_H
#define BOB_IO_VIDEO_WRITER_H #define BOB_IO_VIDEO_WRITER_H
...@@ -119,10 +109,10 @@ namespace bob { namespace io { namespace video { ...@@ -119,10 +109,10 @@ namespace bob { namespace io { namespace video {
return m_format_context->oformat->long_name; return m_format_context->oformat->long_name;
} }
std::string codecName() const { std::string codecName() const {
return m_stream->codec->codec->name; return m_codec->name;
} }
std::string codecLongName() const { std::string codecLongName() const {
return m_stream->codec->codec->long_name; return m_codec->long_name;
} }
/** /**
...@@ -188,7 +178,6 @@ namespace bob { namespace io { namespace video { ...@@ -188,7 +178,6 @@ namespace bob { namespace io { namespace video {
boost::shared_ptr<AVFrame> m_context_frame; ///< output frame data boost::shared_ptr<AVFrame> m_context_frame; ///< output frame data
boost::shared_ptr<AVFrame> m_rgb24_frame; ///< temporary frame data boost::shared_ptr<AVFrame> m_rgb24_frame; ///< temporary frame data
boost::shared_ptr<SwsContext> m_swscaler; ///< software scaler boost::shared_ptr<SwsContext> m_swscaler; ///< software scaler
boost::shared_array<uint8_t> m_buffer; ///< buffer for ffmpeg < 0.11.0
size_t m_height; size_t m_height;
size_t m_width; size_t m_width;
double m_framerate; double m_framerate;
......
...@@ -128,13 +128,8 @@ static PyObject* describe_codec(const AVCodec* codec) { ...@@ -128,13 +128,8 @@ static PyObject* describe_codec(const AVCodec* codec) {
unsigned int i=0; unsigned int i=0;
while(codec->pix_fmts[i] != -1) { while(codec->pix_fmts[i] != -1) {
if (!list_append(pixfmt, if (!list_append(pixfmt, av_get_pix_fmt_name(codec->pix_fmts[i++])))
#if LIBAVUTIL_VERSION_INT >= 0x320f01 //50.15.1 @ ffmpeg-0.6 return 0;
av_get_pix_fmt_name
#else
avcodec_get_pix_fmt_name
#endif
(codec->pix_fmts[i++]))) return 0;
} }
pixfmt = PySequence_Tuple(pixfmt); pixfmt = PySequence_Tuple(pixfmt);
} }
...@@ -604,6 +599,11 @@ static PyModuleDef module_definition = { ...@@ -604,6 +599,11 @@ static PyModuleDef module_definition = {
static PyObject* create_module (void) { static PyObject* create_module (void) {
/* Initialize libavcodec, and register all codecs and formats. */
av_log_set_level(AV_LOG_QUIET);
avcodec_register_all();
av_register_all();
# if PY_VERSION_HEX >= 0x03000000 # if PY_VERSION_HEX >= 0x03000000
PyObject* module = PyModule_Create(&module_definition); PyObject* module = PyModule_Create(&module_definition);
auto module_ = make_xsafe(module); auto module_ = make_xsafe(module);
......
...@@ -17,7 +17,7 @@ from bob.io.base import load ...@@ -17,7 +17,7 @@ from bob.io.base import load
# These are some global parameters for the test. # These are some global parameters for the test.
INPUT_VIDEO = test_utils.datafile('test.mov', __name__) INPUT_VIDEO = test_utils.datafile('test.mov', __name__)
UNICODE_VIDEO = test_utils.datafile('test_straße.mov', __name__)
def test_codec_support(): def test_codec_support():
...@@ -32,11 +32,12 @@ def test_codec_support(): ...@@ -32,11 +32,12 @@ def test_codec_support():
if v['encode']: assert describe_encoder(v['id']) if v['encode']: assert describe_encoder(v['id'])
# Assert we support, at least, some known codecs # Assert we support, at least, some known codecs
for codec in ('ffv1', 'wmv2', 'mpeg4', 'mjpeg'): for codec in ('ffv1', 'wmv2', 'mpeg4', 'mjpeg', 'h264'):
assert codec in supported assert codec in supported
assert supported[codec]['encode'] assert supported[codec]['encode']
assert supported[codec]['decode'] assert supported[codec]['decode']
def test_input_format_support(): def test_input_format_support():
# Describes all encoders # Describes all encoders
...@@ -48,6 +49,7 @@ def test_input_format_support(): ...@@ -48,6 +49,7 @@ def test_input_format_support():
for fmt in ('avi', 'mov', 'mp4'): for fmt in ('avi', 'mov', 'mp4'):
assert fmt in supported assert fmt in supported
def test_output_format_support(): def test_output_format_support():
# Describes all encoders # Describes all encoders
...@@ -59,6 +61,7 @@ def test_output_format_support(): ...@@ -59,6 +61,7 @@ def test_output_format_support():
for fmt in ('avi', 'mov', 'mp4'): for fmt in ('avi', 'mov', 'mp4'):
assert fmt in supported assert fmt in supported
def test_video_reader_attributes(): def test_video_reader_attributes():
from . import reader from . import reader
...@@ -90,32 +93,46 @@ def test_video_reader_attributes(): ...@@ -90,32 +93,46 @@ def test_video_reader_attributes():
def write_unicode_temp_file(): def write_unicode_temp_file():
prefix = 'bobtest_straße_'
suffix = '.avi'
tmpname = test_utils.temporary_filename(prefix=prefix, suffix=suffix)
# Writing temp file for testing # Writing temp file for testing
from . import writer from . import writer
width = 20 width = 20
height = 20 height = 20
framerate = 24 framerate = 24
outv = writer(UNICODE_VIDEO, height, width, framerate) outv = writer(tmpname, height, width, framerate)
for i in range(0, 3): for i in range(0, 3):
newframe = (numpy.random.random_integers(0,255,(3,height,width))) newframe = (numpy.random.random_integers(0,255,(3,height,width)))
outv.append(newframe.astype('uint8')) outv.append(newframe.astype('uint8'))
outv.close() outv.close()
return tmpname
def test_video_reader_unicode(): def test_video_reader_unicode():
try:
# Writing temp file for testing # Writing temp file for testing
write_unicode_temp_file() tmpname = write_unicode_temp_file()
from . import reader from . import reader
iv = reader(UNICODE_VIDEO) iv = reader(tmpname)
assert isinstance(iv.filename, str) assert isinstance(iv.filename, str)
assert 'ß' in UNICODE_VIDEO assert 'ß' in tmpname
assert 'ß' in iv.filename assert 'ß' in iv.filename
#os.remove(UNICODE_VIDEO) finally:
if os.path.exists(tmpname): os.unlink(tmpname)
def test_video_reader_str(): def test_video_reader_str():
...@@ -125,6 +142,7 @@ def test_video_reader_str(): ...@@ -125,6 +142,7 @@ def test_video_reader_str():
assert repr(iv) assert repr(iv)
assert str(iv) assert str(iv)
def test_can_iterate(): def test_can_iterate():
from . import reader from . import reader
...@@ -140,6 +158,7 @@ def test_can_iterate(): ...@@ -140,6 +158,7 @@ def test_can_iterate():
assert counter == len(video) #we have gone through all frames assert counter == len(video) #we have gone through all frames
def test_iteration(): def test_iteration():
from . import reader from . import reader
...@@ -150,20 +169,25 @@ def test_iteration(): ...@@ -150,20 +169,25 @@ def test_iteration():
for l, i in zip(objs, f): for l, i in zip(objs, f):
assert numpy.allclose(l, i) assert numpy.allclose(l, i)
def test_base_load_on_unicode(): def test_base_load_on_unicode():
try:
# Writing temp file for testing # Writing temp file for testing
write_unicode_temp_file() tmpname = write_unicode_temp_file()
from . import reader from . import reader
f = reader(UNICODE_VIDEO) f = reader(tmpname)
objs = load(UNICODE_VIDEO) objs = load(tmpname)
nose.tools.eq_(len(f), len(objs)) nose.tools.eq_(len(f), len(objs))
for l, i in zip(objs, f): for l, i in zip(objs, f):
assert numpy.allclose(l.shape, i.shape) assert numpy.allclose(l.shape, i.shape)
#os.remove(UNICODE_VIDEO) finally:
if os.path.exists(tmpname): os.unlink(tmpname)
def test_indexing(): def test_indexing():
...@@ -183,6 +207,7 @@ def test_indexing(): ...@@ -183,6 +207,7 @@ def test_indexing():
assert numpy.allclose(f[len(f)-1], f[-1]) assert numpy.allclose(f[len(f)-1], f[-1])
assert numpy.allclose(f[len(f)-2], f[-2]) assert numpy.allclose(f[len(f)-2], f[-2])
d