Fixed video transcoding
- Added audiorate with tolerance 80 million - Removed deprecated thumbnailer
This commit is contained in:
parent
64fd0462bd
commit
359781f075
@ -340,218 +340,6 @@ class VideoThumbnailer:
|
||||
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
|
||||
@ -664,6 +452,7 @@ class VideoTranscoder:
|
||||
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')
|
||||
|
Loading…
x
Reference in New Issue
Block a user