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 """
28 Smart video scaler
29 """
30
31
32
33
34
35
36
37
38
39 import gobject
40 import gst
41
43 """
44 Element to do proper videoscale.
45 Keeps Display Aspect Ratio.
46 Adds black borders if needed.
47 """
48
50 gst.Bin.__init__(self)
51 self.videoscale = gst.element_factory_make("videoscale", "smart-videoscale")
52
53
54
55
56 self.videoscale.props.method = 1
57 self.videobox = gst.element_factory_make("videobox", "smart-videobox")
58 self.capsfilter = gst.element_factory_make("capsfilter", "smart-capsfilter")
59 self.add(self.videoscale, self.capsfilter, self.videobox)
60 gst.element_link_many(self.videoscale, self.capsfilter, self.videobox)
61
62 self._sinkPad = gst.GhostPad("sink", self.videoscale.get_pad("sink"))
63 self._sinkPad.set_active(True)
64 self._srcPad = gst.GhostPad("src", self.videobox.get_pad("src"))
65 self._srcPad.set_active(True)
66
67 self.add_pad(self._sinkPad)
68 self.add_pad(self._srcPad)
69
70 self._sinkPad.set_setcaps_function(self._sinkSetCaps)
71
72
73
74 self.capsin = None
75 self.widthin = -1
76 self.heightin = -1
77 self.parin = gst.Fraction(1,1)
78 self.darin = gst.Fraction(1,1)
79 self.capsout = None
80 self.widthout = -1
81 self.heightout = -1
82 self.parout = gst.Fraction(1,1)
83 self.darout = gst.Fraction(1,1)
84
86 """ set the outgoing caps, because gst.BaseTransform is full of CRACK ! """
87 self.widthout, self.heightout, self.parout, self.darout = self._getValuesFromCaps(caps, True)
88
95
104
111
118
120 """
121 returns (width, height, par, dar) from given caps.
122 If caps are None, or not negotiated, it will return
123 (-1, -1, gst.Fraction(1,1), gst.Fraction(1,1))
124 """
125 width = -1
126 height = -1
127 par = gst.Fraction(1,1)
128 dar = gst.Fraction(1,1)
129 if force or (caps and caps.is_fixed()):
130 struc = caps[0]
131 width = struc["width"]
132 height = struc["height"]
133 if struc.has_field('pixel-aspect-ratio'):
134 par = struc['pixel-aspect-ratio']
135 dar = gst.Fraction(width * par.num, height * par.denom)
136 return (width, height, par, dar)
137
139 """ Calculate the new values to set on capsfilter and videobox. """
140 if self.widthin == -1 or self.heightin == -1 or self.widthout == -1 or self.heightout == -1:
141
142 self.error("We don't have input and output caps, we can't calculate videobox values")
143 return
144
145 self.log("incoming width/height/PAR/DAR : %d/%d/%r/%r" % (self.widthin, self.heightin,
146 self.parin, self.darin))
147 self.log("outgoing width/height/PAR/DAR : %d/%d/%r/%r" % (self.widthout, self.heightout,
148 self.parout, self.darout))
149
150 if self.darin == self.darout:
151 self.log("We have same input and output caps, resetting capsfilter and videobox settings")
152
153 caps = gst.caps_new_any()
154 left = 0
155 right = 0
156 top = 0
157 bottom = 0
158 else:
159 par = self.parout
160 dar = self.darin
161 fdarin = float(self.darin.num) / float(self.darin.denom)
162 fdarout = float(self.darout.num) / float(self.darout.denom)
163 if fdarin > fdarout:
164 self.log("incoming DAR is greater that ougoing DAR. Adding top/bottom borders")
165
166
167 newheight = (par.num * self.widthout * dar.denom) / (par.denom * dar.num)
168 self.log("newheight should be %d" % newheight)
169 extra = self.heightout - newheight
170 top = extra / 2
171 bottom = extra - top
172 left = right = 0
173
174 astr = "width=%d,height=%d" % (self.widthout, newheight)
175 else:
176 self.log("incoming DAR is smaller than outgoing DAR. Adding left/right borders")
177
178
179 newwidth = (dar.num * self.heightout * par.denom) / (dar.denom * par.num)
180 self.log("newwidth should be %d" % newwidth)
181 extra = self.widthout - newwidth
182 left = extra / 2
183 right = extra - left
184 top = bottom = 0
185
186 astr = "width=%d,height=%d" % (newwidth, self.heightout)
187 caps = gst.caps_from_string("video/x-raw-yuv,%s;video/x-raw-rgb,%s" % (astr, astr))
188
189
190 self.debug("About to set left/right/top/bottom : %d/%d/%d/%d" % (-left, -right, -top, -bottom))
191 self.videobox.props.left = -left
192 self.videobox.props.right = -right
193 self.videobox.props.top = -top
194 self.videobox.props.bottom = -bottom
195 self.debug("Settings filter caps %s" % caps.to_string())
196 self.capsfilter.props.caps = caps
197 self.debug("done")
198
199
200
201 gobject.type_register(SmartVideoScale)
202