[pitivi] render: Ensure x264enc input format to be Y444
- From: Thibault Saunier <tsaunier src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] render: Ensure x264enc input format to be Y444
- Date: Fri, 3 Feb 2017 21:47:25 +0000 (UTC)
commit 7397b0f3e55ce6e2d8c6c9f1f4e90651755a5573
Author: Thibault Saunier <thibault saunier osg samsung com>
Date: Tue Jan 10 10:49:15 2017 -0300
render: Ensure x264enc input format to be Y444
To avoid the restriction around video width needing to be even.
Good explanation of libx264 restrictions available in
http://stackoverflow.com/questions/20847674/ffmpeg-libx264-height-not-divisible-by-2/29582287#29582287
Fixes https://phabricator.freedesktop.org/T3182
Differential Revision: https://phabricator.freedesktop.org/D1603
pitivi/project.py | 24 ++++++++++++++++++++++++
pitivi/render.py | 1 -
tests/test_render.py | 44 +++++++++++++++++++++++++++++++++++++++++---
3 files changed, 65 insertions(+), 4 deletions(-)
---
diff --git a/pitivi/project.py b/pitivi/project.py
index d97f0d4..aff722d 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -62,6 +62,17 @@ from pitivi.utils.widgets import FractionWidget
DEFAULT_NAME = _("New Project")
+# This is a dictionary to allow adding special restrictions when using a specific
+# encoder element.
+# For example x264enc can't encode frame with odd size if its input format is not Y444
+# so in that case we make sure to force Y444 as x264enc input format.
+ENCODERS_RESTRICTIONS_SETTER = {
+ # To avoid restriction of size in x264enc, make sure that the encoder
+ # input color space is Y444 so that we do not have any restriction
+ "x264enc": lambda project, profile: project._set_restriction(
+ profile, "format", "Y444")
+}
+
class ProjectManager(GObject.Object, Loggable):
"""The project manager.
@@ -883,6 +894,14 @@ class Project(Loggable, GES.Project):
self.audio_profile.set_preset(None)
self._emitChange("rendering-settings-changed", "aencoder", value)
+ def _enforce_video_encoder_restrictions(self, encoder, profile=None):
+ """Enforces @encoder specific restrictions."""
+ if not profile:
+ profile = self.video_profile
+ restriction_setter = ENCODERS_RESTRICTIONS_SETTER.get(encoder)
+ if restriction_setter:
+ restriction_setter(self, profile)
+
@property
def vencoder(self):
return self.video_profile.get_preset_name()
@@ -896,6 +915,7 @@ class Project(Loggable, GES.Project):
self.video_profile.set_preset_name(value)
# Gst.Preset can be set exclusively through EncodingTagets for now.
self.video_profile.set_preset(None)
+ self._enforce_video_encoder_restrictions(value)
self._emitChange("rendering-settings-changed", "vencoder", value)
@property
@@ -1491,6 +1511,10 @@ class Project(Loggable, GES.Project):
value = ref_restrictions[0][fieldname]
res = Project._set_restriction(profile, fieldname, value)
+ encoder = profile.get_preset_name()
+ if encoder:
+ self._enforce_video_encoder_restrictions(encoder, profile)
+
def _ensureVideoRestrictions(self, profile=None, ref_restrictions=None):
values = [
("width", 720),
diff --git a/pitivi/render.py b/pitivi/render.py
index b1c9940..50eb150 100644
--- a/pitivi/render.py
+++ b/pitivi/render.py
@@ -40,7 +40,6 @@ from pitivi.utils.ui import audio_rates
from pitivi.utils.ui import beautify_ETA
from pitivi.utils.ui import frame_rates
from pitivi.utils.ui import get_combo_value
-from pitivi.utils.ui import PADDING
from pitivi.utils.ui import set_combo_value
from pitivi.utils.widgets import GstElementSettingsDialog
from pitivi.utils.widgets import TextWidget
diff --git a/tests/test_render.py b/tests/test_render.py
index 49ccc4d..07005f0 100644
--- a/tests/test_render.py
+++ b/tests/test_render.py
@@ -19,18 +19,30 @@
"""Tests for the render module."""
# pylint: disable=protected-access,no-self-use
from unittest import mock
+from unittest import skipUnless
from gi.repository import GES
from gi.repository import Gst
+from gi.repository import GstPbutils
from gi.repository import Gtk
from pitivi.preset import EncodingTargetManager
from pitivi.render import Encoders
from pitivi.render import extension_for_muxer
from pitivi.utils.ui import get_combo_value
+from pitivi.utils.ui import set_combo_value
from tests import common
+def factory_exists(*factories):
+ """Checks if @factories exists."""
+ for factory in factories:
+ if not Gst.ElementFactory.find(factory):
+ return False, "%s not present on the system" % (factory)
+
+ return True, ""
+
+
class TestRender(common.TestCase):
"""Tests for functions."""
@@ -54,7 +66,7 @@ class TestRender(common.TestCase):
self.assertIsNotNone(extension_for_muxer(muxer), container_profile)
def create_simple_project(self):
- """Create a Project with a layer a clip."""
+ """Creates a Project with a layer a clip."""
timeline_container = common.create_timeline_container()
app = timeline_container.app
project = app.project_manager.current_project
@@ -78,7 +90,7 @@ class TestRender(common.TestCase):
return project
def create_rendering_dialog(self, project):
- """Create a RenderingDialog ready for testing"""
+ """Creates a RenderingDialog ready for testing"""
from pitivi.render import RenderDialog
class MockedBuilder(Gtk.Builder):
@@ -106,9 +118,35 @@ class TestRender(common.TestCase):
with mock.patch.object(dialog, "_pipeline"):
return dialog._renderButtonClickedCb(None)
+ @skipUnless(*factory_exists("x264enc", "matroskamux"))
+ def test_encoder_restrictions(self):
+ """Checks the mechanism to respect encoder specific restrictions."""
+ project = self.create_simple_project()
+ dialog = self.create_rendering_dialog(project)
+
+ # Explicitly set the encoder
+ self.assertTrue(set_combo_value(dialog.muxer_combo,
+ Gst.ElementFactory.find("matroskamux")))
+ self.assertTrue(set_combo_value(dialog.video_encoder_combo,
+ Gst.ElementFactory.find("x264enc")))
+ self.assertEqual(project.video_profile.get_restriction()[0]["format"],
+ "Y444")
+
+ # Set encoding profile
+ if getattr(GstPbutils.EncodingProfile, "copy"): # Available only in > 1.11
+ profile = project.container_profile.copy()
+ vprofile, = [p for p in profile.get_profiles()
+ if isinstance(p, GstPbutils.EncodingVideoProfile)]
+ vprofile.set_restriction(Gst.Caps('video/x-raw'))
+ project.set_container_profile(profile)
+ self.assertEqual(project.video_profile.get_restriction()[0]["format"],
+ "Y444")
+
# pylint: disable=too-many-locals
+ @skipUnless(*factory_exists("vorbisenc", "theoraenc", "oggmux",
+ "opusenc", "vp8enc"))
def test_loading_preset(self):
- """Check preset values are properly exposed in the UI."""
+ """Checks preset values are properly exposed in the UI."""
def find_preset_row_index(combo, name):
"""Finds @name in @combo."""
for i, row in enumerate(combo.get_model()):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]