1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 """
22 Smart video scaler
23 """
24
25
26
27
28
29
30
31
32
33 import gobject
34 import gst
35
36 __version__ = "$Rev$"
37
38
40 """
41 Element to do proper videoscale.
42 Keeps Display Aspect Ratio.
43 Adds black borders if needed.
44 """
45
47 gst.Bin.__init__(self)
48 self.videoscale = gst.element_factory_make(
49 "videoscale", "smart-videoscale")
50
51
52
53
54
55 self.videoscale.props.method = 1
56 self.videobox = gst.element_factory_make(
57 "videobox", "smart-videobox")
58 self.capsfilter = gst.element_factory_make(
59 "capsfilter", "smart-capsfilter")
60 self.add(self.videoscale, self.capsfilter, self.videobox)
61 gst.element_link_many(self.videoscale, self.capsfilter, self.videobox)
62
63 self._sinkPad = gst.GhostPad("sink", self.videoscale.get_pad("sink"))
64 self._sinkPad.set_active(True)
65 self._srcPad = gst.GhostPad("src", self.videobox.get_pad("src"))
66 self._srcPad.set_active(True)
67
68 self.add_pad(self._sinkPad)
69 self.add_pad(self._srcPad)
70
71 self._sinkPad.set_setcaps_function(self._sinkSetCaps)
72
73
74
75 self.capsin = None
76 self.widthin = -1
77 self.heightin = -1
78 self.parin = gst.Fraction(1, 1)
79 self.darin = gst.Fraction(1, 1)
80 self.capsout = None
81 self.widthout = -1
82 self.heightout = -1
83 self.parout = gst.Fraction(1, 1)
84 self.darout = gst.Fraction(1, 1)
85
87 """ set the outgoing caps, because gst.BaseTransform
88 is full of CRACK ! """
89 (self.widthout,
90 self.heightout,
91 self.parout,
92 self.darout) = self._getValuesFromCaps(caps, True)
93
103
115
125
135
137 """
138 returns (width, height, par, dar) from given caps.
139 If caps are None, or not negotiated, it will return
140 (-1, -1, gst.Fraction(1,1), gst.Fraction(1,1))
141 """
142 width = -1
143 height = -1
144 par = gst.Fraction(1, 1)
145 dar = gst.Fraction(1, 1)
146 if force or (caps and caps.is_fixed()):
147 struc = caps[0]
148 width = struc["width"]
149 height = struc["height"]
150 if struc.has_field('pixel-aspect-ratio'):
151 par = struc['pixel-aspect-ratio']
152 dar = gst.Fraction(width * par.num, height * par.denom)
153 return (width, height, par, dar)
154
156 """ Calculate the new values to set on capsfilter and videobox. """
157 if (self.widthin == -1 or self.heightin == -1 or
158 self.widthout == -1 or self.heightout == -1):
159
160 self.error(
161 "We don't have input and output caps, "
162 "we can't calculate videobox values")
163 return
164
165 self.log("incoming width/height/PAR/DAR : %d/%d/%r/%r" % (
166 self.widthin, self.heightin,
167 self.parin, self.darin))
168 self.log("outgoing width/height/PAR/DAR : %d/%d/%r/%r" % (
169 self.widthout, self.heightout,
170 self.parout, self.darout))
171
172 if self.darin == self.darout:
173 self.log(
174 "We have same input and output caps, "
175 "resetting capsfilter and videobox settings")
176
177 caps = gst.caps_new_any()
178 left = 0
179 right = 0
180 top = 0
181 bottom = 0
182 else:
183 par = self.parout
184 dar = self.darin
185 fdarin = float(self.darin.num) / float(self.darin.denom)
186 fdarout = float(self.darout.num) / float(self.darout.denom)
187 if fdarin > fdarout:
188 self.log("incoming DAR is greater that ougoing DAR. "
189 "Adding top/bottom borders")
190
191
192 newheight = ((par.num * self.widthout * dar.denom) /
193 (par.denom * dar.num))
194 self.log("newheight should be %d" % newheight)
195 extra = self.heightout - newheight
196 top = extra / 2
197 bottom = extra - top
198 left = right = 0
199
200 astr = "width=%d,height=%d" % (self.widthout, newheight)
201 else:
202 self.log("incoming DAR is smaller than outgoing DAR. "
203 "Adding left/right borders")
204
205
206 newwidth = ((dar.num * self.heightout * par.denom) /
207 (dar.denom * par.num))
208 self.log("newwidth should be %d" % newwidth)
209 extra = self.widthout - newwidth
210 left = extra / 2
211 right = extra - left
212 top = bottom = 0
213
214 astr = "width=%d,height=%d" % (newwidth, self.heightout)
215 caps = gst.caps_from_string(
216 "video/x-raw-yuv,%s;video/x-raw-rgb,%s" % (astr, astr))
217
218
219 self.debug(
220 "About to set left/right/top/bottom : %d/%d/%d/%d" % (
221 -left, -right, -top, -bottom))
222 self.videobox.props.left = -left
223 self.videobox.props.right = -right
224 self.videobox.props.top = -top
225 self.videobox.props.bottom = -bottom
226 self.debug("Settings filter caps %s" % caps.to_string())
227 self.capsfilter.props.caps = caps
228 self.debug("done")
229
230 gobject.type_register(SmartVideoScale)
231