Commit b15312eb authored by Alexandru Băluț's avatar Alexandru Băluț

render: Pick the default encoder from a list

Reviewed-by: Thibault Saunier's avatarThibault Saunier <tsaunier@gnome.org>
Differential Revision: https://phabricator.freedesktop.org/D1167
parent 8f74ce56
......@@ -9,5 +9,5 @@
"framerate-denom": 1001.0,
"width": 0,
"depth": 16,
"acodec": "faac"
"acodec": "voaacenc"
}
......@@ -59,9 +59,6 @@ from pitivi.utils.widgets import FractionWidget
DEFAULT_NAME = _("New Project")
DEFAULT_MUXER = "oggmux"
DEFAULT_VIDEO_ENCODER = "theoraenc"
DEFAULT_AUDIO_ENCODER = "vorbisenc"
class ProjectManager(GObject.Object, Loggable):
......@@ -671,8 +668,7 @@ class Project(Loggable, GES.Project):
self.container_profile = \
GstPbutils.EncodingContainerProfile.new("pitivi-profile",
_("Pitivi encoding profile"),
Gst.Caps(
"application/ogg"),
Gst.Caps("application/ogg"),
None)
self.video_profile = GstPbutils.EncodingVideoProfile.new(
Gst.Caps("video/x-theora"), None, Gst.Caps("video/x-raw"), 0)
......@@ -682,9 +678,9 @@ class Project(Loggable, GES.Project):
self.container_profile.add_profile(self.audio_profile)
self.add_encoding_profile(self.container_profile)
self.muxer = DEFAULT_MUXER
self.vencoder = DEFAULT_VIDEO_ENCODER
self.aencoder = DEFAULT_AUDIO_ENCODER
self.muxer = Encoders().default_muxer
self.vencoder = Encoders().default_video_encoder
self.aencoder = Encoders().default_audio_encoder
self._ensureAudioRestrictions()
self._ensureVideoRestrictions()
has_default_settings = not bool(uri) and not bool(scenario)
......@@ -1141,7 +1137,7 @@ class Project(Loggable, GES.Project):
self.muxer = self._getElementFactoryName(
Encoders().muxers, container_profile)
if self.muxer is None:
self.muxer = DEFAULT_MUXER
self.muxer = Encoders().default_muxer
for profile in container_profile.get_profiles():
if isinstance(profile, GstPbutils.EncodingVideoProfile):
self.video_profile = profile
......
......@@ -44,7 +44,7 @@ from pitivi.utils.ui import set_combo_value
from pitivi.utils.widgets import GstElementSettingsDialog
class Encoders(object):
class Encoders(Loggable):
"""Registry of avalaible Muxers, Audio encoders and Video encoders.
Also keeps the avalaible combinations of those.
......@@ -59,6 +59,45 @@ class Encoders(object):
compatible audio encoders ordered by rank.
compatible_video_encoders (dict): Maps each muxer name to a list of
compatible video encoders ordered by rank.
default_muxer (str): The factory name of the default muxer.
default_audio_encoder (str): The factory name of the default audio
encoder.
default_video_encoder (str): The factory name of the default video
encoder.
"""
OGG = "oggmux"
MKV = "matroskamux"
MP4 = "mp4mux"
QUICKTIME = "qtmux"
WEBM = "webmmux"
AAC = "voaacenc"
AC3 = "avenc_ac3_fixed"
OPUS = "opusenc"
VORBIS = "vorbisenc"
JPEG = "jpegenc"
THEORA = "theoraenc"
VP8 = "vp8enc"
X264 = "x264enc"
SUPPORTED_ENCODERS_COMBINATIONS = [
(OGG, VORBIS, THEORA),
(OGG, OPUS, THEORA),
(WEBM, VORBIS, VP8),
(WEBM, OPUS, VP8),
(MP4, AAC, X264),
(MP4, AC3, X264),
(QUICKTIME, AAC, JPEG),
(MKV, OPUS, X264),
(MKV, VORBIS, X264),
(MKV, OPUS, JPEG),
(MKV, VORBIS, JPEG)]
"""The combinations of muxers and encoders which are supported.
Mirror of GES_ENCODING_TARGET_COMBINATIONS from
https://cgit.freedesktop.org/gstreamer/gst-editing-services/tree/tests/validate/geslaunch.py
"""
_instance = None
......@@ -67,6 +106,9 @@ class Encoders(object):
"""Returns the singleton instance."""
if not cls._instance:
cls._instance = super(Encoders, cls).__new__(cls, *args, **kwargs)
# We have to initialize the instance here, otherwise
# __init__ is called every time we use Encoders().
Loggable.__init__(cls._instance)
Gst.Registry.get().connect(
"feature-added", cls._instance._registry_feature_added_cb)
cls._instance._load_encoders()
......@@ -108,6 +150,10 @@ class Encoders(object):
for muxer in useless_muxers:
self.muxers.remove(muxer)
self.default_muxer, \
self.default_audio_encoder, \
self.default_video_encoder = self._pick_defaults()
def _find_compatible_encoders(self, encoders, muxer):
"""Returns the list of encoders compatible with the specified muxer."""
res = []
......@@ -130,6 +176,25 @@ class Encoders(object):
return True
return False
def _pick_defaults(self):
"""Picks the defaults for new projects.
Returns:
(str, str, str): The muxer, audio encoder, video encoder.
"""
muxer_names = [fact.get_name() for fact in self.muxers]
aencoder_names = [fact.get_name() for fact in self.aencoders]
vencoder_names = [fact.get_name() for fact in self.vencoders]
for muxer, audio, video in self.SUPPORTED_ENCODERS_COMBINATIONS:
if muxer not in muxer_names or \
audio not in aencoder_names or \
video not in vencoder_names:
continue
self.info("Default encoders: %s, %s, %s", muxer, audio, video)
return muxer, audio, video
self.warning("No good combination of container and encoders available.")
return Encoders.OGG, Encoders.VORBIS, Encoders.THEORA
def _registry_feature_added_cb(self, registry, feature):
# TODO Check what feature has been added and update our lists
pass
......@@ -155,8 +220,12 @@ def beautify_factoryname(factory):
return " ".join(word for word in name.split())
def extension_for_muxer(muxer):
"""Returns the file extension appropriate for the specified muxer."""
def extension_for_muxer(muxer_name):
"""Returns the file extension appropriate for the specified muxer.
Args:
muxer_name (str): The name of the muxer factory.
"""
exts = {
"asfmux": "asf",
"avimux": "avi",
......@@ -185,7 +254,7 @@ def extension_for_muxer(muxer):
"oggmux": "ogv",
"qtmux": "mov",
"webmmux": "webm"}
return exts.get(muxer)
return exts.get(muxer_name)
def factorylist(factories):
......
# -*- coding: utf-8 -*-
# Pitivi video editor
# Copyright (c) 2016, Alex Băluț <alexandru.balut@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
"""Tests for the render module."""
from unittest import mock
from unittest import TestCase
from pitivi.preset import RenderPresetManager
from pitivi.render import Encoders
from pitivi.render import extension_for_muxer
class TestRender(TestCase):
"""Tests for functions."""
def test_extensions_supported(self):
"""Checks we associate file extensions to the well supported muxers."""
for muxer, unused_audio, unused_video in Encoders.SUPPORTED_ENCODERS_COMBINATIONS:
self.assertIsNotNone(extension_for_muxer(muxer), muxer)
def test_extensions_presets(self):
"""Checks we associate file extensions to the muxers of the presets."""
with mock.patch("pitivi.preset.xdg_data_home") as xdg_data_home:
xdg_data_home.return_value = "/pitivi-dir-which-does-not-exist"
preset_manager = RenderPresetManager(system=None)
preset_manager.loadAll()
self.assertTrue(preset_manager.presets)
for unused_name, preset in preset_manager.presets.items():
muxer = preset["container"]
self.assertIsNotNone(extension_for_muxer(muxer), preset)
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