浏览代码

coreaudio-encoder: Add output sample rate setting/property

Palana 10 年之前
父节点
当前提交
eb5745a363
共有 2 个文件被更改,包括 95 次插入4 次删除
  1. 2 0
      plugins/coreaudio-encoder/data/locale/en-US.ini
  2. 93 4
      plugins/coreaudio-encoder/encoder.cpp

+ 2 - 0
plugins/coreaudio-encoder/data/locale/en-US.ini

@@ -1,3 +1,5 @@
 CoreAudioAAC="CoreAudio AAC encoder"
 CoreAudioAAC="CoreAudio AAC encoder"
 Bitrate="Bitrate"
 Bitrate="Bitrate"
 AllowHEAAC="Allow HE-AAC"
 AllowHEAAC="Allow HE-AAC"
+OutputSamplerate="Output Sample Rate"
+UseInputSampleRate="Use Input (OBS) Sample Rate (may list unsupported bitrates)"

+ 93 - 4
plugins/coreaudio-encoder/encoder.cpp

@@ -427,7 +427,8 @@ static bool bitrate_valid(DStr &log, ca_encoder *ca,
 static bool create_encoder(DStr &log, ca_encoder *ca,
 static bool create_encoder(DStr &log, ca_encoder *ca,
 		AudioStreamBasicDescription *in,
 		AudioStreamBasicDescription *in,
 		AudioStreamBasicDescription *out,
 		AudioStreamBasicDescription *out,
-		UInt32 format_id, UInt32 bitrate, UInt32 rate_control)
+		UInt32 format_id, UInt32 bitrate, UInt32 samplerate,
+		UInt32 rate_control)
 {
 {
 #define STATUS_CHECK(c) \
 #define STATUS_CHECK(c) \
 	code = c; \
 	code = c; \
@@ -437,8 +438,12 @@ static bool create_encoder(DStr &log, ca_encoder *ca,
 		return false; \
 		return false; \
 	}
 	}
 
 
+	Float64 srate = samplerate ?
+		(Float64)samplerate :
+		(Float64)ca->samples_per_second;
+
 	auto out_ = asbd_builder()
 	auto out_ = asbd_builder()
-		.sample_rate((Float64)ca->samples_per_second)
+		.sample_rate(srate)
 		.channels_per_frame((UInt32)ca->channels)
 		.channels_per_frame((UInt32)ca->channels)
 		.format_id(format_id)
 		.format_id(format_id)
 		.asbd;
 		.asbd;
@@ -550,6 +555,9 @@ static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder)
 		ca->allowed_formats = &aac_lc_formats;
 		ca->allowed_formats = &aac_lc_formats;
 	}
 	}
 
 
+	auto samplerate =
+		static_cast<UInt32>(obs_data_get_int(settings, "samplerate"));
+
 	DStr log;
 	DStr log;
 
 
 	bool encoder_created = false;
 	bool encoder_created = false;
@@ -559,7 +567,7 @@ static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder)
 				(uint32_t)format_id);
 				(uint32_t)format_id);
 
 
 		if (!create_encoder(log, ca.get(), &in, &out, format_id,
 		if (!create_encoder(log, ca.get(), &in, &out, format_id,
-					bitrate, rate_control))
+					bitrate, samplerate, rate_control))
 			continue;
 			continue;
 
 
 		encoder_created = true;
 		encoder_created = true;
@@ -1031,6 +1039,7 @@ static UInt32 find_matching_bitrate(UInt32 bitrate)
 
 
 static void aac_defaults(obs_data_t *settings)
 static void aac_defaults(obs_data_t *settings)
 {
 {
+	obs_data_set_default_int(settings, "samplerate", 0); //match input
 	obs_data_set_default_int(settings, "bitrate",
 	obs_data_set_default_int(settings, "bitrate",
 			find_matching_bitrate(128));
 			find_matching_bitrate(128));
 	obs_data_set_default_bool(settings, "allow he-aac", true);
 	obs_data_set_default_bool(settings, "allow he-aac", true);
@@ -1123,6 +1132,81 @@ static bool enumerate_bitrates(DStr &log, ca_encoder *ca,
 }
 }
 #endif
 #endif
 
 
+static vector<UInt32> get_samplerates(DStr &log, ca_encoder *ca)
+{
+	vector<UInt32> samplerates;
+
+	auto handle_samplerate = [&](UInt32 rate)
+	{
+		if (find(begin(samplerates), end(samplerates), rate) ==
+				end(samplerates)) {
+			log_to_dstr(log, ca, "Adding sample rate %u\n",
+					static_cast<uint32_t>(rate));
+			samplerates.push_back(rate);
+		} else {
+			log_to_dstr(log, ca, "Sample rate %u already added\n",
+					static_cast<uint32_t>(rate));
+		}
+	};
+
+	auto helper = [&](const AudioValueRange &range)
+	{
+		auto min_ = static_cast<UInt32>(range.mMinimum);
+		auto max_ = static_cast<UInt32>(range.mMaximum);
+
+		handle_samplerate(min_);
+
+		if (min_ == max_)
+			return;
+
+		log_to_dstr(log, ca, "Got actual sample rate range: %u<->%u\n",
+				static_cast<uint32_t>(min_),
+				static_cast<uint32_t>(max_));
+
+		handle_samplerate(max_);
+	};
+
+	for (UInt32 format : (ca ? *ca->allowed_formats : aac_formats)) {
+		log_to_dstr(log, ca, "Trying %s (0x%x)\n",
+				format_id_to_str(format),
+				static_cast<uint32_t>(format));
+
+		auto asbd = asbd_builder()
+			.format_id(format)
+			.asbd;
+
+		enumerate_samplerates(log, ca, asbd, helper);
+	}
+
+	return samplerates;
+}
+
+static void add_samplerates(obs_property_t *prop, ca_encoder *ca)
+{
+	obs_property_list_add_int(prop,
+			obs_module_text("UseInputSampleRate"), 0);
+
+	DStr log;
+
+	auto samplerates = get_samplerates(log, ca);
+
+	if (!samplerates.size()) {
+		CA_CO_DLOG_(LOG_ERROR, "Couldn't find available sample rates");
+		return;
+	}
+
+	if (log->len)
+		CA_CO_DLOG_(LOG_DEBUG, "Sample rate enumeration log");
+
+	sort(begin(samplerates), end(samplerates));
+
+	DStr buffer;
+	for (UInt32 samplerate : samplerates) {
+		dstr_printf(buffer, "%d", static_cast<uint32_t>(samplerate));
+		obs_property_list_add_int(prop, buffer->array, samplerate);
+	}
+}
+
 static vector<UInt32> get_bitrates(DStr &log, ca_encoder *ca,
 static vector<UInt32> get_bitrates(DStr &log, ca_encoder *ca,
 		Float64 samplerate)
 		Float64 samplerate)
 {
 {
@@ -1205,7 +1289,12 @@ static obs_properties_t *aac_properties(void *data)
 
 
 	obs_properties_t *props = obs_properties_create();
 	obs_properties_t *props = obs_properties_create();
 
 
-	obs_property_t *p = obs_properties_add_list(props, "bitrate",
+	obs_property_t *p = obs_properties_add_list(props, "samplerate",
+			obs_module_text("OutputSamplerate"),
+			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
+	add_samplerates(p, ca);
+
+	p = obs_properties_add_list(props, "bitrate",
 			obs_module_text("Bitrate"),
 			obs_module_text("Bitrate"),
 			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
 			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
 	add_bitrates(p, ca);
 	add_bitrates(p, ca);