self.loop.quit()
-class DeprecatedVideoThumbnailer:
- '''
- Creates a video thumbnail
-
- - Sets up discoverer & transcoding pipeline.
- Discoverer finds out information about the media file
- - Launches gobject.MainLoop, this triggers the discoverer to start running
- - Once the discoverer is done, it calls the __discovered callback function
- - The __discovered callback function launches the transcoding process
- - The _on_message callback is called from the transcoding process until it
- gets a message of type gst.MESSAGE_EOS, then it calls __stop which shuts
- down the gobject.MainLoop
- '''
-
- WADSWORTH_CONSTANT = 30 # percent
-
- def __init__(self, src, dst, **kwargs):
- _log.info('Initializing VideoThumbnailer...')
-
- self.loop = gobject.MainLoop()
-
- self.source_path = src
- self.destination_path = dst
-
- self.destination_dimensions = kwargs.get('dimensions') or (180, 180)
-
- if not type(self.destination_dimensions) == tuple:
- raise Exception('dimensions must be tuple: (width, height)')
-
- self._setup()
- self._run()
-
- def _setup(self):
- self._setup_pipeline()
- self._setup_discover()
-
- def _run(self):
- _log.info('Discovering...')
- self.discoverer.discover()
- _log.info('Done')
-
- _log.debug('Initializing MainLoop()')
- self.loop.run()
-
- def _setup_discover(self):
- self.discoverer = discoverer.Discoverer(self.source_path)
-
- # Connect self.__discovered to the 'discovered' event
- self.discoverer.connect('discovered', self.__discovered)
-
- def __discovered(self, data, is_media):
- '''
- Callback for media discoverer.
- '''
- if not is_media:
- self.__stop()
- raise Exception('Could not discover {0}'.format(self.source_path))
-
- _log.debug('__discovered, data: {0}'.format(data))
-
- self.data = data
-
- # Run any tasks that depend on the info from the discovery
- self._on_discovered()
-
- # Tell the transcoding pipeline to start running
- _log.info('Transcoding...')
-
- def _on_discovered(self):
- self.__setup_capsfilter()
-
- def _setup_pipeline(self):
- # Create a new pipeline
- self.pipeline = gst.Pipeline('VideoThumbnailerPipeline')
-
- # Create the elements in the pipeline
- self.filesrc = gst.element_factory_make('filesrc', 'filesrc')
- self.filesrc.set_property('location', self.source_path)
- self.pipeline.add(self.filesrc)
-
- self.decoder = gst.element_factory_make('decodebin2', 'decoder')
- self.decoder.connect('new-decoded-pad', self._on_dynamic_pad)
- self.pipeline.add(self.decoder)
-
- self.ffmpegcolorspace = gst.element_factory_make(
- 'ffmpegcolorspace', 'ffmpegcolorspace')
- self.pipeline.add(self.ffmpegcolorspace)
-
- self.videoscale = gst.element_factory_make('videoscale', 'videoscale')
- self.videoscale.set_property('method', 'bilinear')
- self.pipeline.add(self.videoscale)
-
- self.capsfilter = gst.element_factory_make('capsfilter', 'capsfilter')
- self.pipeline.add(self.capsfilter)
-
- self.jpegenc = gst.element_factory_make('jpegenc', 'jpegenc')
- self.pipeline.add(self.jpegenc)
-
- #self.filesink = gst.element_factory_make('filesink', 'filesink')
- #self.filesink.set_property('location', self.destination_path)
- #self.pipeline.add(self.filesink)
-
- self.appsink = gst.element_factory_make('appsink', 'appsink')
- self.appsink.set_property('emit-signals', True)
- self.appsink.connect('new-preroll', self.__on_sink_preroll)
- self.pipeline.add(self.appsink)
-
- self.progressreport = gst.element_factory_make(
- 'progressreport', 'progressreport')
- self.progressreport.set_property('update-freq', 1)
- self.pipeline.add(self.progressreport)
-
- self.identity = gst.element_factory_make('identity', 'id')
- self.pipeline.add(self.identity)
-
- # Link all the elements together
- self.filesrc.link(self.decoder)
- self.ffmpegcolorspace.link(self.videoscale)
- self.videoscale.link(self.capsfilter)
- self.capsfilter.link(self.jpegenc)
- self.jpegenc.link(self.progressreport)
- self.progressreport.link(self.identity)
- #self.identity.link(self.filesink)
- self.identity.link(self.appsink)
-
- self.pipeline.set_state(gst.STATE_PAUSED)
-
- self._setup_bus()
-
- def __on_sink_preroll(self, sink):
- _log.debug('SINK PREROLL!!!!')
-
- def _on_dynamic_pad(self, dbin, pad, islast):
- '''
- Callback called when ``decodebin2`` has a pad that we can connect to
- '''
- # Intersect the capabilities of the video sink and the pad src
- # Then check if they have no common capabilities.
- if not self.ffmpegcolorspace.get_pad_template('sink')\
- .get_caps().intersect(pad.get_caps()).is_empty():
- # It IS a video src pad.
- pad.link(self.ffmpegcolorspace.get_pad('sink'))
- gst.DEBUG_BIN_TO_DOT_FILE(
- self.pipeline,
- gst.DEBUG_GRAPH_SHOW_ALL,
- 'ss')
-
- def _setup_bus(self):
- self.bus = self.pipeline.get_bus()
- self.bus.add_signal_watch()
- self.bus.connect('message', self._on_message)
-
- def __setup_capsfilter(self):
- caps = ['video/x-raw-rgb', 'pixel-aspect-ratio=1/1']
-
- if self.data.videoheight > self.data.videowidth:
- # Whoa! We have ourselves a portrait video!
- caps.append('height={0}'.format(
- self.destination_dimensions[1]))
- else:
- # It's a landscape, phew, how normal.
- caps.append('width={0}'.format(
- self.destination_dimensions[0]))
-
- self.capsfilter.set_property(
- 'caps',
- gst.caps_from_string(
- ', '.join(caps)))
-
- def __find_wadsworth(self):
- if self.decoder.seek_simple(
- gst.FORMAT_PERCENT,
- gst.SEEK_FLAG_NONE,
- 0 * 10000):
- _log.info('Found wadsworth')
- #pdb.set_trace()
- #self.pipeline.set_state(gst.STATE_PLAYING)
- self.__get_buffer()
- self.__stop()
- else:
- pdb.set_trace()
-
- def __get_buffer(self):
- buffer = self.appsink.emit('pull-preroll')
- open(self.destination_path, 'wb').write(buffer)
-
- def _on_message(self, bus, message):
- t = message.type
-
- _log.debug((
- t == gst.MESSAGE_ASYNC_DONE,
- bus,
- message))
-
- if t == gst.MESSAGE_EOS:
- self.__stop()
- _log.info('Got EOS')
- elif t == gst.MESSAGE_ASYNC_DONE:
- #pdb.set_trace()
- self.__find_wadsworth()
- elif t == gst.MESSAGE_ERROR:
- _log.error((bus, message))
- self.__stop()
-
- def __stop(self):
- _log.debug(self.loop)
-
- self.pipeline.set_state(gst.STATE_NULL)
-
- gobject.idle_add(self.loop.quit)
-
-
class VideoTranscoder:
'''
Video transcoder
self.pipeline.add(self.audioqueue)
self.audiorate = gst.element_factory_make('audiorate', 'audiorate')
+ self.audiorate.set_property('tolerance', 80000000)
self.pipeline.add(self.audiorate)
self.audioconvert = gst.element_factory_make('audioconvert', 'audioconvert')