diff options
Diffstat (limited to 'mediagoblin/tests')
-rw-r--r-- | mediagoblin/tests/media_tools.py | 61 | ||||
-rw-r--r-- | mediagoblin/tests/test_audio.py | 104 | ||||
-rw-r--r-- | mediagoblin/tests/test_mgoblin_app.ini | 2 | ||||
-rw-r--r-- | mediagoblin/tests/test_submission.py | 19 | ||||
-rw-r--r-- | mediagoblin/tests/test_video.py | 132 |
5 files changed, 318 insertions, 0 deletions
diff --git a/mediagoblin/tests/media_tools.py b/mediagoblin/tests/media_tools.py new file mode 100644 index 00000000..8d58c024 --- /dev/null +++ b/mediagoblin/tests/media_tools.py @@ -0,0 +1,61 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2013 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from contextlib import contextmanager +import tempfile + +import gi +gi.require_version('Gst', '1.0') +from gi.repository import Gst +Gst.init(None) + +@contextmanager +def create_av(make_video=False, make_audio=False): + 'creates audio/video in `path`, throws AssertionError on any error' + media = tempfile.NamedTemporaryFile(suffix='.ogg') + pipeline = Gst.Pipeline() + mux = Gst.ElementFactory.make('oggmux', 'mux') + pipeline.add(mux) + if make_video: + video_src = Gst.ElementFactory.make('videotestsrc', 'video_src') + video_src.set_property('num-buffers', 20) + video_enc = Gst.ElementFactory.make('theoraenc', 'video_enc') + pipeline.add(video_src) + pipeline.add(video_enc) + assert video_src.link(video_enc) + assert video_enc.link(mux) + if make_audio: + audio_src = Gst.ElementFactory.make('audiotestsrc', 'audio_src') + audio_src.set_property('num-buffers', 20) + audio_enc = Gst.ElementFactory.make('vorbisenc', 'audio_enc') + pipeline.add(audio_src) + pipeline.add(audio_enc) + assert audio_src.link(audio_enc) + assert audio_enc.link(mux) + sink = Gst.ElementFactory.make('filesink', 'sink') + sink.set_property('location', media.name) + pipeline.add(sink) + mux.link(sink) + pipeline.set_state(Gst.State.PLAYING) + state = pipeline.get_state(Gst.SECOND) + assert state[0] == Gst.StateChangeReturn.SUCCESS + bus = pipeline.get_bus() + message = bus.timed_pop_filtered( + Gst.SECOND, # one second should be more than enough for 50-buf vid + Gst.MessageType.ERROR | Gst.MessageType.EOS) + assert message.type == Gst.MessageType.EOS + pipeline.set_state(Gst.State.NULL) + yield media.name diff --git a/mediagoblin/tests/test_audio.py b/mediagoblin/tests/test_audio.py new file mode 100644 index 00000000..62d582ff --- /dev/null +++ b/mediagoblin/tests/test_audio.py @@ -0,0 +1,104 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2013 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import tempfile +import shutil +import os +import pytest +from contextlib import contextmanager +import logging +import imghdr + +#os.environ['GST_DEBUG'] = '4,python:4' + +pytest.importorskip("gi.repository.Gst") +import gi +gi.require_version('Gst', '1.0') +from gi.repository import Gst +Gst.init(None) + +from mediagoblin.media_types.audio.transcoders import (AudioTranscoder, + AudioThumbnailer) +from mediagoblin.media_types.tools import discover + + +@contextmanager +def create_audio(): + audio = tempfile.NamedTemporaryFile() + src = Gst.ElementFactory.make('audiotestsrc', None) + src.set_property('num-buffers', 50) + enc = Gst.ElementFactory.make('flacenc', None) + dst = Gst.ElementFactory.make('filesink', None) + dst.set_property('location', audio.name) + pipeline = Gst.Pipeline() + pipeline.add(src) + pipeline.add(enc) + pipeline.add(dst) + src.link(enc) + enc.link(dst) + pipeline.set_state(Gst.State.PLAYING) + state = pipeline.get_state(3 * Gst.SECOND) + assert state[0] == Gst.StateChangeReturn.SUCCESS + bus = pipeline.get_bus() + bus.timed_pop_filtered( + 3 * Gst.SECOND, + Gst.MessageType.ERROR | Gst.MessageType.EOS) + pipeline.set_state(Gst.State.NULL) + yield (audio.name) + + +@contextmanager +def create_data_for_test(): + with create_audio() as audio_name: + second_file = tempfile.NamedTemporaryFile() + yield (audio_name, second_file.name) + + +def test_transcoder(): + ''' + Tests AudioTransocder's transcode method + ''' + transcoder = AudioTranscoder() + with create_data_for_test() as (audio_name, result_name): + transcoder.transcode(audio_name, result_name, quality=0.3, + progress_callback=None) + info = discover(result_name) + assert len(info.get_audio_streams()) == 1 + transcoder.transcode(audio_name, result_name, quality=0.3, + mux_name='oggmux', progress_callback=None) + info = discover(result_name) + assert len(info.get_audio_streams()) == 1 + + +def test_thumbnails(): + '''Test thumbnails generation. + + The code below heavily repeats + audio.processing.CommonAudioProcessor.create_spectrogram + 1. Create test audio + 2. Convert it to OGG source for spectogram using transcoder + 3. Create spectogram in jpg + + ''' + thumbnailer = AudioThumbnailer() + transcoder = AudioTranscoder() + with create_data_for_test() as (audio_name, new_name): + transcoder.transcode(audio_name, new_name, mux_name='oggmux') + thumbnail = tempfile.NamedTemporaryFile(suffix='.jpg') + # fft_size below is copypasted from config_spec.ini + thumbnailer.spectrogram(new_name, thumbnail.name, width=100, + fft_size=4096) + assert imghdr.what(thumbnail.name) == 'jpeg' diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini index c351d3fc..6ac64321 100644 --- a/mediagoblin/tests/test_mgoblin_app.ini +++ b/mediagoblin/tests/test_mgoblin_app.ini @@ -36,4 +36,6 @@ BROKER_URL = "sqlite:///%(here)s/test_user_dev/kombu.db" [[mediagoblin.plugins.basic_auth]] [[mediagoblin.plugins.openid]] [[mediagoblin.media_types.image]] +[[mediagoblin.media_types.video]] +[[mediagoblin.media_types.audio]] [[mediagoblin.media_types.pdf]] diff --git a/mediagoblin/tests/test_submission.py b/mediagoblin/tests/test_submission.py index 03d255fb..65c4b3a3 100644 --- a/mediagoblin/tests/test_submission.py +++ b/mediagoblin/tests/test_submission.py @@ -26,7 +26,14 @@ import pytest import six.moves.urllib.parse as urlparse +# this gst initialization stuff is really required here +import gi +gi.require_version('Gst', '1.0') +from gi.repository import Gst +Gst.init(None) + from mediagoblin.tests.tools import fixture_add_user +from .media_tools import create_av from mediagoblin import mg_globals from mediagoblin.db.models import MediaEntry, User from mediagoblin.db.base import Session @@ -365,6 +372,18 @@ class TestSubmission: media = self.check_media(None, {"title": u"With GPS data"}, 1) assert media.get_location.position["latitude"] == 59.336666666666666 + def test_audio(self): + with create_av(make_audio=True) as path: + self.check_normal_upload('Audio', path) + + def test_video(self): + with create_av(make_video=True) as path: + self.check_normal_upload('Video', path) + + def test_audio_and_video(self): + with create_av(make_audio=True, make_video=True) as path: + self.check_normal_upload('Audio and Video', path) + def test_processing(self): public_store_dir = mg_globals.global_config[ 'storage:publicstore']['base_dir'] diff --git a/mediagoblin/tests/test_video.py b/mediagoblin/tests/test_video.py new file mode 100644 index 00000000..79244515 --- /dev/null +++ b/mediagoblin/tests/test_video.py @@ -0,0 +1,132 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2013 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import tempfile +import os +from contextlib import contextmanager +import imghdr + +#os.environ['GST_DEBUG'] = '4,python:4' +import pytest +pytest.importorskip("gi.repository.Gst") + +import gi +gi.require_version('Gst', '1.0') +from gi.repository import Gst +Gst.init(None) + +from mediagoblin.media_types.video.transcoders import (capture_thumb, + VideoTranscoder) +from mediagoblin.media_types.tools import discover + +@contextmanager +def create_data(suffix=None, make_audio=False): + video = tempfile.NamedTemporaryFile() + src = Gst.ElementFactory.make('videotestsrc', None) + src.set_property('num-buffers', 10) + videorate = Gst.ElementFactory.make('videorate', None) + enc = Gst.ElementFactory.make('theoraenc', None) + mux = Gst.ElementFactory.make('oggmux', None) + dst = Gst.ElementFactory.make('filesink', None) + dst.set_property('location', video.name) + pipeline = Gst.Pipeline() + pipeline.add(src) + pipeline.add(videorate) + pipeline.add(enc) + pipeline.add(mux) + pipeline.add(dst) + src.link(videorate) + videorate.link(enc) + enc.link(mux) + mux.link(dst) + if make_audio: + audio_src = Gst.ElementFactory.make('audiotestsrc', None) + audio_src.set_property('num-buffers', 10) + audiorate = Gst.ElementFactory.make('audiorate', None) + audio_enc = Gst.ElementFactory.make('vorbisenc', None) + pipeline.add(audio_src) + pipeline.add(audio_enc) + pipeline.add(audiorate) + audio_src.link(audiorate) + audiorate.link(audio_enc) + audio_enc.link(mux) + pipeline.set_state(Gst.State.PLAYING) + state = pipeline.get_state(3 * Gst.SECOND) + assert state[0] == Gst.StateChangeReturn.SUCCESS + bus = pipeline.get_bus() + message = bus.timed_pop_filtered( + 3 * Gst.SECOND, + Gst.MessageType.ERROR | Gst.MessageType.EOS) + pipeline.set_state(Gst.State.NULL) + if suffix: + result = tempfile.NamedTemporaryFile(suffix=suffix) + else: + result = tempfile.NamedTemporaryFile() + yield (video.name, result.name) + + +#TODO: this should be skipped if video plugin is not enabled +def test_thumbnails(): + ''' + Test thumbnails generation. + 1. Create a video (+audio) from gst's videotestsrc + 2. Capture thumbnail + 3. Everything should get removed because of temp files usage + ''' + #data create_data() as (video_name, thumbnail_name): + test_formats = [('.png', 'png'), ('.jpg', 'jpeg'), ('.gif', 'gif')] + for suffix, format in test_formats: + with create_data(suffix) as (video_name, thumbnail_name): + capture_thumb(video_name, thumbnail_name, width=40) + # check result file format + assert imghdr.what(thumbnail_name) == format + # TODO: check height and width + # FIXME: it doesn't work with small width, say, 10px. This should be + # fixed somehow + suffix, format = test_formats[0] + with create_data(suffix, True) as (video_name, thumbnail_name): + capture_thumb(video_name, thumbnail_name, width=40) + assert imghdr.what(thumbnail_name) == format + with create_data(suffix, True) as (video_name, thumbnail_name): + capture_thumb(video_name, thumbnail_name, width=10) # smaller width + assert imghdr.what(thumbnail_name) == format + with create_data(suffix, True) as (video_name, thumbnail_name): + capture_thumb(video_name, thumbnail_name, width=100) # bigger width + assert imghdr.what(thumbnail_name) == format + + +def test_transcoder(): + # test without audio + with create_data() as (video_name, result_name): + transcoder = VideoTranscoder() + transcoder.transcode( + video_name, result_name, + vp8_quality=8, + vp8_threads=0, # autodetect + vorbis_quality=0.3, + dimensions=(640, 640)) + assert len(discover(result_name).get_video_streams()) == 1 + # test with audio + with create_data(make_audio=True) as (video_name, result_name): + transcoder = VideoTranscoder() + transcoder.transcode( + video_name, result_name, + vp8_quality=8, + vp8_threads=0, # autodetect + vorbis_quality=0.3, + dimensions=(640, 640)) + assert len(discover(result_name).get_video_streams()) == 1 + assert len(discover(result_name).get_audio_streams()) == 1 |