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 BB |
22 | #os.environ['GST_DEBUG'] = '4,python:4' |
23 | ||
7e266d5a | 24 | #TODO: this should be skipped if video plugin is not enabled |
91f5f5e7 BB |
25 | import gi |
26 | gi.require_version('Gst', '1.0') | |
27 | from gi.repository import Gst | |
28 | Gst.init(None) | |
7e266d5a | 29 | |
91f5f5e7 BB |
30 | from mediagoblin.media_types.video.transcoders import (capture_thumb, |
31 | VideoTranscoder) | |
32 | from mediagoblin.media_types.tools import discover | |
7e266d5a BB |
33 | |
34 | @contextmanager | |
91f5f5e7 | 35 | def create_data(suffix=None, make_audio=False): |
7e266d5a | 36 | video = tempfile.NamedTemporaryFile() |
91f5f5e7 BB |
37 | src = Gst.ElementFactory.make('videotestsrc', None) |
38 | src.set_property('num-buffers', 10) | |
39 | videorate = Gst.ElementFactory.make('videorate', None) | |
40 | enc = Gst.ElementFactory.make('theoraenc', None) | |
41 | mux = Gst.ElementFactory.make('oggmux', None) | |
42 | dst = Gst.ElementFactory.make('filesink', None) | |
7e266d5a | 43 | dst.set_property('location', video.name) |
91f5f5e7 BB |
44 | pipeline = Gst.Pipeline() |
45 | pipeline.add(src) | |
46 | pipeline.add(videorate) | |
47 | pipeline.add(enc) | |
48 | pipeline.add(mux) | |
49 | pipeline.add(dst) | |
50 | src.link(videorate) | |
51 | videorate.link(enc) | |
52 | enc.link(mux) | |
53 | mux.link(dst) | |
54 | if make_audio: | |
55 | audio_src = Gst.ElementFactory.make('audiotestsrc', None) | |
56 | audio_src.set_property('num-buffers', 10) | |
57 | audiorate = Gst.ElementFactory.make('audiorate', None) | |
58 | audio_enc = Gst.ElementFactory.make('vorbisenc', None) | |
59 | pipeline.add(audio_src) | |
60 | pipeline.add(audio_enc) | |
61 | pipeline.add(audiorate) | |
62 | audio_src.link(audiorate) | |
63 | audiorate.link(audio_enc) | |
64 | audio_enc.link(mux) | |
65 | pipeline.set_state(Gst.State.PLAYING) | |
66 | state = pipeline.get_state(3 * Gst.SECOND) | |
67 | assert state[0] == Gst.StateChangeReturn.SUCCESS | |
7e266d5a | 68 | bus = pipeline.get_bus() |
91f5f5e7 BB |
69 | message = bus.timed_pop_filtered( |
70 | 3 * Gst.SECOND, | |
71 | Gst.MessageType.ERROR | Gst.MessageType.EOS) | |
72 | pipeline.set_state(Gst.State.NULL) | |
73 | if suffix: | |
74 | result = tempfile.NamedTemporaryFile(suffix=suffix) | |
75 | else: | |
76 | result = tempfile.NamedTemporaryFile() | |
77 | yield (video.name, result.name) | |
7e266d5a BB |
78 | |
79 | ||
80 | #TODO: this should be skipped if video plugin is not enabled | |
81 | def test_thumbnails(): | |
82 | ''' | |
83 | Test thumbnails generation. | |
91f5f5e7 BB |
84 | 1. Create a video (+audio) from gst's videotestsrc |
85 | 2. Capture thumbnail | |
86 | 3. Everything should get removed because of temp files usage | |
7e266d5a BB |
87 | ''' |
88 | #data create_data() as (video_name, thumbnail_name): | |
89 | test_formats = [('.png', 'png'), ('.jpg', 'jpeg'), ('.gif', 'gif')] | |
90 | for suffix, format in test_formats: | |
91 | with create_data(suffix) as (video_name, thumbnail_name): | |
92 | capture_thumb(video_name, thumbnail_name, width=40) | |
91f5f5e7 | 93 | # check result file format |
7e266d5a BB |
94 | assert imghdr.what(thumbnail_name) == format |
95 | # TODO: check height and width | |
96 | # FIXME: it doesn't work with small width, say, 10px. This should be | |
97 | # fixed somehow | |
91f5f5e7 BB |
98 | suffix, format = test_formats[0] |
99 | with create_data(suffix, True) as (video_name, thumbnail_name): | |
100 | capture_thumb(video_name, thumbnail_name, width=40) | |
101 | assert imghdr.what(thumbnail_name) == format | |
102 | with create_data(suffix, True) as (video_name, thumbnail_name): | |
103 | capture_thumb(video_name, thumbnail_name, width=10) # smaller width | |
104 | assert imghdr.what(thumbnail_name) == format | |
105 | with create_data(suffix, True) as (video_name, thumbnail_name): | |
106 | capture_thumb(video_name, thumbnail_name, width=100) # bigger width | |
107 | assert imghdr.what(thumbnail_name) == format | |
108 | ||
109 | ||
110 | def test_transcoder(): | |
111 | # test without audio | |
112 | with create_data() as (video_name, result_name): | |
113 | transcoder = VideoTranscoder() | |
114 | transcoder.transcode( | |
115 | video_name, result_name, | |
116 | vp8_quality=8, | |
117 | vp8_threads=0, # autodetect | |
118 | vorbis_quality=0.3, | |
119 | dimensions=(640, 640)) | |
120 | assert len(discover(result_name).get_video_streams()) == 1 | |
121 | # test with audio | |
122 | with create_data(make_audio=True) as (video_name, result_name): | |
123 | transcoder = VideoTranscoder() | |
124 | transcoder.transcode( | |
125 | video_name, result_name, | |
126 | vp8_quality=8, | |
127 | vp8_threads=0, # autodetect | |
128 | vorbis_quality=0.3, | |
129 | dimensions=(640, 640)) | |
130 | assert len(discover(result_name).get_video_streams()) == 1 | |
131 | assert len(discover(result_name).get_audio_streams()) == 1 |