1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import gobject
19 import gst
20
21 from flumotion.common import messages, gstreamer
22 from flumotion.common.i18n import N_, gettexter
23 from flumotion.component import feedcomponent
24 from flumotion.component.converters.overlay import genimg
25
26 __version__ = "$Rev$"
27 T_ = gettexter()
28
29
30
31
32
34 __gstdetails__ = ('FluOverlaySrc', 'Source',
35 'Overlay Image source for flumotion', 'Zaheer Merali')
36 __gsttemplates__ = (
37 gst.PadTemplate("src",
38 gst.PAD_SRC,
39 gst.PAD_ALWAYS,
40 gst.caps_new_any()))
41 imgBuf = ""
42 capsStr = ""
43 duration = 1.0/25
44
46 gst.BaseSrc.__init__(self)
47 self.set_format(gst.FORMAT_TIME)
48
57
58
59 -class Overlay(feedcomponent.ParseLaunchComponent):
60 checkTimestamp = True
61 checkOffset = True
62 _filename = None
63 CAPS_TEMPLATE = "video/x-raw-rgb,bpp=32,depth=32,width=%d,height=%d," \
64 "red_mask=-16777216,green_mask=16711680,blue_mask=65280," \
65 "alpha_mask=255,endianness=4321,framerate=0/1"
66
68 pipeline = ('@eater:default@ ! ffmpegcolorspace !'
69 'video/x-raw-yuv,format=(fourcc)AYUV ! videomixer name=mix !'
70 '@feeder:default@')
71 return pipeline
72
74 imgBuf, imagesOverflowed, textOverflowed = \
75 genimg.generateOverlay(
76 text=self.text,
77 font=self.font,
78 showFlumotion=self.showFlumotion,
79 showCC=self.showCC,
80 showXiph=self.showXiph,
81 width=width, height=height)
82
83 if textOverflowed:
84 m = messages.Warning(
85 T_(N_("Overlayed text '%s' too wide for the video image."),
86 self.text), mid="text-too-wide")
87 self.addMessage(m)
88
89 if imagesOverflowed:
90 m = messages.Warning(
91 T_(N_("Overlayed logotypes too wide for the video image.")),
92 mid="image-too-wide")
93 self.addMessage(m)
94
95 if self.source.get_factory().get_name() == 'appsrc':
96 self.imgBuf = imgBuf
97 else:
98 self.source.imgBuf = imgBuf
99
106
111
113 caps = pad.get_negotiated_caps()
114 if caps is None:
115 return
116 struct = pad.get_negotiated_caps().get_structure(0)
117 height = struct['height']
118 width = struct['width']
119 framerate = struct['framerate']
120
121 self._set_source_image(width, height)
122 self._set_source_caps(width, height)
123 self._set_source_framerate(framerate)
124
125 if not self.sourceBin.get_pad("src").is_linked():
126 self.sourceBin.link_filtered(self.videomixer,
127 gst.Caps("video/x-raw-yuv, format=(fourcc)AYUV"))
128 self.sourceBin.set_locked_state(False)
129 self.sourceBin.set_state(gst.STATE_PLAYING)
130
132 if gstreamer.element_factory_exists("appsrc") and \
133 gstreamer.get_plugin_version("app") >= (0, 10, 22, 0):
134 self.source = gst.element_factory_make('appsrc', 'source')
135 self.source.set_property('do-timestamp', True)
136 self.source.connect('need-data', self.push_buffer)
137 else:
138
139 gobject.type_register(OverlayImageSource)
140 gst.element_register(OverlayImageSource, "fluoverlaysrc",
141 gst.RANK_MARGINAL)
142 self.source = gst.element_factory_make('fluoverlaysrc', 'source')
143
144 self.sourceBin = gst.Bin()
145
146 alphacolor = gst.element_factory_make('alphacolor')
147
148 self.sourceBin.add_many(self.source, alphacolor)
149 self.source.link(alphacolor)
150 pipeline.add(self.sourceBin)
151
152 self.sourceBin.add_pad(gst.GhostPad('src', alphacolor.get_pad('src')))
153
154
155 self.sourceBin.set_locked_state(True)
156
197
199 """
200 Pushes buffer to appsrc in GStreamer
201
202 @param source: the appsrc element to push to
203 @type source: GstElement
204 """
205 self.log("Pushing buffer")
206 gstBuf = gst.Buffer(self.imgBuf)
207 padcaps = gst.caps_from_string(self.capsStr)
208 gstBuf.set_caps(padcaps)
209 gstBuf.duration = int(self.duration * gst.SECOND)
210 source.emit('push-buffer', gstBuf)
211