[pitivi] render: Quality widget for supported encoders
- From: Alexandru Băluț <alexbalut src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] render: Quality widget for supported encoders
- Date: Wed, 30 Sep 2020 17:55:48 +0000 (UTC)
commit 19cea8931fd3862d1a24beb2d42915f7744e559d
Author: Ayush Mittal <ayush mittal9398 gmail com>
Date: Thu Aug 13 03:38:05 2020 +0530
render: Quality widget for supported encoders
data/ui/renderingdialog.ui | 1254 ++++++++++++++++++++++----------------------
pitivi/render.py | 124 ++++-
tests/test_render.py | 31 ++
3 files changed, 789 insertions(+), 620 deletions(-)
---
diff --git a/data/ui/renderingdialog.ui b/data/ui/renderingdialog.ui
index 7237999ae..5bbdc5d4c 100644
--- a/data/ui/renderingdialog.ui
+++ b/data/ui/renderingdialog.ui
@@ -8,16 +8,21 @@
<property name="step_increment">1</property>
<property name="page_increment">1</property>
</object>
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="lower">0</property>
+ <property name="upper">2</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">1</property>
+ </object>
+ <object class="GtkSizeGroup" id="common_size_group"/>
<object class="GtkImage" id="help_icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">question-round-symbolic</property>
</object>
- <object class="GtkSizeGroup" id="common_size_group">
+ <object class="GtkSizeGroup">
<widgets>
- <widget name="label5"/>
- <widget name="label1"/>
- <widget name="label6"/>
+ <widget name="expander_label"/>
</widgets>
</object>
<object class="GtkPopover" id="preset_popover">
@@ -31,7 +36,7 @@
</object>
<object class="GtkDialog" id="render-dialog">
<property name="can_focus">False</property>
- <property name="border_width">12</property>
+ <property name="border_width">18</property>
<property name="title" translatable="yes">Render</property>
<property name="modal">True</property>
<property name="window_position">center-always</property>
@@ -43,8 +48,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
- <property name="spacing">12</property>
- <property name="baseline_position">bottom</property>
+ <property name="spacing">18</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area3">
<property name="visible">True</property>
@@ -72,756 +76,776 @@
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
- <property name="position">0</property>
+ <property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<child>
- <object class="GtkGrid" id="table2">
+ <object class="GtkScale" id="quality_scale">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_STRUCTURE_MASK | GDK_SCROLL_MASK</property>
+ <property name="adjustment">adjustment2</property>
+ <property name="lower_stepper_sensitivity">on</property>
+ <property name="upper_stepper_sensitivity">on</property>
+ <property name="restrict_to_fill_level">False</property>
+ <property name="fill_level">0</property>
+ <property name="round_digits">0</property>
+ <property name="draw_value">False</property>
+ <property name="value_pos">right</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="quality_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="margin_top">6</property>
+ <property name="label" translatable="yes">Quality:</property>
+ <property name="justify">fill</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="margin_top">6</property>
+ <property name="label" translatable="yes">Preset:</property>
+ <property name="justify">right</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="preset_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="row_spacing">6</property>
- <property name="column_spacing">15</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="baseline_position">top</property>
<child>
- <object class="GtkLabel" id="label6">
+ <object class="GtkMenuButton" id="preset_selection_menubutton">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="direction">right</property>
+ <property name="popover">preset_popover</property>
+ <child>
+ <object class="GtkGrid" id="preset_button_grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">3</property>
+ <property name="margin_right">3</property>
+ <property name="margin_start">3</property>
+ <property name="margin_end">3</property>
+ <property name="margin_top">3</property>
+ <property name="margin_bottom">3</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkImage" id="preset_icon">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-missing-image</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="preset_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Custom</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="preset_menubutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
<property name="valign">start</property>
- <property name="xpad">0</property>
- <property name="label" translatable="yes">Preset:</property>
+ <property name="relief">none</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">open-menu-symbolic</property>
+ </object>
+ </child>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFileChooserButton" id="filebutton">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="action">select-folder</property>
+ <signal name="current-folder-changed" handler="_current_folder_changed_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Folder:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="fileentry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <signal name="changed" handler="_filename_changed_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">File name:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkExpander" id="advanced_expander">
+ <property name="name">Advanced</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="resize_toplevel">True</property>
<child>
- <object class="GtkBox" id="preset_box">
+ <object class="GtkGrid" id="advanced_grid">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="baseline_position">top</property>
+ <property name="row_spacing">10</property>
<child>
- <object class="GtkMenuButton" id="preset_selection_menubutton">
+ <object class="GtkGrid" id="container_grid">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="direction">right</property>
- <property name="popover">preset_popover</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">3</property>
+ <property name="column_spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Container format:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
<child>
- <object class="GtkGrid" id="preset_button_grid">
+ <object class="GtkBox" id="box2">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_left">3</property>
- <property name="margin_right">3</property>
- <property name="margin_start">3</property>
- <property name="margin_end">3</property>
- <property name="margin_top">3</property>
- <property name="margin_bottom">3</property>
- <property name="row_spacing">4</property>
+ <property name="spacing">6</property>
<child>
- <object class="GtkImage" id="preset_icon">
+ <object class="GtkComboBox" id="muxercombobox">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="stock">gtk-missing-image</property>
+ <property name="halign">start</property>
+ <signal name="changed" handler="_muxer_combo_changed_cb" swapped="no"/>
+ <child>
+ <object class="GtkCellRendererText" id="renderer1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="preset_label">
+ <object class="GtkButton" id="container_context_help_button">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Custom</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">help_icon</property>
+ <property name="relief">none</property>
+ <property name="always_show_image">True</property>
+ <signal name="clicked" handler="_container_context_help_clicked_cb"
swapped="no"/>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
</object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
</child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
</packing>
</child>
<child>
- <object class="GtkMenuButton" id="preset_menubutton">
+ <object class="GtkBox" id="box5">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="valign">start</property>
- <property name="relief">none</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkImage" id="image1">
+ <object class="GtkRadioButton" id="automatically_use_proxies">
+ <property name="label" translatable="yes">Automatically render from proxy
files</property>
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">open-menu-symbolic</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_markup" translatable="yes">Use proxy files if they are
available and the source asset media format is not officially supported.
+
+This option is a good trade-off between quality of the rendered video and stability.</property>
+ <property name="halign">start</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="always_use_proxies">
+ <property name="label" translatable="yes">Always render from proxy
files</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_markup" translatable="yes">Render all proxied clips from
the proxy assets. There might be some quality loss during the rendering process.</property>
+ <property name="halign">start</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="never_use_proxies">
+ <property name="label" translatable="yes">Never render from proxy
files</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_markup" translatable="yes">Always use source assets for
rendering. It is the best choice for the quality of the rendered video, but you might hit some bugs because
of the use of not officially supported media formats.
+<i>Use at your own risk!</i></property>
+ <property name="halign">start</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
</object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
</child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
</packing>
</child>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkExpander" id="advanced_expander">
- <property name="name">Advanced</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="resize_toplevel">True</property>
- <child>
- <object class="GtkGrid" id="advanced_grid">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="row_spacing">10</property>
- <child>
- <object class="GtkGrid" id="audio_video_grid">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_top">4</property>
- <property name="column_spacing">5</property>
- <property name="column_homogeneous">True</property>
<child>
- <object class="GtkFrame" id="video_frame">
+ <object class="GtkGrid" id="audio_video_grid">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label_xalign">0</property>
+ <property name="margin_top">4</property>
+ <property name="column_spacing">5</property>
+ <property name="column_homogeneous">True</property>
<child>
- <object class="GtkAlignment" id="alignment1">
+ <object class="GtkFrame" id="audio_frame">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="left_padding">12</property>
+ <property name="label_xalign">0</property>
<child>
- <object class="GtkBox" id="box3">
+ <object class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="border_width">12</property>
- <property name="orientation">vertical</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Scale:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
+ <property name="left_padding">12</property>
<child>
- <object class="GtkBox" id="hbox3">
+ <object class="GtkBox" id="box4">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="spacing">12</property>
+ <property name="border_width">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
<child>
- <object class="GtkSpinButton" id="scale_spinbutton">
+ <object class="GtkLabel" id="label23">
<property name="visible">True</property>
- <property name="can_focus">True</property>
+ <property name="can_focus">False</property>
<property name="halign">start</property>
- <property name="invisible_char">•</property>
- <property name="text">1.0</property>
- <property name="primary_icon_activatable">False</property>
- <property name="secondary_icon_activatable">False</property>
- <property name="adjustment">adjustment1</property>
- <property name="digits">1</property>
- <property name="numeric">True</property>
- <property name="value">1</property>
- <signal name="value-changed" handler="_scale_spinbutton_changed_cb"
swapped="no"/>
- <child internal-child="accessible">
- <object class="AtkObject" id="scale_spinbutton-atkobject">
- <property name="AtkObject::accessible-name"
translatable="yes">Scale</property>
- </object>
- </child>
+ <property name="label" translatable="yes">Channels:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
</object>
<packing>
<property name="expand">False</property>
- <property name="fill">False</property>
+ <property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="resolution_label">
+ <object class="GtkComboBox" id="channels_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
- <property name="label">1000 x 1000</property>
- <property name="width_chars">12</property>
- <property name="xalign">0</property>
- <child internal-child="accessible">
- <object class="AtkObject" id="resolution_label-atkobject">
- <property name="AtkObject::accessible-name"
translatable="yes">Height</property>
- </object>
+ <signal name="changed" handler="_channels_combo_changed_cb"
swapped="no"/>
+ <child>
+ <object class="GtkCellRendererText" id="renderer5"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
</child>
</object>
<packing>
<property name="expand">False</property>
- <property name="fill">True</property>
+ <property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="project_settings_button">
- <property name="label" translatable="yes">Project Settings...</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="halign">end</property>
- <signal name="clicked" handler="_project_settings_button_clicked_cb"
swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="video_settings_button">
- <property name="label" translatable="yes">Advanced...</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="halign">end</property>
- <signal name="clicked" handler="_video_settings_button_clicked_cb"
swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="video_encoder_combo">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <signal name="changed" handler="_video_encoder_combo_changed_cb"
swapped="no"/>
<child>
- <object class="GtkCellRendererText" id="renderer2"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
+ <object class="GtkButton" id="audio_settings_button">
+ <property name="label" translatable="yes">Advanced...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <property name="xalign">1</property>
+ <signal name="clicked" handler="_audio_settings_button_clicked_cb"
swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">2</property>
+ </packing>
</child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">4</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label16">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Codec:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">5</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="frame_rate_combo">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <signal name="changed" handler="_frame_rate_combo_changed_cb"
swapped="no"/>
<child>
- <object class="GtkCellRendererText" id="renderer3"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
- <child internal-child="accessible">
- <object class="AtkObject" id="frame_rate_combo-atkobject">
- <property name="AtkObject::accessible-name"
translatable="yes">Framerate</property>
+ <object class="GtkComboBox" id="audio_encoder_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <signal name="changed" handler="_audio_encoder_changed_combo_cb"
swapped="no"/>
+ <child>
+ <object class="GtkCellRendererText" id="renderer4"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
</object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label21">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Codec:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="sample_rate_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <signal name="changed" handler="_sample_rate_combo_changed_cb"
swapped="no"/>
+ <child>
+ <object class="GtkCellRendererText" id="renderer6"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Sample rate:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">6</property>
+ </packing>
</child>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">6</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label17">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Frame rate:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">7</property>
- </packing>
</child>
</object>
</child>
+ <child type="label">
+ <object class="GtkCheckButton" id="audio_output_checkbutton">
+ <property name="label" translatable="yes">Audio</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="_audio_output_checkbutton_toggled_cb"
swapped="no"/>
+ </object>
+ </child>
</object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
</child>
- <child type="label">
- <object class="GtkCheckButton" id="video_output_checkbutton">
- <property name="label" translatable="yes">Video</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="halign">start</property>
- <property name="xalign">0</property>
- <property name="active">True</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="_video_output_checkbutton_toggled_cb"
swapped="no"/>
- </object>
- </child>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame" id="audio_frame">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label_xalign">0</property>
<child>
- <object class="GtkAlignment" id="alignment2">
+ <object class="GtkFrame" id="video_frame">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="left_padding">12</property>
+ <property name="label_xalign">0</property>
<child>
- <object class="GtkBox" id="box4">
+ <object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="border_width">12</property>
- <property name="orientation">vertical</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkLabel" id="label23">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Channels:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
+ <property name="left_padding">12</property>
<child>
- <object class="GtkComboBox" id="channels_combo">
+ <object class="GtkBox" id="box3">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">start</property>
- <signal name="changed" handler="_channels_combo_changed_cb"
swapped="no"/>
+ <property name="border_width">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
<child>
- <object class="GtkCellRendererText" id="renderer5"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Scale:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
</child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="audio_settings_button">
- <property name="label" translatable="yes">Advanced...</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="halign">end</property>
- <property name="xalign">1</property>
- <signal name="clicked" handler="_audio_settings_button_clicked_cb"
swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="audio_encoder_combo">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <signal name="changed" handler="_audio_encoder_changed_combo_cb"
swapped="no"/>
<child>
- <object class="GtkCellRendererText" id="renderer4"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
+ <object class="GtkBox" id="hbox3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkSpinButton" id="scale_spinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="halign">start</property>
+ <property name="invisible_char">•</property>
+ <property name="text">1.0</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="digits">1</property>
+ <property name="numeric">True</property>
+ <property name="value">1</property>
+ <signal name="value-changed"
handler="_scale_spinbutton_changed_cb" swapped="no"/>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="scale_spinbutton-atkobject">
+ <property name="AtkObject::accessible-name"
translatable="yes">Scale</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="resolution_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label">1000 x 1000</property>
+ <property name="width_chars">12</property>
+ <property name="xalign">0</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="resolution_label-atkobject">
+ <property name="AtkObject::accessible-name"
translatable="yes">Height</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
</child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label21">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Codec:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">4</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="sample_rate_combo">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <signal name="changed" handler="_sample_rate_combo_changed_cb"
swapped="no"/>
<child>
- <object class="GtkCellRendererText" id="renderer6"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
+ <object class="GtkButton" id="project_settings_button">
+ <property name="label" translatable="yes">Project
Settings...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <signal name="clicked" handler="_project_settings_button_clicked_cb"
swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="video_settings_button">
+ <property name="label" translatable="yes">Advanced...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <signal name="clicked" handler="_video_settings_button_clicked_cb"
swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="video_encoder_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <signal name="changed" handler="_video_encoder_combo_changed_cb"
swapped="no"/>
+ <child>
+ <object class="GtkCellRendererText" id="renderer2"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label16">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Codec:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="frame_rate_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <signal name="changed" handler="_frame_rate_combo_changed_cb"
swapped="no"/>
+ <child>
+ <object class="GtkCellRendererText" id="renderer3"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="frame_rate_combo-atkobject">
+ <property name="AtkObject::accessible-name"
translatable="yes">Framerate</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label17">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Frame rate:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">7</property>
+ </packing>
</child>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">5</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label4">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Sample rate:</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">6</property>
- </packing>
</child>
</object>
</child>
- </object>
- </child>
- <child type="label">
- <object class="GtkCheckButton" id="audio_output_checkbutton">
- <property name="label" translatable="yes">Audio</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="halign">start</property>
- <property name="xalign">0</property>
- <property name="active">True</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="_audio_output_checkbutton_toggled_cb"
swapped="no"/>
- </object>
- </child>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkGrid" id="container_grid">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="row_spacing">3</property>
- <property name="column_spacing">9</property>
- <child>
- <object class="GtkLabel" id="label2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Container format:</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="box2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkComboBox" id="muxercombobox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <signal name="changed" handler="_muxer_combo_changed_cb" swapped="no"/>
- <child>
- <object class="GtkCellRendererText" id="renderer1"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
+ <child type="label">
+ <object class="GtkCheckButton" id="video_output_checkbutton">
+ <property name="label" translatable="yes">Video</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="_video_output_checkbutton_toggled_cb"
swapped="no"/>
+ </object>
</child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="container_context_help_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="image">help_icon</property>
- <property name="relief">none</property>
- <property name="always_show_image">True</property>
- <signal name="clicked" handler="_container_context_help_clicked_cb"
swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
</packing>
</child>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
</child>
- <child>
- <object class="GtkBox" id="box5">
+ <child type="label">
+ <object class="GtkLabel" id="expander_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkRadioButton" id="automatically_use_proxies">
- <property name="label" translatable="yes">Automatically render from proxy
files</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="tooltip_markup" translatable="yes">Use proxy files if they are
available and the source asset media format is not officially supported.
-
-This option is a good trade-off between quality of the rendered video and stability.</property>
- <property name="halign">start</property>
- <property name="active">True</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkRadioButton" id="always_use_proxies">
- <property name="label" translatable="yes">Always render from proxy files</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="tooltip_markup" translatable="yes">Render all proxied clips from the
proxy assets. There might be some quality loss during the rendering process.</property>
- <property name="halign">start</property>
- <property name="active">True</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkRadioButton" id="never_use_proxies">
- <property name="label" translatable="yes">Never render from proxy files</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="tooltip_markup" translatable="yes">Always use source assets for
rendering. It is the best choice for the quality of the rendered video, but you might hit some bugs because
of the use of not officially supported media formats.
-<i>Use at your own risk!</i></property>
- <property name="halign">start</property>
- <property name="active">True</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">Advanced</property>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">2</property>
- </packing>
</child>
</object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="expander_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Advanced</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkGrid" id="folder_and_file">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="row_spacing">10</property>
- <property name="column_spacing">15</property>
- <child>
- <object class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Folder:</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkFileChooserButton" id="filebutton">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="hexpand">True</property>
- <property name="action">select-folder</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="fileentry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="activates_default">True</property>
- </object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">1</property>
+ <property name="top_attach">2</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="label5">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">File name:</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
+ <placeholder/>
</child>
</object>
<packing>
- <property name="expand">False</property>
+ <property name="expand">True</property>
<property name="fill">True</property>
- <property name="position">3</property>
+ <property name="position">0</property>
</packing>
</child>
</object>
diff --git a/pitivi/render.py b/pitivi/render.py
index ff18fdbc9..d3c7aa898 100644
--- a/pitivi/render.py
+++ b/pitivi/render.py
@@ -18,6 +18,7 @@
import os
import posixpath
import time
+from enum import IntEnum
from gettext import gettext as _
from gi.repository import GdkPixbuf
@@ -101,7 +102,7 @@ class PresetItem(GObject.Object):
name_dict = {
"youtube": _("YouTube"),
- "dvd": _("DVD")
+ "dvd": _("DVD"),
}
self.name = name
@@ -182,7 +183,7 @@ class PresetsManager(GObject.Object, Loggable):
self.action_save = None
self.cur_preset_item = None
- self.model = Gio.ListStore.new(PresetItem) # preset profiles model
+ self.model = Gio.ListStore.new(PresetItem)
self.load_all()
@@ -246,10 +247,12 @@ class PresetsManager(GObject.Object, Loggable):
def _save_preset_cb(self, unused_action, unused_param):
name = self.cur_preset_item.target.get_name()
+ # Remove the currently selected preset item from the model.
res, pos = self.model.find(self.cur_preset_item)
assert res, self.cur_preset_item.name
self.model.remove(pos)
+ # Recreate the preset with the current values.
self.cur_preset_item = self.create_preset(name)
self.emit("profile-selected", self.cur_preset_item)
@@ -302,7 +305,7 @@ class PresetsManager(GObject.Object, Loggable):
return name
def select_preset(self, preset_item):
- """Selects preset from currently active row in preset listbox.
+ """Selects a preset.
Args:
preset_item (PresetItem): The row representing the preset to be applied.
@@ -558,7 +561,83 @@ def extension_for_muxer(muxer_name):
return exts.get(muxer_name)
-# --------------------------------- Public classes -----------------------------#
+class Quality(IntEnum):
+ LOW = 0
+ MEDIUM = 1
+ HIGH = 2
+
+
+class QualityAdapter(Loggable):
+ """Adapter between a quality value and the properties of an Encoder."""
+
+ def __init__(self, props_values, prop_name=None):
+ super().__init__()
+
+ self.props_values = props_values
+
+ if not prop_name:
+ assert len(props_values) == 1
+ prop_name = list(props_values.keys())[0]
+ self.prop_name = prop_name
+
+ def update_adjustment(self, adjustment, vcodecsettings, callback_handler_id):
+ if self.prop_name in vcodecsettings:
+ encoder_property_value = vcodecsettings[self.prop_name]
+ values = self.props_values[self.prop_name]
+ for quality in (Quality.HIGH, Quality.MEDIUM, Quality.LOW):
+ if (values[0] < values[-1] and encoder_property_value >= values[quality]) or \
+ (values[0] > values[-1] and encoder_property_value <= values[quality]):
+ break
+
+ self.debug("Got existing value for prop %s=%s -> quality=%s", self.prop_name,
encoder_property_value, quality)
+ else:
+ quality = Quality.LOW
+ self.debug("Cannot calculate quality from missing prop %s", self.prop_name)
+
+ adjustment.handler_block(callback_handler_id)
+ try:
+ adjustment.props.value = quality
+ finally:
+ adjustment.handler_unblock(callback_handler_id)
+
+ def update_project_vcodecsettings(self, project, quality):
+ for prop_name, values in self.props_values.items():
+ if callable(values):
+ value = values(project)
+ else:
+ value = values[quality]
+ project.vcodecsettings[prop_name] = value
+
+
+quality_adapters = {
+ Encoders.X264: QualityAdapter(
+ {
+ # quantizer accepts values between 0..50, default is 21.
+ # Values inspired by https://slhck.info/video/2017/03/01/rate-control.html
+ "quantizer": (25, 21, 18),
+ # Encoding pass/type: Constant Quality
+ #
https://gstreamer.freedesktop.org/documentation/x264/index.html?gi-language=python#GstX264EncPass
+ "pass": lambda unused_project: 5,
+ },
+ prop_name="quantizer"),
+ Encoders.VP8: QualityAdapter(
+ {
+ # cq-level accepts values between 0..63, default is 10.
+ "cq-level": (31, 47, 63),
+ # Rate control mode: Constant Quality Mode (CQ) mode
+ #
https://gstreamer.freedesktop.org/documentation/vpx/GstVPXEnc.html?gi-language=python#GstVPXEnc:end-usage
+ "end-usage": lambda unused_project: 2,
+ },
+ prop_name="cq-level"),
+ Encoders.THEORA: QualityAdapter({
+ # Setting the quality property will produce a variable bitrate (VBR) stream.
+ # quality accepts values between 0..63, default is 48.
+ "quality": (31, 48, 63)}),
+ Encoders.JPEG: QualityAdapter({
+ # quality accepts values between 0..100, default is 85.
+ "quality": (70, 85, 100)}),
+}
+
class RenderingProgressDialog(GObject.Object):
@@ -743,6 +822,8 @@ class RenderDialog(Loggable):
self.widgets_group.add_vertex(self.audio_encoder_combo, signal="changed")
self.widgets_group.add_vertex(self.video_encoder_combo, signal="changed")
self.widgets_group.add_vertex(self.preset_menubutton, signal="clicked")
+ self.widgets_group.add_vertex(self.preset_selection_menubutton, signal="clicked")
+ self.widgets_group.add_vertex(self.quality_adjustment, signal="value-changed",
update_func=self._update_quality_adjustment_func)
self.widgets_group.add_edge(self.frame_rate_combo, self.preset_menubutton)
self.widgets_group.add_edge(self.audio_encoder_combo, self.preset_menubutton)
@@ -750,6 +831,9 @@ class RenderDialog(Loggable):
self.widgets_group.add_edge(self.muxer_combo, self.preset_menubutton)
self.widgets_group.add_edge(self.channels_combo, self.preset_menubutton)
self.widgets_group.add_edge(self.sample_rate_combo, self.preset_menubutton)
+ self.widgets_group.add_edge(self.preset_selection_menubutton, self.audio_encoder_combo)
+ self.widgets_group.add_edge(self.preset_selection_menubutton, self.video_encoder_combo)
+ self.widgets_group.add_edge(self.video_encoder_combo, self.quality_adjustment)
def _presets_manager_profile_selected_cb(self, unused_target, preset_item):
"""Handles the selection of a render preset."""
@@ -828,6 +912,20 @@ class RenderDialog(Loggable):
self.preset_icon = builder.get_object("preset_icon")
self.preset_menubutton = builder.get_object("preset_menubutton")
self.preset_popover = builder.get_object("preset_popover")
+ self.quality_box = builder.get_object("quality_box")
+ self.quality_scale = builder.get_object("quality_scale")
+ self.quality_adjustment = self.quality_scale.props.adjustment
+
+ self.quality_adjustment_handler_id = self.quality_adjustment.connect("value-changed",
self._quality_adjustment_value_changed_cb)
+
+ # round_digits is set to -1 in gtk_scale_set_draw_value.
+ # Set it to 0 since we don't care about intermediary values.
+ self.quality_scale.props.round_digits = 0
+
+ lower = self.quality_adjustment.props.lower
+ upper = self.quality_adjustment.props.upper
+ self.quality_scale.add_mark(lower + (upper - lower) / 2, Gtk.PositionType.BOTTOM, _("medium"))
+ self.quality_scale.add_mark(upper, Gtk.PositionType.BOTTOM, _("high"))
self.__automatically_use_proxies = builder.get_object(
"automatically_use_proxies")
@@ -1242,6 +1340,7 @@ class RenderDialog(Loggable):
"""Plays a sound to signal the render operation is done."""
if "GSound" in MISSING_SOFT_DEPS:
return
+
from gi.repository import GSound
sound_context = GSound.Context()
try:
@@ -1316,7 +1415,6 @@ class RenderDialog(Loggable):
# ------------------- Callbacks ------------------------------------------ #
- # -- UI callbacks
def _ok_button_clicked_cb(self, unused_button, media_type):
assert media_type in ("audio", "video")
setattr(self.project, media_type[0] + "codecsettings", self.dialog.get_settings())
@@ -1583,3 +1681,19 @@ class RenderDialog(Loggable):
# Update muxer-dependent widgets.
self.update_available_encoders()
+
+ def _update_quality_adjustment_func(self, unused_source, adjustment):
+ encoder = get_combo_value(self.video_encoder_combo)
+ adapter = quality_adapters.get(encoder.get_name())
+ self.quality_scale.set_sensitive(bool(adapter))
+
+ if adapter:
+ adapter.update_adjustment(self.quality_adjustment, self.project.vcodecsettings,
self.quality_adjustment_handler_id)
+ else:
+ self.quality_adjustment.props.value = self.quality_adjustment.props.lower
+
+ def _quality_adjustment_value_changed_cb(self, adjustment):
+ encoder = get_combo_value(self.video_encoder_combo)
+ adapter = quality_adapters.get(encoder.get_name())
+ quality = round(self.quality_adjustment.props.value)
+ adapter.update_project_vcodecsettings(self.project, quality)
diff --git a/tests/test_render.py b/tests/test_render.py
index f3f212c7c..b518f13da 100644
--- a/tests/test_render.py
+++ b/tests/test_render.py
@@ -31,6 +31,9 @@ from pitivi.render import Encoders
from pitivi.render import extension_for_muxer
from pitivi.render import PresetBoxRow
from pitivi.render import PresetsManager
+from pitivi.render import Quality
+from pitivi.render import quality_adapters
+from pitivi.render import QualityAdapter
from pitivi.timeline.timeline import TimelineContainer
from pitivi.utils.proxy import ProxyingStrategy
from pitivi.utils.ui import get_combo_value
@@ -86,6 +89,34 @@ def setup_render_presets(*profiles):
return setup_wrapper
+class TestQualityAdapter(common.TestCase):
+ """Tests for the QualityAdapter class."""
+
+ def check_adapter(self, adapter, expected_qualities):
+ qualities = []
+ for prop_value in range(len(expected_qualities)):
+ adjustment = mock.Mock()
+ vcodecsettings = {adapter.prop_name: prop_value}
+ adapter.update_adjustment(adjustment, vcodecsettings, 0)
+ qualities.append(adjustment.props.value)
+ self.assertListEqual(qualities, expected_qualities)
+
+ def test_update_adjustment(self):
+ self.check_adapter(QualityAdapter({"prop1": (0, 3, 5)}),
+ [Quality.LOW, Quality.LOW, Quality.LOW, Quality.MEDIUM, Quality.MEDIUM,
Quality.HIGH])
+ self.check_adapter(QualityAdapter({"prop1": (100, 3, 2)}),
+ [Quality.HIGH, Quality.HIGH, Quality.HIGH, Quality.MEDIUM, Quality.LOW,
Quality.LOW])
+
+ self.check_adapter(quality_adapters[Encoders.X264],
+ [Quality.HIGH] * 19 + [Quality.MEDIUM] * 3 + [Quality.LOW] * 29)
+ self.check_adapter(quality_adapters[Encoders.VP8],
+ [Quality.LOW] * 47 + [Quality.MEDIUM] * 16 + [Quality.HIGH] * 1)
+ self.check_adapter(quality_adapters[Encoders.THEORA],
+ [Quality.LOW] * 48 + [Quality.MEDIUM] * 15 + [Quality.HIGH] * 1)
+ self.check_adapter(quality_adapters[Encoders.JPEG],
+ [Quality.LOW] * 85 + [Quality.MEDIUM] * 15 + [Quality.HIGH] * 1)
+
+
class TestRender(BaseTestMediaLibrary):
"""Tests for functions."""
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]