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