Skip to content

Commit

Permalink
Fix Freeseer#623 Add audio/video quality configuration support
Browse files Browse the repository at this point in the history
  • Loading branch information
farazs committed Dec 12, 2014
1 parent 6a1330a commit 872c68c
Show file tree
Hide file tree
Showing 15 changed files with 586 additions and 24 deletions.
69 changes: 69 additions & 0 deletions src/freeseer/framework/multimedia.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,54 @@ def set_audio_feedback_handler(self, audio_feedback):
"""Sets the handler for Audio Feedback levels"""
self.audio_feedback_event = audio_feedback

def compute_bitrate(self):
"""Compute the bitrate based on current quality and video input resolution"""
mixer_plugin = self.plugman.get_plugin_by_name(self.config.videomixer, "VideoMixer")
pixels = mixer_plugin.plugin_object.get_resolution_pixels()
quality = self.config.video_quality

if quality == Quality.LOW:
bitrate = pixels * Quality.LOW_VIDEO_FACTOR
elif quality == Quality.MEDIUM:
bitrate = pixels * Quality.MEDIUM_VIDEO_FACTOR
elif quality == Quality.HIGH:
bitrate = pixels * Quality.HIGH_VIDEO_FACTOR

return int(round(bitrate / 100) * 100)

def update_video_quality(self):
"""Update video bitrate based on quality for file and stream output"""
if self.config.video_quality == Quality.CUSTOM:
return

bitrate = self.compute_bitrate()

file_output_plugin = self.plugman.get_plugin_by_name(self.config.record_to_file_plugin, "Output")
stream_output_plugin = self.plugman.get_plugin_by_name(self.config.record_to_stream_plugin, "Output")

file_configurable = file_output_plugin.plugin_object.configurable
stream_configurable = stream_output_plugin.plugin_object.configurable

if file_configurable:
file_output_plugin.plugin_object.set_video_bitrate(bitrate)

if stream_configurable:
stream_output_plugin.plugin_object.set_video_bitrate(bitrate)

if file_configurable or stream_configurable:
log.info("Set video bitrate to %s", bitrate)

def update_audio_quality(self):
"""Update audio quality for file and stream output"""
if self.config.audio_quality == Quality.CUSTOM:
return

file_output_plugin = self.plugman.get_plugin_by_name(self.config.record_to_file_plugin, "Output")
stream_output_plugin = self.plugman.get_plugin_by_name(self.config.record_to_stream_plugin, "Output")

file_output_plugin.plugin_object.set_audio_quality(self.config.audio_quality)
stream_output_plugin.plugin_object.set_audio_quality(self.config.audio_quality)

##
## Recording functions
##
Expand Down Expand Up @@ -183,6 +231,9 @@ def load_backend(self, presentation=None, filename=None):

load_plugins = []

self.update_video_quality()
self.update_audio_quality()

if self.config.record_to_file:
p = self.plugman.get_plugin_by_name(self.config.record_to_file_plugin, "Output")
load_plugins.append(p)
Expand Down Expand Up @@ -377,3 +428,21 @@ def unload_videomixer(self):
self.videomixer.unlink(self.video_tee)
self.player.remove(self.videomixer)
self.record_video = False


class Quality:
"""Class to hold constants for Audio/Video quality"""
qualities = ["High", "Medium", "Low", "Custom"]

LOW = qualities.index("Low")
MEDIUM = qualities.index("Medium")
HIGH = qualities.index("High")
CUSTOM = qualities.index("Custom")

HIGH_VIDEO_FACTOR = 0.006
MEDIUM_VIDEO_FACTOR = 0.0045
LOW_VIDEO_FACTOR = 0.003

HIGH_AUDIO_FACTOR = 0.8
MEDIUM_AUDIO_FACTOR = 0.5
LOW_AUDIO_FACTOR = 0.2
41 changes: 39 additions & 2 deletions src/freeseer/framework/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ class IBackendPlugin(IPlugin):
os = []

config_loaded = False
widget_config_loaded = False

def __init__(self):
IPlugin.__init__(self)
Expand Down Expand Up @@ -289,9 +290,9 @@ def get_dialog(self):
self.retranslate() # Translate the UI

# Only load configuration the first time the user opens widget
if not self.config_loaded:
if not self.widget_config_loaded:
log.debug("%s loading configuration into widget.", self.name)
self.config_loaded = True
self.widget_config_loaded = True
self.widget_load_config(self.plugman)

if widget is not None:
Expand All @@ -300,6 +301,12 @@ def get_dialog(self):
if self.config is not None:
self.config.save()

def get_config(self):
"""Check if the config is loaded, if not then load it."""
if not self.config_loaded:
self.config_loaded = True
self.load_config(self.plugman)

def get_widget(self):
"""
Implement this method to return the settings widget (Qt based).
Expand Down Expand Up @@ -377,6 +384,9 @@ def get_videoinput_bin(self):
"""
raise NotImplementedError

def get_resolution_pixels(self):
raise NotImplementedError


