Commit 2df88480 authored by Thibault Saunier's avatar Thibault Saunier

Remove broken support for non square pixels

All the compositing is done on square pixels, and modern formats all
use square pixels.

At least for now, we will only work with square pixels.

And update/fix video presets.
Reviewed-by: 's avatarAlex Băluț <&lt;alexandru.balut@gmail.com&gt;>
Differential Revision: https://phabricator.freedesktop.org/D1871
parent 4a5844f5
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.19.0 -->
<!-- Generated with glade 3.20.1 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkAdjustment" id="adjustment1">
......@@ -280,115 +280,6 @@
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="aspect_ratio_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">6</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">Aspect Ratio:</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>
<child>
<object class="GtkGrid" id="aspect_ratio_grid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<property name="valign">start</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkRadioButton" id="select_dar_radiobutton">
<property name="label" translatable="yes" comments="DAR is the aspect ratio of the image being displayed to the viewer. &quot;Display&quot; is used as a noun, not as a verb/action.">Display aspect ratio</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.5</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="_selectDarRadiobuttonToggledCb" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="dar_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<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">1</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="par_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkCellRendererText" id="renderer2"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="select_par_radiobutton">
<property name="label" translatable="yes" comments="PAR is the aspect ratio &quot;of the pixels&quot;, not an aspect ratio &quot;in pixels&quot;.">Pixel aspect ratio</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.5</property>
<property name="draw_indicator">True</property>
<property name="group">select_dar_radiobutton</property>
</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">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="frame_rate_box">
<property name="visible">True</property>
......@@ -436,7 +327,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="position">1</property>
</packing>
</child>
</object>
......
{
"par-num": 4.0,
"name": "HDV 1080i30",
"framerate-num": 30000.0,
"name": "SD 1080p24",
"framerate-num": 24000.0,
"framerate-denom": 1001.0,
"height": 1080,
"width": 1440,
"par-denom": 3.0
"width": 1440
}
{
"name": "SD 1080p30",
"framerate-num": 30.0,
"framerate-denom": 1.0,
"height": 1080,
"width": 1440
}
{
"par-num": 1.0,
"name": "1080p24",
"name": "HD 1080p24",
"framerate-num": 24000.0,
"framerate-denom": 1001.0,
"height": 1080,
"width": 1920,
"par-denom": 1.0
"width": 1920
}
{
"name": "HD 1080p30",
"framerate-num": 30.0,
"framerate-denom": 1.0,
"height": 1080,
"width": 1920
}
{
"par-num": 1.0,
"name": "720p24",
"framerate-num": 24000.0,
"framerate-denom": 1001.0,
"height": 720,
"width": 1280,
"par-denom": 1.0
"width": 1280
}
{
"par-num": 1.0,
"name": "720p30",
"framerate-num": 30000.0,
"framerate-denom": 1001.0,
"height": 720,
"width": 1280,
"par-denom": 1.0
"width": 1280
}
{
"par-num": 16.0,
"name": "iPod",
"framerate-num": 25.0,
"framerate-denom": 1.0,
"height": 240,
"width": 320,
"par-denom": 15.0
}
......@@ -358,6 +358,14 @@ def initialize_modules():
from pitivi.configure import get_audiopresets_dir, get_videopresets_dir
Gst.init(None)
require_version("GstPbutils", GST_API_VERSION)
from gi.repository import GstPbutils
# Monky patch an helper method to retrieve the size of a video
# when using square pixels.
GstPbutils.DiscovererVideoInfo.get_square_width = \
lambda i: i.get_width() * i.get_par_num() / i.get_par_denom()
if not os.environ.get("GES_DISCOVERY_TIMEOUT"):
os.environ["GES_DISCOVERY_TIMEOUT"] = "5"
......
......@@ -88,7 +88,7 @@ class ClipMediaPropsDialog(object):
break
for stream in self.video_streams:
self.size_width.set_text(str(stream.get_width()))
self.size_width.set_text(str(stream.get_square_width()))
self.size_height.set_text(str(stream.get_height()))
self.is_image = stream.is_image()
if not self.is_image:
......@@ -145,14 +145,11 @@ class ClipMediaPropsDialog(object):
# This also handles the case where the video is a still image
video = self.video_streams[0]
if self.size_checkbutton.get_active():
project.videowidth = video.get_width()
project.videowidth = video.get_square_width()
project.videoheight = video.get_height()
if self.framerate_checkbutton.get_active() and not self.is_image:
project.videorate = Gst.Fraction(video.get_framerate_num(),
video.get_framerate_denom())
if self.PAR_checkbutton.get_active() and not self.is_image:
project.videopar = Gst.Fraction(video.get_par_num(),
video.get_par_denom())
if self.has_audio:
audio = self.audio_streams[0]
if self.channels_checkbutton.get_active():
......
......@@ -1325,7 +1325,7 @@ class PreviewAssetWindow(Gtk.Window):
# For videos and images, automatically resize the window
# Try to keep it 1:1 if it can fit within 85% of the parent window
video = video_streams[0]
img_width = video.get_width()
img_width = video.get_square_width()
img_height = video.get_height()
mainwindow_width, mainwindow_height = self._main_window.get_size()
max_width = 0.85 * mainwindow_width
......
......@@ -255,8 +255,7 @@ class PreviewWidget(Gtk.Grid, Loggable):
self.player.setClipUri(self.current_selected_uri)
self.player.setState(Gst.State.PAUSED)
self.pos_adj.props.upper = duration
video_width = (
video.get_par_num() / video.get_par_denom()) * video.get_width()
video_width = video.get_square_width()
video_height = video.get_height()
w, h = self.__get_best_size(video_width, video_height)
self.preview_video.set_size_request(w, h)
......
......@@ -438,15 +438,10 @@ class VideoPresetManager(PresetManager):
framerate_denom = parser["framerate-denom"]
framerate = Gst.Fraction(framerate_num, framerate_denom)
par_num = parser["par-num"]
par_denom = parser["par-denom"]
par = Gst.Fraction(par_num, par_denom)
return {
"width": width,
"height": height,
"frame-rate": framerate,
"par": par,
}
def _serializePreset(self, preset):
......@@ -455,16 +450,13 @@ class VideoPresetManager(PresetManager):
"height": int(preset["height"]),
"framerate-num": preset["frame-rate"].num,
"framerate-denom": preset["frame-rate"].denom,
"par-num": preset["par"].num,
"par-denom": preset["par"].denom,
}
def _projectToPreset(self, project):
return {
"width": project.videowidth,
"height": project.videoheight,
"frame-rate": project.videorate,
"par": project.videopar}
"frame-rate": project.videorate}
class AudioPresetManager(PresetManager):
......
......@@ -884,16 +884,6 @@ class Project(Loggable, GES.Project):
if self.setVideoRestriction("framerate", value):
self._emitChange("rendering-settings-changed", "videorate", value)
@property
def videopar(self):
return self.video_profile.get_restriction()[0]["pixel-aspect-ratio"]
@videopar.setter
def videopar(self, value):
if self.setVideoRestriction("pixel-aspect-ratio", value):
self._emitChange(
"rendering-settings-changed", "pixel-aspect-ratio", value)
@property
def audiochannels(self):
return self.audio_profile.get_restriction()[0]["channels"]
......@@ -1472,10 +1462,12 @@ class Project(Loggable, GES.Project):
videocaps.set_value("width", width)
videocaps.set_value("height", height)
videocaps.set_value("framerate", self.videorate)
videocaps.set_value("pixel-aspect-ratio", Gst.Fraction(1, 1))
audiocaps = Gst.Caps.new_empty_simple("audio/x-raw")
audiocaps.set_value("rate", self.audiorate)
audiocaps.set_value("channels", self.audiochannels)
for track in self.ges_timeline.get_tracks():
if isinstance(track, GES.VideoTrack):
track.set_restriction_caps(videocaps)
......@@ -1550,7 +1542,7 @@ class Project(Loggable, GES.Project):
return self._dirty
def getDAR(self):
return Gst.Fraction(self.videowidth, self.videoheight) * self.videopar
return Gst.Fraction(self.videowidth, self.videoheight)
def getVideoWidthAndHeight(self, render=False):
"""Returns the video width and height as a tuple.
......@@ -1579,9 +1571,8 @@ class Project(Loggable, GES.Project):
Gst.Caps: The video settings caps.
"""
videowidth, videoheight = self.getVideoWidthAndHeight(render=render)
vstr = "width=%d,height=%d,pixel-aspect-ratio=%d/%d,framerate=%d/%d" % (
vstr = "width=%d,height=%d,pixel-aspect-ratio=1/1,framerate=%d/%d" % (
videowidth, videoheight,
self.videopar.num, self.videopar.denom,
self.videorate.num, self.videorate.denom)
caps_str = "video/x-raw,%s" % (vstr)
video_caps = Gst.caps_from_string(caps_str)
......@@ -1772,14 +1763,12 @@ class Project(Loggable, GES.Project):
if video_streams and self._has_default_video_settings:
video = video_streams[0]
if not video.is_image():
self.videowidth = video.get_width()
self.videowidth = video.get_square_width()
self.videoheight = video.get_height()
if video.get_framerate_num() > 0:
# The asset has a non-variable framerate.
self.videorate = Gst.Fraction(video.get_framerate_num(),
video.get_framerate_denom())
self.videopar = Gst.Fraction(video.get_par_num(),
video.get_par_denom())
self._has_default_video_settings = False
emit = True
audio_streams = info.get_audio_streams()
......@@ -1858,8 +1847,6 @@ class ProjectSettingsDialog(object):
getObj = self.builder.get_object
self.window = getObj("project-settings-dialog")
self.frame_rate_combo = getObj("frame_rate_combo")
self.dar_combo = getObj("dar_combo")
self.par_combo = getObj("par_combo")
self.channels_combo = getObj("channels_combo")
self.sample_rate_combo = getObj("sample_rate_combo")
self.year_spinbutton = getObj("year_spinbutton")
......@@ -1868,7 +1855,6 @@ class ProjectSettingsDialog(object):
self.height_spinbutton = getObj("height_spinbutton")
self.audio_presets_combo = getObj("audio_presets_combo")
self.video_presets_combo = getObj("video_presets_combo")
self.select_par_radiobutton = getObj("select_par_radiobutton")
self.constrain_sar_button = getObj("constrain_sar_button")
self.select_dar_radiobutton = getObj("select_dar_radiobutton")
self.title_entry = getObj("title_entry")
......@@ -1885,14 +1871,6 @@ class ProjectSettingsDialog(object):
def _setupUiConstraints(self):
"""Creates the dynamic widgets and connects other widgets."""
# Add custom fraction widgets for DAR and PAR.
aspect_ratio_grid = self.builder.get_object("aspect_ratio_grid")
self.dar_fraction_widget = FractionWidget()
aspect_ratio_grid.attach(self.dar_fraction_widget, 0, 2, 1, 1)
self.dar_fraction_widget.show()
self.par_fraction_widget = FractionWidget()
aspect_ratio_grid.attach(self.par_fraction_widget, 1, 2, 1, 1)
self.par_fraction_widget.show()
# Add custom framerate fraction widget.
frame_rate_box = self.builder.get_object("frame_rate_box")
......@@ -1902,8 +1880,6 @@ class ProjectSettingsDialog(object):
# Populate comboboxes.
self.frame_rate_combo.set_model(frame_rates)
self.dar_combo.set_model(display_aspect_ratios)
self.par_combo.set_model(pixel_aspect_ratios)
self.channels_combo.set_model(audio_channels)
self.sample_rate_combo.set_model(audio_rates)
......@@ -1918,10 +1894,6 @@ class ProjectSettingsDialog(object):
signal="value-changed",
update_func=self._updateFraction,
update_func_args=(self.frame_rate_combo,))
self.wg.addVertex(self.dar_combo, signal="changed")
self.wg.addVertex(self.dar_fraction_widget, signal="value-changed")
self.wg.addVertex(self.par_combo, signal="changed")
self.wg.addVertex(self.par_fraction_widget, signal="value-changed")
self.wg.addVertex(self.width_spinbutton, signal="value-changed")
self.wg.addVertex(self.height_spinbutton, signal="value-changed")
self.wg.addVertex(self.audio_preset_menubutton,
......@@ -1945,41 +1917,6 @@ class ProjectSettingsDialog(object):
self.wg.addBiEdge(
self.frame_rate_combo, self.frame_rate_fraction_widget)
# Keep the DAR combo and fraction widgets in sync.
self.wg.addEdge(self.dar_combo, self.dar_fraction_widget,
edge_func=self.updateDarFromCombo)
self.wg.addEdge(self.dar_fraction_widget, self.dar_combo,
edge_func=self.updateDarFromFractionWidget)
# Keep the PAR combo and fraction widgets in sync.
self.wg.addEdge(self.par_combo, self.par_fraction_widget,
edge_func=self.updateParFromCombo)
self.wg.addEdge(self.par_fraction_widget, self.par_combo,
edge_func=self.updateParFromFractionWidget)
# Constrain the DAR and PAR by linking the fraction widgets together.
# The combos are already linked to their fraction widgets.
self.wg.addEdge(self.par_fraction_widget, self.dar_fraction_widget,
edge_func=self.updateDarFromPar)
self.wg.addEdge(self.dar_fraction_widget, self.par_fraction_widget,
edge_func=self.updateParFromDar)
# Update the PAR when the w or h change and the DAR radio is selected.
self.wg.addEdge(self.width_spinbutton, self.par_fraction_widget,
predicate=self.darSelected,
edge_func=self.updateParFromDar)
self.wg.addEdge(self.height_spinbutton, self.par_fraction_widget,
predicate=self.darSelected,
edge_func=self.updateParFromDar)
# Update the DAR when the w or h change and the PAR radio is selected.
self.wg.addEdge(self.width_spinbutton, self.dar_fraction_widget,
predicate=self.parSelected,
edge_func=self.updateDarFromPar)
self.wg.addEdge(self.height_spinbutton, self.dar_fraction_widget,
predicate=self.parSelected,
edge_func=self.updateDarFromPar)
# Presets.
self.audio_presets.loadAll()
self.video_presets.loadAll()
......@@ -1990,15 +1927,12 @@ class ProjectSettingsDialog(object):
self.video_presets, "height", self.height_spinbutton)
self.bindFractionWidget(
self.video_presets, "frame-rate", self.frame_rate_fraction_widget)
self.bindPar(self.video_presets)
# Bind the widgets in the Audio tab to the Audio Presets Manager.
self.bindCombo(self.audio_presets, "channels", self.channels_combo)
self.bindCombo(
self.audio_presets, "sample-rate", self.sample_rate_combo)
self.wg.addEdge(
self.par_fraction_widget, self.video_preset_menubutton)
self.wg.addEdge(
self.frame_rate_fraction_widget, self.video_preset_menubutton)
self.wg.addEdge(self.width_spinbutton, self.video_preset_menubutton)
......@@ -2007,16 +1941,6 @@ class ProjectSettingsDialog(object):
self.wg.addEdge(self.channels_combo, self.audio_preset_menubutton)
self.wg.addEdge(self.sample_rate_combo, self.audio_preset_menubutton)
def bindPar(self, mgr):
def updatePar(value):
# activate par so we can set the value
self.select_par_radiobutton.props.active = True
self.par_fraction_widget.setWidgetValue(value)
mgr.bindWidget(
"par", updatePar, self.par_fraction_widget.getWidgetValue)
def bindFractionWidget(self, mgr, name, widget):
mgr.bindWidget(name, widget.setWidgetValue, widget.getWidgetValue)
......@@ -2053,25 +1977,9 @@ class ProjectSettingsDialog(object):
def _updateSar(self):
self.sar = self.getSAR()
def _selectDarRadiobuttonToggledCb(self, unused_button):
self._updateDarParSensitivity()
def _updateDarParSensitivity(self):
dar_is_selected = self.darSelected()
self.dar_fraction_widget.set_sensitive(dar_is_selected)
self.dar_combo.set_sensitive(dar_is_selected)
self.par_fraction_widget.set_sensitive(not dar_is_selected)
self.par_combo.set_sensitive(not dar_is_selected)
def _updatePresetMenuButton(self, unused_source, unused_target, mgr):
mgr.updateMenuActions()
def darSelected(self):
return self.select_dar_radiobutton.props.active
def parSelected(self):
return not self.darSelected()
def updateWidth(self):
height = int(self.height_spinbutton.get_value())
fraction = height * self.sar
......@@ -2084,42 +1992,11 @@ class ProjectSettingsDialog(object):
height = int(fraction.num / fraction.denom)
self.height_spinbutton.set_value(height)
def updateDarFromPar(self):
par = self.par_fraction_widget.getWidgetValue()
sar = self.getSAR()
self.dar_fraction_widget.setWidgetValue(sar * par)
def updateParFromDar(self):
dar = self.dar_fraction_widget.getWidgetValue()
sar = self.getSAR()
self.par_fraction_widget.setWidgetValue(dar / sar)
def updateDarFromCombo(self):
self.dar_fraction_widget.setWidgetValue(
get_combo_value(self.dar_combo))
def updateDarFromFractionWidget(self):
set_combo_value(
self.dar_combo, self.dar_fraction_widget.getWidgetValue())
def updateParFromCombo(self):
self.par_fraction_widget.setWidgetValue(
get_combo_value(self.par_combo))
def updateParFromFractionWidget(self):
set_combo_value(
self.par_combo, self.par_fraction_widget.getWidgetValue())
def updateUI(self):
# Video
self.width_spinbutton.set_value(self.project.videowidth)
self.height_spinbutton.set_value(self.project.videoheight)
self.frame_rate_fraction_widget.setWidgetValue(self.project.videorate)
self.par_fraction_widget.setWidgetValue(self.project.videopar)
if self.project.videopar == Gst.Fraction(1, 1):
self.select_par_radiobutton.props.active = True
self._updateDarParSensitivity()
matching_video_preset = self.video_presets.matchingPreset(self.project)
if matching_video_preset:
......@@ -2151,7 +2028,6 @@ class ProjectSettingsDialog(object):
self.project.videowidth = int(self.width_spinbutton.get_value())
self.project.videoheight = int(self.height_spinbutton.get_value())
self.project.videopar = self.par_fraction_widget.getWidgetValue()
self.project.videorate = self.frame_rate_fraction_widget.getWidgetValue()
self.project.audiochannels = get_combo_value(self.channels_combo)
......
......@@ -900,7 +900,7 @@ class VideoSource(TimelineElement):
video_source = self._ges_elem
sinfo = video_source.get_asset().get_stream_info()
asset_width = sinfo.get_width()
asset_width = sinfo.get_square_width()
asset_height = sinfo.get_height()
parent = video_source.get_parent()
if parent and not self.__videoflip:
......@@ -921,7 +921,7 @@ class VideoSource(TimelineElement):
assert res
if "clockwise" in method.value_nick and self.__videoflip.props.active:
asset_width = sinfo.get_height()
asset_height = sinfo.get_width()
asset_height = sinfo.get_square_width()
# Find the biggest size of the video inside the
# final view (project size) keeping the aspect ratio
......
......@@ -528,8 +528,6 @@ class TestProjectSettings(common.TestCase):
self.assertEqual(1080, project.videoheight)
project.videorate = Gst.Fraction(50, 7)
self.assertEqual(Gst.Fraction(50, 7), project.videorate)
project.videopar = Gst.Fraction(2, 7)
self.assertEqual(Gst.Fraction(2, 7), project.videopar)
def testSetAudioProp(self):
timeline = common.create_timeline_container()
......@@ -597,7 +595,6 @@ class TestProjectSettings(common.TestCase):
self.assertEqual(960, project.videowidth)
self.assertEqual(400, project.videoheight)
self.assertEqual(Gst.Fraction(24, 1), project.videorate)
self.assertEqual(Gst.Fraction(1, 1), project.videopar)
def testLoad(self):
project = Project(uri="fake.xges", app=common.create_pitivi_mock())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment