瀏覽代碼

coreaudio-encoder: Update default bitrate matching/logging

Palana 10 年之前
父節點
當前提交
6ad48ddb20
共有 1 個文件被更改,包括 77 次插入44 次删除
  1. 77 44
      plugins/coreaudio-encoder/encoder.cpp

+ 77 - 44
plugins/coreaudio-encoder/encoder.cpp

@@ -3,8 +3,10 @@
 #include <obs-module.h>
 
 #include <algorithm>
+#include <cstdlib>
 #include <initializer_list>
 #include <memory>
+#include <mutex>
 #include <vector>
 
 #ifndef _WIN32
@@ -1027,64 +1029,95 @@ static AudioConverterRef he_aac_default_converter(void)
 	return get_default_converter(kAudioFormatMPEG4AAC_HE);
 }
 
-struct find_matching_bitrate_helper {
-	UInt32 bitrate;
-	UInt32 best_match;
-	int diff;
-};
-typedef struct find_matching_bitrate_helper find_matching_bitrate_helper;
-
-static void find_matching_bitrate_func(void *data, UInt32 min, UInt32 max)
+static bool find_best_match(DStr &log, ca_encoder *ca, UInt32 bitrate,
+		UInt32 &best_match)
 {
-	find_matching_bitrate_helper *helper =
-		static_cast<find_matching_bitrate_helper*>(data);
+	UInt32 actual_bitrate = bitrate * 1000;
+	bool found_match = false;
 
-	int min_diff = abs((int)helper->bitrate - (int)min);
-	int max_diff = abs((int)helper->bitrate - (int)max);
+	auto handle_bitrate = [&](UInt32 candidate)
+	{
+		if (abs(static_cast<intmax_t>(actual_bitrate - candidate)) <
+		    abs(static_cast<intmax_t>(actual_bitrate - best_match))) {
+			log_to_dstr(log, ca, "Found new best match %u\n",
+					static_cast<uint32_t>(candidate));
 
-	if (min_diff < helper->diff) {
-		helper->best_match = min;
-		helper->diff = min_diff;
-	}
+			found_match = true;
+			best_match = candidate;
+		}
+	};
+
+	auto helper = [&](UInt32 min_, UInt32 max_)
+	{
+		handle_bitrate(min_);
+
+		if (min_ == max_)
+			return;
+
+		log_to_dstr(log, ca, "Got actual bit rate range: %u<->%u\n",
+				static_cast<uint32_t>(min_),
+				static_cast<uint32_t>(max_));
 
-	if (max_diff < helper->diff) {
-		helper->best_match = max;
-		helper->diff = max_diff;
+		handle_bitrate(max_);
+	};
+
+	for (UInt32 format_id : aac_formats) {
+		log_to_dstr(log, ca, "Trying %s (0x%x)\n",
+				format_id_to_str(format_id), format_id);
+
+		auto out = get_default_out_asbd_builder()
+			.format_id(format_id)
+			.asbd;
+
+		auto converter = get_converter(log, ca, out);
+
+		if (converter)
+			enumerate_bitrates(log, ca, converter.get(),
+					helper);
+		else
+			log_to_dstr(log, ca, "Could not get converter\n");
 	}
+
+	best_match /= 1000;
+
+	return found_match;
 }
 
 static UInt32 find_matching_bitrate(UInt32 bitrate)
 {
-	find_matching_bitrate_helper helper;
-	helper.bitrate = bitrate * 1000;
-	helper.best_match = 0;
-	helper.diff = INT_MAX;
+	static UInt32 match = bitrate;
 
-	AudioConverterRef converter = aac_default_converter();
-	if (!converter) {
-		CA_LOG(LOG_ERROR, "Could not get converter to match "
-				"default bitrate");
-		return bitrate;
-	}
+	static once_flag once;
 
-	bool has_bitrates = enumerate_bitrates(NULL, converter,
-			find_matching_bitrate_func, &helper);
-	AudioConverterDispose(converter);
+	call_once(once, [&]()
+	{
+		DStr log;
+		ca_encoder *ca = nullptr;
 
-	if (!has_bitrates) {
-		CA_LOG(LOG_ERROR, "No bitrates found while matching "
-				"default bitrate");
-		AudioConverterDispose(converter);
-		return bitrate;
-	}
+		if (!find_best_match(log, ca, bitrate, match)) {
+			CA_CO_DLOG(LOG_ERROR, "No matching bitrates found for "
+				"target bitrate %u",
+				static_cast<uint32_t>(bitrate));
+
+			match = bitrate;
+			return;
+		}
 
-	if (helper.best_match != helper.bitrate)
-		CA_LOG(LOG_INFO, "Returning closest matching bitrate %u "
-				"instead of requested bitrate %u",
-				(uint32_t)helper.best_match / 1000,
-				(uint32_t)bitrate);
+		if (match != bitrate) {
+			CA_CO_DLOG(LOG_INFO, "Default bitrate (%u) isn't "
+				"supported, returning %u as closest match",
+				static_cast<uint32_t>(bitrate),
+				static_cast<uint32_t>(match));
+			return;
+		}
+
+		if (log->len)
+			CA_CO_DLOG(LOG_DEBUG, "Default bitrate matching log "
+					"for bitrate %u",
+					static_cast<uint32_t>(bitrate));
+	});
 
-	return helper.best_match / 1000;
+	return match;
 }
 
 static void aac_defaults(obs_data_t *settings)