Commit | Line | Data |
---|---|---|
7e266d5a BB |
1 | # GNU MediaGoblin -- federated, autonomous media hosting |
2 | # Copyright (C) 2013 MediaGoblin contributors. See AUTHORS. | |
3 | # | |
4 | # This program is free software: you can redistribute it and/or modify | |
5 | # it under the terms of the GNU Affero General Public License as published by | |
6 | # the Free Software Foundation, either version 3 of the License, or | |
7 | # (at your option) any later version. | |
8 | # | |
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU Affero General Public License for more details. | |
13 | # | |
14 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
17 | import tempfile | |
7e266d5a | 18 | import os |
7e266d5a | 19 | from contextlib import contextmanager |
7e266d5a BB |
20 | import imghdr |
21 | ||
91f5f5e7 | 22 | #os.environ['GST_DEBUG'] = '4,python:4' |
fd365db4 BB |
23 | import pytest |
24 | pytest.importorskip("gi.repository.Gst") | |
91f5f5e7 | 25 | |
91f5f5e7 BB |
26 | import gi |
27 | gi.require_version('Gst', '1.0') | |
28 | from gi.repository import Gst | |
29 | Gst.init(None) | |
7e266d5a | 30 | |
91f5f5e7 BB |
31 | from mediagoblin.media_types.video.transcoders import (capture_thumb, |
32 | VideoTranscoder) | |
33 | from mediagoblin.media_types.tools import discover | |
7e266d5a BB |
34 | |
35 | @contextmanager | |
91f5f5e7 | 36 | def create_data(suffix=None, make_audio=False): |
7e266d5a | 37 | video = tempfile.NamedTemporaryFile() |
91f5f5e7 BB |
38 | src = Gst.ElementFactory.make('videotestsrc', None) |
39 | src.set_property('num-buffers', 10) | |
40 | videorate = Gst.ElementFactory.make('videorate', None) | |
41 | enc = Gst.ElementFactory.make('theoraenc', None) | |
42 | mux = Gst.ElementFactory.make('oggmux', None) | |
43 | dst = Gst.ElementFactory.make('filesink', None) | |
7e266d5a | 44 | dst.set_property('location', video.name) |
91f5f5e7 BB |
45 | pipeline = Gst.Pipeline() |
46 | pipeline.add(src) | |
47 | pipeline.add(videorate) | |
48 | pipeline.add(enc) | |
49 | pipeline.add(mux) | |
50 | pipeline.add(dst) | |
51 | src.link(videorate) | |
52 | videorate.link(enc) | |
53 | enc.link(mux) | |
54 | mux.link(dst) | |
55 | if make_audio: | |
56 | audio_src = Gst.ElementFactory.make('audiotestsrc', None) | |
57 | audio_src.set_property('num-buffers', 10) | |
58 | audiorate = Gst.ElementFactory.make('audiorate', None) | |
59 | audio_enc = Gst.ElementFactory.make('vorbisenc', None) | |
60 | pipeline.add(audio_src) | |
61 | pipeline.add(audio_enc) | |
62 | pipeline.add(audiorate) | |
63 | audio_src.link(audiorate) | |
64 | audiorate.link(audio_enc) | |
65 | audio_enc.link(mux) | |
66 | pipeline.set_state(Gst.State.PLAYING) | |
67 | state = pipeline.get_state(3 * Gst.SECOND) | |
68 | assert state[0] == Gst.StateChangeReturn.SUCCESS | |
7e266d5a | 69 | bus = pipeline.get_bus() |
91f5f5e7 BB |
70 | message = bus.timed_pop_filtered( |
71 | 3 * Gst.SECOND, | |
72 | Gst.MessageType.ERROR | Gst.MessageType.EOS) | |
73 | pipeline.set_state(Gst.State.NULL) | |
74 | if suffix: | |
75 | result = tempfile.NamedTemporaryFile(suffix=suffix) | |
76 | else: | |
77 | result = tempfile.NamedTemporaryFile() | |
78 | yield (video.name, result.name) | |
7e266d5a BB |
79 | |
80 | ||
81 | #TODO: this should be skipped if video plugin is not enabled | |
82 | def test_thumbnails(): | |
83 | ''' | |
84 | Test thumbnails generation. | |
91f5f5e7 BB |
85 | 1. Create a video (+audio) from gst's videotestsrc |
86 | 2. Capture thumbnail | |
87 | 3. Everything should get removed because of temp files usage | |
7e266d5a BB |
88 | ''' |
89 | #data create_data() as (video_name, thumbnail_name): | |
90 | test_formats = [('.png', 'png'), ('.jpg', 'jpeg'), ('.gif', 'gif')] | |
91 | for suffix, format in test_formats: | |
92 | with create_data(suffix) as (video_name, thumbnail_name): | |
93 | capture_thumb(video_name, thumbnail_name, width=40) | |
91f5f5e7 | 94 | # check result file format |
7e266d5a BB |
95 | assert imghdr.what(thumbnail_name) == format |
96 | # TODO: check height and width | |
97 | # FIXME: it doesn't work with small width, say, 10px. This should be | |
98 | # fixed somehow | |
91f5f5e7 BB |
99 | suffix, format = test_formats[0] |
100 | with create_data(suffix, True) as (video_name, thumbnail_name): | |
101 | capture_thumb(video_name, thumbnail_name, width=40) | |
102 | assert imghdr.what(thumbnail_name) == format | |
103 | with create_data(suffix, True) as (video_name, thumbnail_name): | |
104 | capture_thumb(video_name, thumbnail_name, width=10) # smaller width | |
105 | assert imghdr.what(thumbnail_name) == format | |
106 | with create_data(suffix, True) as (video_name, thumbnail_name): | |
107 | capture_thumb(video_name, thumbnail_name, width=100) # bigger width | |
108 | assert imghdr.what(thumbnail_name) == format | |
109 | ||
110 | ||
111 | def test_transcoder(): | |
112 | # test without audio | |
113 | with create_data() as (video_name, result_name): | |
114 | transcoder = VideoTranscoder() | |
115 | transcoder.transcode( | |
116 | video_name, result_name, | |
117 | vp8_quality=8, | |
118 | vp8_threads=0, # autodetect | |
119 | vorbis_quality=0.3, | |
120 | dimensions=(640, 640)) | |
121 | assert len(discover(result_name).get_video_streams()) == 1 | |
122 | # test with audio | |
123 | with create_data(make_audio=True) as (video_name, result_name): | |
124 | transcoder = VideoTranscoder() | |
125 | transcoder.transcode( | |
126 | video_name, result_name, | |
127 | vp8_quality=8, | |
128 | vp8_threads=0, # autodetect | |
129 | vorbis_quality=0.3, | |
130 | dimensions=(640, 640)) | |
131 | assert len(discover(result_name).get_video_streams()) == 1 | |
132 | assert len(discover(result_name).get_audio_streams()) == 1 |