class IVideoMixer(IBackendPlugin):
CATEGORY = "VideoMixer"
Expand Down Expand Up @@ -408,6 +418,18 @@ def load_inputs(self, player, mixer, inputs):
"""
raise NotImplementedError

def get_resolution_pixels(self):
"""
Returns the total number of pixels in the selected from the video input plugin.
"""
raise NotImplementedError

def supports_video_quality(self):
"""
Returns True if the current video input plugin supports video quality else returns False.
"""
return False


class IOutput(IBackendPlugin):
#
Expand All @@ -432,6 +454,7 @@ class IOutput(IBackendPlugin):
type = None # Types: AUDIO, VIDEO, BOTH
extension = None
location = None
configurable = False

metadata_order = [
"title",
Expand Down Expand Up @@ -479,6 +502,20 @@ def generate_xml_metadata(self, metadata):

return ET.ElementTree(root)

def set_audio_quality(self, quality):
"""Implement this to set the audio quality of the plugin.
Input quality is either LOW, MEDIUM, or HIGH.
"""
pass

def set_video_bitrate(self, bitrate):
"""Implement this to set the bitrate of the plugin.
Only implement if the bitrate of the plugin can be specified.
"""
pass


class IImporter(IBackendPlugin):
CATEGORY = "Importer"
Expand Down
35 changes: 33 additions & 2 deletions src/freeseer/frontend/configtool/AVWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from PyQt4 import QtCore
from PyQt4 import QtGui

from freeseer.framework.multimedia import Quality
from freeseer.frontend.qtcommon.dpi_adapt_qtgui import QGroupBoxWithDpi
from freeseer.frontend.qtcommon.dpi_adapt_qtgui import QWidgetWithDpi

Expand Down Expand Up @@ -71,7 +72,7 @@ def __init__(self, parent=None):

self.audioGroupBox.setCheckable(True)
self.audioGroupBox.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
self.audioGroupBox.setFixedSize(BOX_WIDTH, BOX_HEIGHT)
self.audioGroupBox.setFixedSize(BOX_WIDTH, 1.5 * BOX_HEIGHT)
self.audioGroupBox.setStyleSheet(boxStyle)

self.audioMixerLabel = QtGui.QLabel("Audio Mixer")
Expand All @@ -87,6 +88,21 @@ def __init__(self, parent=None):
audioLayout.addWidget(self.audioMixerComboBox, 0, 1)
audioLayout.addWidget(self.audioMixerSetupPushButton, 0, 2)

self.audioQualityLabel = QtGui.QLabel("Audio Quality")
self.audioQualityLabel.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
self.audioQualityComboBox = QtGui.QComboBox()
self.audioQualityComboBox.addItems(Quality.qualities)
self.audioQualityLabel.setBuddy(self.audioQualityComboBox)
self.audioQualitySetupPushButton = QtGui.QToolButton()
self.audioQualitySetupPushButton.setText("Setup")
self.audioQualitySetupPushButton.setIcon(config_icon)
self.audioQualitySetupPushButton.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
self.audioQualitySetupPushButton.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
self.audioQualitySetupPushButton.setEnabled(False)
audioLayout.addWidget(self.audioQualityLabel, 1, 0)
audioLayout.addWidget(self.audioQualityComboBox, 1, 1)
audioLayout.addWidget(self.audioQualitySetupPushButton, 1, 2)

#
# Video Input
#
Expand All @@ -98,7 +114,7 @@ def __init__(self, parent=None):

self.videoGroupBox.setCheckable(True)
self.videoGroupBox.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
self.videoGroupBox.setFixedSize(BOX_WIDTH, BOX_HEIGHT)
self.videoGroupBox.setFixedSize(BOX_WIDTH, 1.5 * BOX_HEIGHT)
self.videoGroupBox.setStyleSheet(boxStyle)

self.videoMixerLabel = QtGui.QLabel("Video Mixer")
Expand All @@ -114,6 +130,21 @@ def __init__(self, parent=None):
videoLayout.addWidget(self.videoMixerComboBox, 0, 1)
videoLayout.addWidget(self.videoMixerSetupPushButton, 0, 2)

self.videoQualityLabel = QtGui.QLabel("Video Quality")
self.videoQualityLabel.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
self.videoQualityComboBox = QtGui.QComboBox()
self.videoQualityComboBox.addItems(Quality.qualities)
self.videoQualityLabel.setBuddy(self.videoQualityComboBox)
self.videoQualitySetupPushButton = QtGui.QToolButton()
self.videoQualitySetupPushButton.setText("Setup")
self.videoQualitySetupPushButton.setIcon(config_icon)
self.videoQualitySetupPushButton.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
self.videoQualitySetupPushButton.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
self.videoQualitySetupPushButton.setEnabled(False)
videoLayout.addWidget(self.videoQualityLabel, 1, 0)
videoLayout.addWidget(self.videoQualityComboBox, 1, 1)
videoLayout.addWidget(self.videoQualitySetupPushButton, 1, 2)

#
# Record to Stream
#
Expand Down
2 changes: 1 addition & 1 deletion src/freeseer/frontend/configtool/ConfigToolWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def __init__(self, parent=None):
'''
super(ConfigToolWidget, self).__init__(parent)

self.setMinimumSize(800, 400)
self.setMinimumSize(800, 460)
self.mainLayout = QtGui.QHBoxLayout()
self.setLayout(self.mainLayout)

Expand Down
Loading

0 comments on commit 872c68c

Please sign in to comment.