test_video.py 5.1 KB

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