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