76
def __init__(self, filename):
77
def __init__(self, filename, max_interleave=1.0):
79
filename: str; absolute path of the file to be discovered.
80
max_interleave: int or float; the maximum frame interleave in seconds.
81
The value must be greater than the input file frame interleave
82
or the discoverer may not find out all input file's streams.
83
The default value is 1 second and you shouldn't have to change it,
84
changing it mean larger discovering time and bigger memory usage.
77
86
gobject.GObject.__init__(self)
79
88
self.mimetype = None
123
134
self.typefind.connect("have-type", self._have_type_cb)
124
135
self.dbin.connect("new-decoded-pad", self._new_decoded_pad_cb)
136
self.dbin.connect("no-more-pads", self._no_more_pads_cb)
125
137
self.dbin.connect("unknown-type", self._unknown_type_cb)
139
def _timed_out_or_eos(self):
140
if (not self.is_audio and not self.is_video) or \
141
(self.is_audio and not self.audiocaps) or \
142
(self.is_video and not self.videocaps):
143
self._finished(False)
127
147
def _finished(self, success=False):
128
148
self.debug("success:%d" % success)
129
149
self._success = success
140
160
self.set_state(gst.STATE_READY)
141
161
self.debug("about to emit signal")
142
162
self.emit('discovered', self._success)
145
164
def _bus_message_cb(self, bus, message):
146
165
if message.type == gst.MESSAGE_EOS:
166
self.debug("Got EOS")
167
self._timed_out_or_eos()
148
168
elif message.type == gst.MESSAGE_TAG:
149
169
for key in message.parse_tag().keys():
150
170
self.tags[key] = message.structure[key]
151
171
elif message.type == gst.MESSAGE_ERROR:
172
self.debug("Got error")
154
175
def discover(self):
163
184
self.bus.connect("message", self._bus_message_cb)
166
self._timeoutid = gobject.timeout_add(3000, self._finished)
187
self._timeoutid = gobject.timeout_add(3000, self._timed_out_or_eos)
168
189
self.info("setting to PLAY")
169
190
if not self.set_state(gst.STATE_PLAYING):
219
240
for tag in self.tags.keys():
220
241
print "%20s :\t" % tag, self.tags[tag]
243
def _no_more_pads_cb(self, dbin):
244
self.info("no more pads")
245
self._nomorepads = True
222
247
def _unknown_type_cb(self, dbin, pad, caps):
223
248
self.debug("unknown type : %s" % caps.to_string())
224
249
# if we get an unknown type and we don't already have an
237
262
pad.info("no negotiated caps available")
239
pad.info("caps:%s" % caps.to_string)
264
pad.info("caps:%s" % caps.to_string())
240
265
# the caps are fixed
241
266
# We now get the total length of that stream
242
267
q = gst.query_new_duration(gst.FORMAT_TIME)
267
292
self.videowidth = caps[0]["width"]
268
293
self.videoheight = caps[0]["height"]
269
294
self.videorate = caps[0]["framerate"]
270
if (not self.is_audio) or self.audiocaps:
295
if self._nomorepads and ((not self.is_audio) or self.audiocaps):
271
296
self._finished(True)
273
298
def _new_decoded_pad_cb(self, dbin, pad, is_last):
282
307
self.warning("got a different caps.. %s" % caps.to_string())
284
309
if is_last and not self.is_video and not self.is_audio:
310
self.debug("is last, not video or audio")
285
311
self._finished(False)
287
313
# we connect a fakesink to the new pad...
288
314
pad.info("adding queue->fakesink")
289
fakesink = gst.element_factory_make("fakesink")
315
fakesink = gst.element_factory_make("fakesink", "fakesink%d-%s" %
316
(self.sinknumber, "audio" in caps.to_string() and "audio" or "video"))
290
318
queue = gst.element_factory_make("queue")
291
# we want the queue to buffer up to 2 seconds of data before outputting
292
# This enables us to cope with formats that don't create their source
293
# pads straight away, but instead wait for the first buffer of that
295
queue.props.min_threshold_time = 1 * gst.SECOND
296
queue.props.max_size_time = 2 * gst.SECOND
319
# we want the queue to buffer up to the specified amount of data
320
# before outputting. This enables us to cope with formats
321
# that don't create their source pads straight away,
322
# but instead wait for the first buffer of that stream.
323
# The specified time must be greater than the input file
324
# frame interleave for the discoverer to work properly.
325
queue.props.min_threshold_time = int(self._max_interleave * gst.SECOND)
326
queue.props.max_size_time = int(2 * self._max_interleave * gst.SECOND)
297
327
queue.props.max_size_bytes = 0
299
329
# If durations are bad on the buffers (common for video decoders), we'll
300
# never reach the min_threshold_time or max_size_time. So, set a large
330
# never reach the min_threshold_time or max_size_time. So, set a
301
331
# max size in buffers, and if reached, disable the min_threshold_time.
302
332
# This ensures we don't fail to discover with various ffmpeg
303
333
# demuxers/decoders that provide bogus (or no) duration.
304
queue.props.max_size_buffers = 100
334
queue.props.max_size_buffers = int(100 * self._max_interleave)
305
335
def _disable_min_threshold_cb(queue):
306
336
queue.props.min_threshold_time = 0
307
337
queue.disconnect(signal_id)