summaryrefslogtreecommitdiff
path: root/voctocore/videomix.py
blob: 8cc3cb941326906ee900709e7bdfa5eed792d318 (plain)
  1. import sys, inspect, math
  2. from pprint import pprint
  3. from gi.repository import GLib, Gst
  4. class Videomix:
  5. decoder = []
  6. mixerpads = []
  7. def __init__(self):
  8. self.pipeline = Gst.Pipeline()
  9. # create audio and video mixer
  10. mixerbin = self.createMixer()
  11. # collection of video-sources to connect to the quadmix
  12. quadmixSources = []
  13. # create camera sources
  14. for camberabin in self.createDummyCamSources():
  15. # link camerasource to audiomixer
  16. camberabin.get_by_name('audio_src').link(self.pipeline.get_by_name('liveaudio'))
  17. # inject a ×2 distributor and link one end to the live-mixer
  18. distributor = self.createDistributor(camberabin.get_by_name('video_src'))
  19. distributor.get_by_name('a').link(self.pipeline.get_by_name('livevideo'))
  20. # collect the other end to add it later to the quadmix
  21. quadmixSources.append(distributor.get_by_name('b'))
  22. # would generate pause & slides with another generator which only
  23. # yields if the respective fil are there and which only have a video-pad
  24. self.addVideosToQuadmix(quadmixSources, self.pipeline.get_by_name('quadmix'))
  25. # demonstrate some control
  26. liveaudio = self.pipeline.get_by_name('liveaudio')
  27. liveaudio.set_property('active-pad', liveaudio.get_static_pad('sink_0'))
  28. livevideo = self.pipeline.get_by_name('livevideo')
  29. pad = livevideo.get_static_pad('sink_1')
  30. pad.set_property('alpha', 0.5)
  31. self.pipeline.set_state(Gst.State.PLAYING)
  32. def createMixer(self):
  33. mixerbin = Gst.parse_bin_from_description("""
  34. videomixer name=livevideo ! autovideosink
  35. input-selector name=liveaudio ! autoaudiosink
  36. videomixer name=quadmix ! autovideosink
  37. """, False)
  38. self.pipeline.add(mixerbin)
  39. return mixerbin
  40. def addVideosToQuadmix(self, videosources, quadmix):
  41. count = len(videosources)
  42. rows = math.ceil(math.sqrt(count))
  43. cols = math.ceil(count / rows)
  44. for videosource in videosources:
  45. # define size somewhere, scale and place here
  46. videosource.link(quadmix)
  47. def createDistributor(self, videosource):
  48. distributor = Gst.parse_bin_from_description("""
  49. tee name=t
  50. t. ! queue name=a
  51. t. ! queue name=b
  52. """, False)
  53. self.pipeline.add(distributor)
  54. videosource.link(distributor.get_by_name('t'))
  55. return distributor
  56. def createDummyCamSources(self):
  57. uris = ('file:///home/peter/122.mp4', 'file:///home/peter/10025.mp4',)
  58. for idx, uri in enumerate(uris):
  59. # create a bin for camera input
  60. camberabin = Gst.parse_bin_from_description("""
  61. uridecodebin name=input
  62. input. ! videoconvert ! videoscale ! videorate ! video/x-raw,width=1024,height=576,framerate=25/1 ! identity name=video_src
  63. input. ! audioconvert name=audio_src
  64. """, False)
  65. # configure camera input
  66. camberabin.get_by_name('input').set_property('uri', uri)
  67. # pass bin upstream
  68. self.pipeline.add(camberabin)
  69. yield camberabin
  70. def createCamSources(self):
  71. for cam in range(2):
  72. # create a bin for camera input
  73. camberabin = Gst.parse_bin_from_description("""
  74. decklinksrc name=input input=sdi input-mode=1080p25
  75. input. ! videoconvert ! videoscale ! videorate ! video/x-raw,width=1920,height=1080,framerate=25/1 ! identity name=video_src
  76. input. ! audioconvert name=audio_src
  77. """, False)
  78. # configure camera input
  79. camberabin.get_by_name('input').set_property('subdevice', cam)
  80. # pass bin upstream
  81. self.pipeline.add(camberabin)
  82. yield camberabin