def createVideoNoPreset(self, mgr): mgr.prependPreset(_("No preset"), { "par": gst.Fraction(int(get_combo_value(self.par_combo).num), int(get_combo_value(self.par_combo).denom)), "frame-rate": gst.Fraction(int(get_combo_value(self.frame_rate_combo).num), int(get_combo_value(self.frame_rate_combo).denom)), "height": int(self.height_spinbutton.get_value()), "width": int(self.width_spinbutton.get_value())})
def _addAudioPresetButtonClickedCb(self, button): preset_name = self._getUniquePresetName(self.audio_presets) self.audio_presets.addPreset(preset_name, { "channels": get_combo_value(self.channels_combo), "sample-rate": get_combo_value(self.sample_rate_combo), "depth": get_combo_value(self.sample_depth_combo) }) self.audio_presets.restorePreset(preset_name) self._updateAudioPresetButtons()
def _elementAddedCb(self, bin, element): # Setting properties on Gst.Element-s has they are added to the # Gst.Encodebin if element.get_factory() == get_combo_value(self.video_encoder_combo): for setting in self.settings.vcodecsettings: element.set_property(setting, self.settings.vcodecsettings[setting]) elif element.get_factory() == get_combo_value(self.audio_encoder_combo): for setting in self.settings.acodecsettings: element.set_property(setting, self.settings.vcodecsettings[setting])
def _elementAddedCb(self, unused_bin, gst_element): """Sets properties on the specified Gst.Element.""" factory = gst_element.get_factory() settings = {} if factory == get_combo_value(self.video_encoder_combo): settings = self.project.vcodecsettings elif factory == get_combo_value(self.audio_encoder_combo): settings = self.project.acodecsettings for propname, value in settings.items(): gst_element.set_property(propname, value) self.debug("Setting %s to %s", propname, value)
def updateSettings(self): width = int(self.width_spinbutton.get_value()) height = int(self.height_spinbutton.get_value()) par = self.par_fraction_widget.getWidgetValue() frame_rate = self.frame_rate_fraction_widget.getWidgetValue() channels = get_combo_value(self.channels_combo) sample_rate = get_combo_value(self.sample_rate_combo) sample_depth = get_combo_value(self.sample_depth_combo) self.settings.setVideoProperties(width, height, frame_rate, par) self.settings.setAudioProperties(channels, sample_rate, sample_depth) self.project.setSettings(self.settings)
def _elementAddedCb(self, bin, element): """ Setting properties on Gst.Element-s has they are added to the Gst.Encodebin """ factory = element.get_factory() settings = {} if factory == get_combo_value(self.video_encoder_combo): settings = self.project.vcodecsettings elif factory == get_combo_value(self.audio_encoder_combo): settings = self.project.acodecsettings for propname, value in settings.iteritems(): element.set_property(propname, value) self.debug("Setting %s to %s", propname, value)
def _videoEncoderComboChangedCb(self, combo): vencoder = get_combo_value(combo).get_name() self.project.vencoder = vencoder if not self.muxer_combo_changing: # The user directly changed the video encoder combo. self.preferred_vencoder = vencoder
def _audioEncoderChangedComboCb(self, combo): factory = get_combo_value(combo) name = factory.get_name() self.project.aencoder = name if not self.muxer_combo_changing: # The user directly changed the audio encoder combo. self.debug("User chose an audio encoder: %s", name) self.preferred_aencoder = name
def bindCombo(self, mgr, name, widget): if name == "container": mgr.bindWidget(name, lambda x: self.muxer_setter(widget, x), lambda: get_combo_value(widget).get_name()) elif name == "acodec": mgr.bindWidget(name, lambda x: self.acodec_setter(widget, x), lambda: get_combo_value(widget).get_name()) elif name == "vcodec": mgr.bindWidget(name, lambda x: self.vcodec_setter(widget, x), lambda: get_combo_value(widget).get_name()) elif name == "depth": mgr.bindWidget(name, lambda x: self.sample_depth_setter(widget, x), lambda: get_combo_value(widget)) elif name == "sample-rate": mgr.bindWidget(name, lambda x: self.sample_rate_setter(widget, x), lambda: get_combo_value(widget)) elif name == "channels": mgr.bindWidget(name, lambda x: self.channels_setter(widget, x), lambda: get_combo_value(widget)) elif name == "frame-rate": mgr.bindWidget(name, lambda x: self.framerate_setter(widget, x), lambda: get_combo_value(widget))
def _addRenderPresetButtonClickedCb(self, unused_button): preset_name = self._getUniquePresetName(self.render_presets) self.render_presets.addPreset( preset_name, { "channels": int(get_combo_value(self.channels_combo)), "sample-rate": int(get_combo_value(self.sample_rate_combo)), "acodec": get_combo_value(self.audio_encoder_combo).get_name(), "vcodec": get_combo_value(self.video_encoder_combo).get_name(), "container": get_combo_value(self.muxercombobox).get_name(), "frame-rate": Gst.Fraction(int(get_combo_value(self.frame_rate_combo).num), int(get_combo_value( self.frame_rate_combo).denom)), "height": 0, "width": 0 }) self.render_presets.restorePreset(preset_name) self._updateRenderPresetButtons()
def _audioEncoderChangedComboCb(self, combo): factory = get_combo_value(combo) name = factory.get_name() self.project.aencoder = name if not self.muxer_combo_changing: # The user directly changed the audio encoder combo. self.debug("User chose an audio encoder: %s", name) self.preferred_aencoder = name self._update_valid_audio_restrictions(factory)
def createNoPreset(self, mgr): mgr.prependPreset(_("No preset"), { "depth": int(get_combo_value(self.sample_depth_combo)), "channels": int(get_combo_value(self.channels_combo)), "sample-rate": int(get_combo_value(self.sample_rate_combo)), "acodec": get_combo_value(self.audio_encoder_combo).get_name(), "vcodec": get_combo_value(self.video_encoder_combo).get_name(), "container": get_combo_value(self.muxercombobox).get_name(), "frame-rate": Gst.Fraction(int(get_combo_value(self.frame_rate_combo).num), int(get_combo_value(self.frame_rate_combo).denom)), "height": self.getDimension("height"), "width": self.getDimension("width")})
def _muxerComboChangedCb(self, combo): """Handles the changing of the container format combobox.""" factory = get_combo_value(combo) self.project.muxer = factory.get_name() # Update the extension of the filename. basename = os.path.splitext(self.fileentry.get_text())[0] self.updateFilename(basename) # Update muxer-dependent widgets. self.updateAvailableEncoders()
def createNoPreset(self, mgr): mgr.prependPreset(_("No preset"), { "depth": int(get_combo_value(self.sample_depth_combo)), "channels": int(get_combo_value(self.channels_combo)), "sample-rate": int(get_combo_value(self.sample_rate_combo)), "acodec": get_combo_value(self.audio_encoder_combo).get_name(), "vcodec": get_combo_value(self.video_encoder_combo).get_name(), "container": get_combo_value(self.muxercombobox).get_name(), "frame-rate": Gst.Fraction( int(get_combo_value(self.frame_rate_combo).num), int(get_combo_value(self.frame_rate_combo).denom)), "height": self.project.videoheight, "width": self.project.videowidth})
def _audioEncoderChangedComboCb(self, combo): aencoder = get_combo_value(combo).get_name() self.settings.setEncoders(aencoder=aencoder) for template in Gst.Registry.get().lookup_feature(aencoder).get_static_pad_templates(): if template.name_template == "src": self.audiotype = template.get_caps().to_string() for elem in self.audiotype.split(","): if "{" in elem or "[" in elem: self.audiotype = self.audiotype[:self.audiotype.index(elem) - 1] break if not self.muxer_combo_changing: # The user directly changed the audio encoder combo. self.preferred_aencoder = aencoder
def _videoEncoderComboChangedCb(self, combo): vencoder = get_combo_value(combo).get_name() for template in gst.registry_get_default().lookup_feature(vencoder).get_static_pad_templates(): if template.name_template == "src": self.videotype = template.get_caps().to_string() for elem in self.videotype.split(","): if "{" in elem or "[" in elem: self.videotype = self.videotype[:self.videotype.index(elem) - 1] break self.settings.setEncoders(vencoder=vencoder) if not self.muxer_combo_changing: # The user directly changed the video encoder combo. self.preferred_vencoder = vencoder
def _muxerComboChangedCb(self, muxer_combo): """Handle the changing of the container format combobox.""" self.project.muxer = get_combo_value(muxer_combo).get_name() # Update the extension of the filename. basename = os.path.splitext(self.fileentry.get_text())[0] self.updateFilename(basename) # Update muxer-dependent widgets. self.muxer_combo_changing = True try: self.updateAvailableEncoders() finally: self.muxer_combo_changing = False
def _update_valid_restriction_values(self, caps, combo, caps_template, model, value, caps_template_expander=None): def caps_template_expander_func(caps_template, value): return caps_template % value if not caps_template_expander: caps_template_expander = caps_template_expander_func model_headers = [model.get_column_type(i) for i in range(model.get_n_columns())] reduced_model = Gtk.ListStore(*model_headers) for name, value in dict(model).items(): ecaps = Gst.Caps(caps_template_expander(caps_template, value)) if not caps.intersect(ecaps).is_empty(): reduced_model.append((name, value)) combo.set_model(reduced_model) set_combo_value(combo, value) if get_combo_value(combo) != value: combo.set_active(len(reduced_model) - 1) self.warning("%s in %s not supported, setting: %s", value, caps_template, get_combo_value(combo))
def _addRenderPresetButtonClickedCb(self, button): preset_name = self._getUniquePresetName(self.render_presets) self.render_presets.addPreset(preset_name, { "depth": int(get_combo_value(self.sample_depth_combo)), "channels": int(get_combo_value(self.channels_combo)), "sample-rate": int(get_combo_value(self.sample_rate_combo)), "acodec": get_combo_value(self.audio_encoder_combo).get_name(), "vcodec": get_combo_value(self.video_encoder_combo).get_name(), "container": get_combo_value(self.muxercombobox).get_name(), "frame-rate": Gst.Fraction(int(get_combo_value(self.frame_rate_combo).num), int(get_combo_value(self.frame_rate_combo).denom)), "height": 0, "width": 0}) self.render_presets.restorePreset(preset_name) self._updateRenderPresetButtons()
def _muxerComboChangedCb(self, muxer_combo): """Handle the changing of the container format combobox.""" muxer = get_combo_value(muxer_combo).get_name() for template in Gst.Registry.get().lookup_feature(muxer).get_static_pad_templates(): if template.name_template == "src": self.muxertype = template.get_caps().to_string() self.settings.setEncoders(muxer=muxer) # Update the extension of the filename. basename = os.path.splitext(self.fileentry.get_text())[0] self.updateFilename(basename) # Update muxer-dependent widgets. self.muxer_combo_changing = True try: self.updateAvailableEncoders() finally: self.muxer_combo_changing = False
def _update_encoder_combo(self, encoder_combo, preferred_encoder): """Selects the specified encoder for the specified encoder combo.""" if preferred_encoder: # A preference exists, pick it if it can be found in # the current model of the combobox. encoder = Encoders().factories_by_name.get(preferred_encoder) set_combo_value(encoder_combo, encoder) if not preferred_encoder or not get_combo_value(encoder_combo): # No preference exists or it is not available, # pick the first encoder from the combobox's model. first = encoder_combo.props.model.get_iter_first() if not first: # Model is empty. Should not happen. self.warning("Model is empty") return if not encoder_combo.props.model.iter_has_child(first): # The first item is a supported factory. encoder_combo.set_active_iter(first) else: # The first element is the Unsupported group. second = encoder_combo.props.model.iter_nth_child(first, 0) encoder_combo.set_active_iter(second)
def _sampleRateComboChangedCb(self, combo): self.project.audiorate = get_combo_value(combo)
def _channelsComboChangedCb(self, combo): self.project.audiochannels = get_combo_value(combo)
def updateParFromCombo(self): self.par_fraction_widget.setWidgetValue(get_combo_value(self.par_combo))
def _audioSettingsButtonClickedCb(self, button): factory = get_combo_value(self.audio_encoder_combo) self._elementSettingsDialog(factory, 'acodecsettings')
def createAudioNoPreset(self, mgr): mgr.prependPreset(_("No preset"), { "depth": int(get_combo_value(self.sample_depth_combo)), "channels": int(get_combo_value(self.channels_combo)), "sample-rate": int(get_combo_value(self.sample_rate_combo))})
def _videoSettingsButtonClickedCb(self, unused_button): factory = get_combo_value(self.video_encoder_combo) self._elementSettingsDialog(factory, 'vcodecsettings')
def __init__(self, app, project): Loggable.__init__(self) self.app = app self.project = project self.system = app.system self._pipeline = self.project.pipeline self.outfile = None self.notification = None # Variables to keep track of progress indication timers: self._filesizeEstimateTimer = self._timeEstimateTimer = None self._is_rendering = False self._rendering_is_paused = False self.current_position = None self._time_started = 0 self._time_spent_paused = 0 # Avoids the ETA being wrong on resume # Various gstreamer signal connection ID's # {object: sigId} self._gstSigId = {} self.render_presets = RenderPresetManager(self.app.system, Encoders()) self.render_presets.loadAll() # Whether encoders changing are a result of changing the muxer. self.muxer_combo_changing = False self._createUi() # Directory and Filename self.filebutton.set_current_folder(self.app.settings.lastExportFolder) if not self.project.name: self.updateFilename(_("Untitled")) else: self.updateFilename(self.project.name) # We store these so that when the user tries various container formats, # (AKA muxers) we select these a/v encoders, if they are compatible with # the current container format. self.preferred_vencoder = self.project.vencoder self.preferred_aencoder = self.project.aencoder self.__unproxiedClips = {} self.frame_rate_combo.set_model(frame_rates) self.channels_combo.set_model(audio_channels) self.sample_rate_combo.set_model(audio_rates) self.__initialize_muxers_model() self._displaySettings() self._displayRenderSettings() self.window.connect("delete-event", self._deleteEventCb) self.project.connect("rendering-settings-changed", self._settingsChanged) # Monitor changes self.wg = RippleUpdateGroup() self.wg.addVertex(self.frame_rate_combo, signal="changed") self.wg.addVertex(self.channels_combo, signal="changed") self.wg.addVertex(self.sample_rate_combo, signal="changed") self.wg.addVertex(self.muxer_combo, signal="changed") self.wg.addVertex(self.audio_encoder_combo, signal="changed") self.wg.addVertex(self.video_encoder_combo, signal="changed") self.wg.addVertex(self.preset_menubutton, update_func=self._updatePresetMenuButton) self.wg.addEdge(self.frame_rate_combo, self.preset_menubutton) self.wg.addEdge(self.audio_encoder_combo, self.preset_menubutton) self.wg.addEdge(self.video_encoder_combo, self.preset_menubutton) self.wg.addEdge(self.muxer_combo, self.preset_menubutton) self.wg.addEdge(self.channels_combo, self.preset_menubutton) self.wg.addEdge(self.sample_rate_combo, self.preset_menubutton) # Bind widgets to RenderPresetsManager self.render_presets.bindWidget( "container", lambda x: self.muxer_setter(self.muxer_combo, x), lambda: get_combo_value(self.muxer_combo).get_name()) self.render_presets.bindWidget( "acodec", lambda x: self.acodec_setter(self.audio_encoder_combo, x), lambda: get_combo_value(self.audio_encoder_combo).get_name()) self.render_presets.bindWidget( "vcodec", lambda x: self.vcodec_setter(self.video_encoder_combo, x), lambda: get_combo_value(self.video_encoder_combo).get_name()) self.render_presets.bindWidget( "sample-rate", lambda x: self.sample_rate_setter(self.sample_rate_combo, x), lambda: get_combo_value(self.sample_rate_combo)) self.render_presets.bindWidget( "channels", lambda x: self.channels_setter(self.channels_combo, x), lambda: get_combo_value(self.channels_combo)) self.render_presets.bindWidget( "frame-rate", lambda x: self.framerate_setter(self.frame_rate_combo, x), lambda: get_combo_value(self.frame_rate_combo)) self.render_presets.bindWidget( "height", lambda x: setattr(self.project, "videoheight", x), lambda: 0) self.render_presets.bindWidget( "width", lambda x: setattr(self.project, "videowidth", x), lambda: 0)
def _updateFraction(self, unused, fraction, combo): fraction.setWidgetValue(get_combo_value(combo))
def bindCombo(self, mgr, name, widget): mgr.bindWidget(name, lambda x: set_combo_value(widget, x), lambda: get_combo_value(widget))
def _audioEncoderChangedComboCb(self, combo): aencoder = get_combo_value(combo).get_name() self.project.aencoder = aencoder if not self.muxer_combo_changing: # The user directly changed the audio encoder combo. self.preferred_aencoder = aencoder
def _frameRateComboChangedCb(self, combo): framerate = get_combo_value(combo) self.project.framerate = framerate
def __init__(self, app, project): from pitivi.preset import RenderPresetManager Loggable.__init__(self) self.app = app self.project = project self.system = app.system self._pipeline = self.project.pipeline self.outfile = None self.notification = None # Variables to keep track of progress indication timers: self._filesizeEstimateTimer = self._timeEstimateTimer = None self._is_rendering = False self._rendering_is_paused = False self.current_position = None self._time_started = 0 self._time_spent_paused = 0 # Avoids the ETA being wrong on resume # Various gstreamer signal connection ID's # {object: sigId} self._gstSigId = {} self.render_presets = RenderPresetManager(self.app.system) self.render_presets.loadAll() self._createUi() # Directory and Filename self.filebutton.set_current_folder(self.app.settings.lastExportFolder) if not self.project.name: self.updateFilename(_("Untitled")) else: self.updateFilename(self.project.name) # We store these so that when the user tries various container formats, # (AKA muxers) we select these a/v encoders, if they are compatible with # the current container format. self.preferred_vencoder = self.project.vencoder self.preferred_aencoder = self.project.aencoder self.__unproxiedClips = {} self._initializeComboboxModels() self._displaySettings() self._displayRenderSettings() self.window.connect("delete-event", self._deleteEventCb) self.project.connect( "rendering-settings-changed", self._settingsChanged) # Monitor changes self.wg = RippleUpdateGroup() self.wg.addVertex(self.frame_rate_combo, signal="changed") self.wg.addVertex(self.channels_combo, signal="changed") self.wg.addVertex(self.sample_rate_combo, signal="changed") self.wg.addVertex(self.muxercombobox, signal="changed") self.wg.addVertex(self.audio_encoder_combo, signal="changed") self.wg.addVertex(self.video_encoder_combo, signal="changed") self.wg.addVertex(self.preset_menubutton, update_func=self._updatePresetMenuButton) self.wg.addEdge(self.frame_rate_combo, self.preset_menubutton) self.wg.addEdge(self.audio_encoder_combo, self.preset_menubutton) self.wg.addEdge(self.video_encoder_combo, self.preset_menubutton) self.wg.addEdge(self.muxercombobox, self.preset_menubutton) self.wg.addEdge(self.channels_combo, self.preset_menubutton) self.wg.addEdge(self.sample_rate_combo, self.preset_menubutton) # Bind widgets to RenderPresetsManager self.render_presets.bindWidget( "container", lambda x: self.muxer_setter(self.muxercombobox, x), lambda: get_combo_value(self.muxercombobox).get_name()) self.render_presets.bindWidget( "acodec", lambda x: self.acodec_setter(self.audio_encoder_combo, x), lambda: get_combo_value(self.audio_encoder_combo).get_name()) self.render_presets.bindWidget( "vcodec", lambda x: self.vcodec_setter(self.video_encoder_combo, x), lambda: get_combo_value(self.video_encoder_combo).get_name()) self.render_presets.bindWidget( "sample-rate", lambda x: self.sample_rate_setter(self.sample_rate_combo, x), lambda: get_combo_value(self.sample_rate_combo)) self.render_presets.bindWidget( "channels", lambda x: self.channels_setter(self.channels_combo, x), lambda: get_combo_value(self.channels_combo)) self.render_presets.bindWidget( "frame-rate", lambda x: self.framerate_setter(self.frame_rate_combo, x), lambda: get_combo_value(self.frame_rate_combo)) self.render_presets.bindWidget( "height", lambda x: setattr(self.project, "videoheight", x), lambda: 0) self.render_presets.bindWidget( "width", lambda x: setattr(self.project, "videowidth", x), lambda: 0)
def _sampleDepthComboChangedCb(self, combo): self.project.audiodepth = get_combo_value(combo)
def test_loading_preset(self): """Checks preset values are properly exposed in the UI.""" project = self.create_simple_project() dialog = self.create_rendering_dialog(project) test_data = [ ("test", { "aencoder": "vorbisenc", "vencoder": "theoraenc", "muxer": "oggmux" }), ("test_ogg-vp8-opus", { "aencoder": "opusenc", "vencoder": ["vp8enc", "vaapivp8enc"], "muxer": "oggmux" }), ("test_fullhd", { "aencoder": "vorbisenc", "vencoder": "theoraenc", "muxer": "oggmux", "videowidth": 1920, "videoheight": 1080, "videorate": Gst.Fraction(120, 1) }), ("test_ogg-vp8-opus", { "aencoder": "opusenc", "vencoder": ["vp8enc", "vaapivp8enc"], "muxer": "oggmux" }), ("test_fullhd", { "aencoder": "vorbisenc", "vencoder": "theoraenc", "muxer": "oggmux", "videowidth": 1920, "videoheight": 1080, "videorate": Gst.Fraction(120, 1) }), ] attr_dialog_widget_map = { "videorate": dialog.frame_rate_combo, "aencoder": dialog.audio_encoder_combo, "vencoder": dialog.video_encoder_combo, "muxer": dialog.muxer_combo, } dialog._preset_selection_menubutton_clicked_cb(None) for preset_name, values in test_data: self.select_render_preset(dialog, preset_name) for attr, val in values.items(): val = val if isinstance(val, list) else [val] combo = attr_dialog_widget_map.get(attr) if combo: combo_value = get_combo_value(combo) if isinstance(combo_value, Gst.ElementFactory): combo_value = combo_value.get_name() self.assertIn(combo_value, val, preset_name) self.assertIn(getattr(project, attr), val)
def test_loading_preset(self): """Checks preset values are properly exposed in the UI.""" def preset_changed_cb(combo, changed): """Callback for the "combo::changed" signal.""" changed.append(1) project = self.create_simple_project() dialog = self.create_rendering_dialog(project) preset_combo = dialog.render_presets.combo changed = [] preset_combo.connect("changed", preset_changed_cb, changed) test_data = [ ("test", { "aencoder": "vorbisenc", "vencoder": "theoraenc", "muxer": "oggmux" }), ("test_ogg-vp8-opus", { "aencoder": "opusenc", "vencoder": ["vp8enc", "vaapivp8enc"], "muxer": "oggmux" }), ("test_fullhd", { "aencoder": "vorbisenc", "vencoder": "theoraenc", "muxer": "oggmux", "videowidth": 1920, "videoheight": 1080, "videorate": Gst.Fraction(120, 1) }), ("test_ogg-vp8-opus", { "aencoder": "opusenc", "vencoder": ["vp8enc", "vaapivp8enc"], "muxer": "oggmux" }), ("test_fullhd", { "aencoder": "vorbisenc", "vencoder": "theoraenc", "muxer": "oggmux", "videowidth": 1920, "videoheight": 1080, "videorate": Gst.Fraction(120, 1) }), ] attr_dialog_widget_map = { "videorate": dialog.frame_rate_combo, "aencoder": dialog.audio_encoder_combo, "vencoder": dialog.video_encoder_combo, "muxer": dialog.muxer_combo, } for preset_name, values in test_data: i = find_preset_row_index(preset_combo, preset_name) self.assertNotEqual(i, None) del changed[:] preset_combo.set_active(i) self.assertEqual(changed, [1], "Preset %s" % preset_name) for attr, val in values.items(): val = val if isinstance(val, list) else [val] combo = attr_dialog_widget_map.get(attr) if combo: combo_value = get_combo_value(combo) if isinstance(combo_value, Gst.ElementFactory): combo_value = combo_value.get_name() self.assertIn(combo_value, val, preset_name) self.assertIn(getattr(project, attr), val)