mirror of
https://github.com/clementine-player/Clementine
synced 2025-02-07 15:48:51 +01:00
gstengine: Make output format configurable
Add an output format option in playback settings. The options are Detect, S16LE, and F32LE. Selecting Detect will use the existing behavior and detect the native format when the pipeline starts. The other options will set the format when the pipeline is built.
This commit is contained in:
parent
15fdad3d51
commit
2804a4d89f
@ -85,7 +85,11 @@ using std::unique_ptr;
|
||||
using std::vector;
|
||||
|
||||
const char* GstEngine::kSettingsGroup = "GstEngine";
|
||||
const char* GstEngine::kSettingFormat = "format";
|
||||
const char* GstEngine::kAutoSink = "autoaudiosink";
|
||||
const char* GstEngine::kOutFormatDetect = "";
|
||||
const char* GstEngine::kOutFormatS16LE = "S16LE";
|
||||
const char* GstEngine::kOutFormatF32LE = "F32LE";
|
||||
const char* GstEngine::kHypnotoadPipeline =
|
||||
"audiotestsrc wave=6 ! "
|
||||
"audioecho intensity=1 delay=50000000 ! "
|
||||
@ -239,6 +243,8 @@ void GstEngine::ReloadSettings() {
|
||||
|
||||
mono_playback_ = s.value("monoplayback", false).toBool();
|
||||
sample_rate_ = s.value("samplerate", kAutoSampleRate).toInt();
|
||||
format_ = s.value(GstEngine::kSettingFormat, GstEngine::kOutFormatDetect)
|
||||
.toString();
|
||||
}
|
||||
|
||||
qint64 GstEngine::position_nanosec() const {
|
||||
@ -819,6 +825,7 @@ shared_ptr<GstEnginePipeline> GstEngine::CreatePipeline() {
|
||||
ret->set_buffer_min_fill(buffer_min_fill_);
|
||||
ret->set_mono_playback(mono_playback_);
|
||||
ret->set_sample_rate(sample_rate_);
|
||||
ret->set_format(format_);
|
||||
|
||||
ret->AddBufferConsumer(this);
|
||||
for (BufferConsumer* consumer : buffer_consumers_) {
|
||||
|
@ -73,7 +73,11 @@ class GstEngine : public Engine::Base, public BufferConsumer {
|
||||
typedef QList<OutputDetails> OutputDetailsList;
|
||||
|
||||
static const int kAutoSampleRate = -1;
|
||||
static const char* kOutFormatDetect;
|
||||
static const char* kOutFormatS16LE;
|
||||
static const char* kOutFormatF32LE;
|
||||
static const char* kSettingsGroup;
|
||||
static const char* kSettingFormat;
|
||||
static const char* kAutoSink;
|
||||
|
||||
bool Init();
|
||||
@ -223,6 +227,7 @@ class GstEngine : public Engine::Base, public BufferConsumer {
|
||||
|
||||
bool mono_playback_;
|
||||
int sample_rate_;
|
||||
QString format_;
|
||||
|
||||
mutable bool can_decode_success_;
|
||||
mutable bool can_decode_last_;
|
||||
|
@ -464,6 +464,11 @@ bool GstEnginePipeline::InitAudioBin() {
|
||||
// Link the trunk to the tee via filter.
|
||||
gst_element_link_many(tee_src, capsfilter_, tee_, nullptr);
|
||||
|
||||
// If the user has selected a format, then set it now.
|
||||
if (format_ != GstEngine::kOutFormatDetect) {
|
||||
SetOutputFormat(format_);
|
||||
}
|
||||
|
||||
// Link the analyzer output of the tee
|
||||
gst_element_link(probe_queue, probe_converter);
|
||||
|
||||
@ -884,7 +889,9 @@ void GstEnginePipeline::NewPadCallback(GstElement*, GstPad* pad,
|
||||
qLog(Debug) << "Initial decoder caps:" << caps_str;
|
||||
g_free(caps_str);
|
||||
|
||||
if (instance->pipeline_is_initialised_) {
|
||||
if (instance->format_ != GstEngine::kOutFormatDetect) {
|
||||
// Caps were set when the pipeline was constructed.
|
||||
} else if (instance->pipeline_is_initialised_) {
|
||||
qLog(Debug)
|
||||
<< "Ignoring native format since pipeline is already running.";
|
||||
} else {
|
||||
@ -892,11 +899,10 @@ void GstEnginePipeline::NewPadCallback(GstElement*, GstPad* pad,
|
||||
|
||||
// The output branch only handles F32LE and S16LE. If the source is S16LE,
|
||||
// then use that throughout the pipeline. Otherwise, use F32LE.
|
||||
if (fmt != "S16LE") {
|
||||
GstCaps* new_caps = gst_caps_new_simple(
|
||||
"audio/x-raw", "format", G_TYPE_STRING, "F32LE", nullptr);
|
||||
g_object_set(instance->capsfilter_, "caps", new_caps, nullptr);
|
||||
gst_caps_unref(new_caps);
|
||||
if (fmt == GstEngine::kOutFormatS16LE) {
|
||||
instance->SetOutputFormat(GstEngine::kOutFormatS16LE);
|
||||
} else {
|
||||
instance->SetOutputFormat(GstEngine::kOutFormatF32LE);
|
||||
}
|
||||
}
|
||||
gst_caps_unref(caps);
|
||||
@ -1297,6 +1303,14 @@ void GstEnginePipeline::UpdateVolume() {
|
||||
g_object_set(G_OBJECT(volume_), "volume", vol, nullptr);
|
||||
}
|
||||
|
||||
void GstEnginePipeline::SetOutputFormat(const QString& format) {
|
||||
qLog(Debug) << "Setting format to" << format;
|
||||
GstCaps* new_caps = gst_caps_new_simple(
|
||||
"audio/x-raw", "format", G_TYPE_STRING, format.toUtf8().data(), nullptr);
|
||||
g_object_set(capsfilter_, "caps", new_caps, nullptr);
|
||||
gst_caps_unref(new_caps);
|
||||
}
|
||||
|
||||
void GstEnginePipeline::StartFader(qint64 duration_nanosec,
|
||||
QTimeLine::Direction direction,
|
||||
QTimeLine::CurveShape shape,
|
||||
|
@ -51,6 +51,7 @@ class GstEnginePipeline : public GstPipelineBase {
|
||||
void set_buffer_min_fill(int percent);
|
||||
void set_mono_playback(bool enabled);
|
||||
void set_sample_rate(int rate);
|
||||
void set_format(const QString& format) { format_ = format; }
|
||||
|
||||
// Creates the pipeline, returns false on error
|
||||
bool InitFromReq(const MediaPlaybackRequest& req, qint64 end_nanosec);
|
||||
@ -153,6 +154,7 @@ class GstEnginePipeline : public GstPipelineBase {
|
||||
void UpdateVolume();
|
||||
void UpdateEqualizer();
|
||||
void UpdateStereoBalance();
|
||||
void SetOutputFormat(const QString& format);
|
||||
bool ReplaceDecodeBin(GstElement* new_bin);
|
||||
bool ReplaceDecodeBin(const QUrl& url);
|
||||
|
||||
@ -215,6 +217,7 @@ class GstEnginePipeline : public GstPipelineBase {
|
||||
|
||||
bool mono_playback_;
|
||||
int sample_rate_;
|
||||
QString format_;
|
||||
|
||||
// The URL that is currently playing, and the URL that is to be preloaded
|
||||
// when the current track is close to finishing.
|
||||
|
@ -50,6 +50,10 @@ PlaybackSettingsPage::PlaybackSettingsPage(SettingsDialog* dialog)
|
||||
ui_->sample_rate->setItemData(2, 48000);
|
||||
ui_->sample_rate->setItemData(3, 96000);
|
||||
ui_->sample_rate->setItemData(4, 192000);
|
||||
|
||||
ui_->output_format->setItemData(0, GstEngine::kOutFormatDetect);
|
||||
ui_->output_format->setItemData(1, GstEngine::kOutFormatS16LE);
|
||||
ui_->output_format->setItemData(2, GstEngine::kOutFormatF32LE);
|
||||
}
|
||||
|
||||
PlaybackSettingsPage::~PlaybackSettingsPage() { delete ui_; }
|
||||
@ -116,6 +120,9 @@ void PlaybackSettingsPage::Load() {
|
||||
ui_->mono_playback->setChecked(s.value("monoplayback", false).toBool());
|
||||
ui_->sample_rate->setCurrentIndex(ui_->sample_rate->findData(
|
||||
s.value("samplerate", GstEngine::kAutoSampleRate).toInt()));
|
||||
ui_->output_format->setCurrentIndex(ui_->output_format->findData(
|
||||
s.value(GstEngine::kSettingFormat, GstEngine::kOutFormatDetect)
|
||||
.toString()));
|
||||
ui_->buffer_min_fill->setValue(s.value("bufferminfill", 33).toInt());
|
||||
s.endGroup();
|
||||
}
|
||||
@ -153,6 +160,9 @@ void PlaybackSettingsPage::Save() {
|
||||
s.setValue(
|
||||
"samplerate",
|
||||
ui_->sample_rate->itemData(ui_->sample_rate->currentIndex()).toInt());
|
||||
s.setValue(GstEngine::kSettingFormat,
|
||||
ui_->output_format->itemData(ui_->output_format->currentIndex())
|
||||
.toString());
|
||||
s.setValue("bufferminfill", ui_->buffer_min_fill->value());
|
||||
s.endGroup();
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>596</width>
|
||||
<height>667</height>
|
||||
<height>766</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -70,7 +70,16 @@
|
||||
<item>
|
||||
<widget class="QWidget" name="fading_options" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@ -193,7 +202,16 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
@ -336,16 +354,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="mono_playback">
|
||||
<property name="toolTip">
|
||||
<string>Changing mono playback preference will be effective for the next playing songs</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Mono playback</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="sample_rate_label">
|
||||
<property name="text">
|
||||
@ -354,7 +362,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<layout class="QHBoxLayout" name="sample_rate_layout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="sample_rate">
|
||||
<property name="sizePolicy">
|
||||
@ -417,6 +425,65 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="output_format_label">
|
||||
<property name="text">
|
||||
<string>Format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="mono_playback">
|
||||
<property name="toolTip">
|
||||
<string>Changing mono playback preference will be effective for the next playing songs</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Mono playback</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<layout class="QHBoxLayout" name="output_format_layout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="output_format">
|
||||
<property name="toolTip">
|
||||
<string>The format is only updated when a pipeline starts.</string>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Detect</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>S16LE (16-bit)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>F32LE (32-bit)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
Loading…
x
Reference in New Issue
Block a user