Fixed video transcoding

- Added audiorate with tolerance 80 million
- Removed deprecated thumbnailer
This commit is contained in:
Joar Wandborg 2011-11-16 14:20:27 +01:00
parent 64fd0462bd
commit 359781f075

View File

@ -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')