ソースを参照

obs-ffmpeg: Query and log the AMF codec level

Log the codec level being used by AMF-based encoders after
ffmpeg_opts have been parsed. Users could have manually changed the
codec level so query the level via AMF then determine the string for
logging.
Alex Luccisano 6 ヶ月 前
コミット
d31271834f
1 ファイル変更70 行追加3 行削除
  1. 70 3
      plugins/obs-ffmpeg/texture-amf.cpp

+ 70 - 3
plugins/obs-ffmpeg/texture-amf.cpp

@@ -1419,6 +1419,37 @@ static void amf_set_codec_level(amf_base *enc)
 	}
 }
 
+static bool amf_get_level_str(amf_base *enc, amf_int64 level, char const **level_str)
+{
+	bool found = false;
+	std::vector<codec_level_entry> *levels;
+
+	if (enc->codec == amf_codec_type::AVC) {
+		levels = &avc_levels;
+	} else if (enc->codec == amf_codec_type::HEVC) {
+		levels = &hevc_levels;
+	} else if (enc->codec == amf_codec_type::AV1) {
+		levels = &av1_levels;
+	} else {
+		blog(LOG_ERROR, "%s: Unknown amf_codec_type", __FUNCTION__);
+		return false;
+	}
+
+	for (auto level_it = levels->begin(); level_it != levels->end(); ++level_it) {
+		if (level == level_it->amf_level) {
+			found = true;
+			*level_str = level_it->level_str;
+			break;
+		}
+	}
+
+	if (!found) {
+		*level_str = "unknown";
+	}
+
+	return found;
+}
+
 static bool amf_avc_init(void *data, obs_data_t *settings)
 {
 	amf_base *enc = (amf_base *)data;
@@ -1488,6 +1519,17 @@ static bool amf_avc_init(void *data, obs_data_t *settings)
 	if (!ffmpeg_opts || !*ffmpeg_opts)
 		ffmpeg_opts = "(none)";
 
+	/* The ffmpeg_opts just above may have explicitly set the AVC level to a value different than what was
+	 * determined by amf_set_codec_level(). Query the final AVC level then lookup the matching string. Warn if not
+	 * found, because ffmpeg_opts is free-form and may have set something bogus.
+	 */
+	amf_int64 final_level;
+	get_avc_property(enc, PROFILE_LEVEL, &final_level);
+	const char *level_str = nullptr;
+	if (!amf_get_level_str(enc, final_level, &level_str)) {
+		warn("AVC level string not found. Level %d may be incorrect.", final_level);
+	}
+
 	info("settings:\n"
 	     "\trate_control: %s\n"
 	     "\tbitrate:      %d\n"
@@ -1495,11 +1537,12 @@ static bool amf_avc_init(void *data, obs_data_t *settings)
 	     "\tkeyint:       %d\n"
 	     "\tpreset:       %s\n"
 	     "\tprofile:      %s\n"
+	     "\tlevel:        %s\n"
 	     "\tb-frames:     %d\n"
 	     "\twidth:        %d\n"
 	     "\theight:       %d\n"
 	     "\tparams:       %s",
-	     rc_str, bitrate, qp, gop_size, preset, profile, bf, enc->cx, enc->cy, ffmpeg_opts);
+	     rc_str, bitrate, qp, gop_size, preset, profile, level_str, bf, enc->cx, enc->cy, ffmpeg_opts);
 
 	return true;
 }
@@ -1788,6 +1831,17 @@ static bool amf_hevc_init(void *data, obs_data_t *settings)
 	if (!ffmpeg_opts || !*ffmpeg_opts)
 		ffmpeg_opts = "(none)";
 
+	/* The ffmpeg_opts just above may have explicitly set the HEVC level to a value different than what was
+	 * determined by amf_set_codec_level(). Query the final HEVC level then lookup the matching string. Warn if not
+	 * found, because ffmpeg_opts is free-form and may have set something bogus.
+	 */
+	amf_int64 final_level;
+	get_hevc_property(enc, PROFILE_LEVEL, &final_level);
+	char const *level_str = nullptr;
+	if (!amf_get_level_str(enc, final_level, &level_str)) {
+		warn("HEVC level string not found. Level %d may be incorrect.", final_level);
+	}
+
 	info("settings:\n"
 	     "\trate_control: %s\n"
 	     "\tbitrate:      %d\n"
@@ -1795,10 +1849,11 @@ static bool amf_hevc_init(void *data, obs_data_t *settings)
 	     "\tkeyint:       %d\n"
 	     "\tpreset:       %s\n"
 	     "\tprofile:      %s\n"
+	     "\tlevel:        %s\n"
 	     "\twidth:        %d\n"
 	     "\theight:       %d\n"
 	     "\tparams:       %s",
-	     rc_str, bitrate, qp, gop_size, preset, profile, enc->cx, enc->cy, ffmpeg_opts);
+	     rc_str, bitrate, qp, gop_size, preset, profile, level_str, enc->cx, enc->cy, ffmpeg_opts);
 
 	return true;
 }
@@ -2142,6 +2197,17 @@ static bool amf_av1_init(void *data, obs_data_t *settings)
 	if (!ffmpeg_opts || !*ffmpeg_opts)
 		ffmpeg_opts = "(none)";
 
+	/* The ffmpeg_opts just above may have explicitly set the AV1 level to a value different than what was
+	 * determined by amf_set_codec_level(). Query the final AV1 level then lookup the matching string. Warn if not
+	 * found, because ffmpeg_opts is free-form and may have set something bogus.
+	 */
+	amf_int64 final_level;
+	get_av1_property(enc, LEVEL, &final_level);
+	char const *level_str = nullptr;
+	if (!amf_get_level_str(enc, final_level, &level_str)) {
+		warn("AV1 level string not found. Level %d may be incorrect.", final_level);
+	}
+
 	info("settings:\n"
 	     "\trate_control: %s\n"
 	     "\tbitrate:      %d\n"
@@ -2149,11 +2215,12 @@ static bool amf_av1_init(void *data, obs_data_t *settings)
 	     "\tkeyint:       %d\n"
 	     "\tpreset:       %s\n"
 	     "\tprofile:      %s\n"
+	     "\tlevel:        %s\n"
 	     "\tb-frames:     %d\n"
 	     "\twidth:        %d\n"
 	     "\theight:       %d\n"
 	     "\tparams:       %s",
-	     rc_str, bitrate, qp, gop_size, preset, profile, bf, enc->cx, enc->cy, ffmpeg_opts);
+	     rc_str, bitrate, qp, gop_size, preset, profile, level_str, bf, enc->cx, enc->cy, ffmpeg_opts);
 
 	return true;
 }