FallbackFormat

FallbackFormat

#Overview

name: FallbackFormat

The value of this variable can be defined or overridden in .ini config files. 1 .ini config file referencing this setting variable.

It is referenced in 9 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of FallbackFormat is to provide a backup or alternative format when the primary or requested format is not available or supported. This variable is used in different contexts within the Unreal Engine, primarily in audio processing and frame number handling.

FallbackFormat is utilized by the following Unreal Engine subsystems and modules:

  1. OpenXR Plugin: In the swapchain creation process for handling unsupported formats.
  2. Audio System: For determining the audio format to use when the preferred format is unavailable.
  3. Time Management: In frame number display and parsing.

The value of this variable is typically set in configuration files or during initialization of the respective systems. For example, in the Audio system, it’s read from the configuration file using the “FallbackFormat” key in the “Audio” section.

FallbackFormat often interacts with other variables such as PlatformFormat, PlatformStreamingFormat, and AllWaveFormats in the audio system, and DisplayRateAttr, TickResolutionAttr, and DisplayFormatAttr in the time management system.

Developers should be aware that:

  1. FallbackFormat is crucial for ensuring system stability when preferred formats are unavailable.
  2. Its value should be carefully chosen to maintain compatibility and performance.
  3. In some cases, using the fallback format may result in reduced quality or performance compared to the primary format.

Best practices when using this variable include:

  1. Always ensure that the fallback format is supported by the target platform.
  2. Log warnings when falling back to this format to aid in debugging and optimization.
  3. Consider the implications of using the fallback format on performance and quality.
  4. Regularly review and update the fallback format choices as new format support becomes available in engine updates.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseEngine.ini:1567, section: [Audio]

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Plugins/Runtime/OpenXR/Source/OpenXRHMD/Private/OpenXRHMD_Swapchain.cpp:141

Scope (from outer to inner):

file
function     uint8 FOpenXRSwapchain::GetNearestSupportedSwapchainFormat

Source code excerpt:


	// Search for a fallback format in order of preference (first element in the array has the highest preference).
	uint8 FallbackFormat = 0;
	uint32 FallbackPlatformFormat = 0;
	for (int64_t Format : Formats) //-V1078
	{
		if (RequestedFormat == PF_DepthStencil)
		{
			if (Format == ToPlatformFormat(PF_D24))
			{
				FallbackFormat = PF_D24;
				FallbackPlatformFormat = Format;
				break;
			}
		}
		else
		{
			if (Format == ToPlatformFormat(PF_B8G8R8A8))
			{
				FallbackFormat = PF_B8G8R8A8;
				FallbackPlatformFormat = Format;
				break;
			}
			else if (Format == ToPlatformFormat(PF_R8G8B8A8))
			{
				FallbackFormat = PF_R8G8B8A8;
				FallbackPlatformFormat = Format;
				break;
			}
		}
	}

	if (!FallbackFormat)
	{
		UE_LOG(LogHMD, Warning, TEXT("No compatible swapchain format found!"));
		return PF_Unknown;
	}

	UE_LOG(LogHMD, Warning, TEXT("Swapchain format not supported (%d), falling back to runtime preferred format (%d)."), PlatformFormat, FallbackPlatformFormat);
	return FallbackFormat;
}

XrSwapchain FOpenXRSwapchain::CreateSwapchain(XrSession InSession, uint32 PlatformFormat, uint32 SizeX, uint32 SizeY, uint32 ArraySize, uint32 NumMips, uint32 NumSamples, ETextureCreateFlags CreateFlags, void* Next /*= nullptr*/)
{
	XrSwapchainUsageFlags Usage = 0;
	if (!(CreateFlags & TexCreate_SRGB))

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Sound/AudioFormatSettings.h:20

Scope (from outer to inner):

file
namespace    Audio
class        class FAudioFormatSettings
function     FName GetFallbackFormat

Source code excerpt:

		ENGINE_API void GetWaveFormatModuleHints(TArray<FName>& OutHints) const;

		FName GetFallbackFormat() const { return FallbackFormat; }

	private:
		ENGINE_API void ReadConfiguration(FConfigCacheIni*, const FString& InConfigFilename, const FString& InPlatformIdentifierForLogging);

		TArray<FName> AllWaveFormats;
		TArray<FName> WaveFormatModuleHints;
		FName PlatformFormat;
		FName PlatformStreamingFormat;
		FName FallbackFormat;
	};
}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/AudioFormatSettings.cpp:69

Scope (from outer to inner):

file
namespace    Audio
function     FName FAudioFormatSettings::GetWaveFormat

Source code excerpt:

			else
			{
				FormatName = FallbackFormat;
			}
		}
		FormatName = GetCloudStreamingFormatOverride(FormatName, Wave);
		return FormatName;
	}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/AudioFormatSettings.cpp:120

Scope (from outer to inner):

file
namespace    Audio
function     void FAudioFormatSettings::ReadConfiguration

Source code excerpt:

		}

		// FallbackFormat
		{
			FString FallbackFormatString;
			if (InConfigSystem->GetString(TEXT("Audio"), TEXT("FallbackFormat"), FallbackFormatString, InConfigFilename))
			{
				FallbackFormat = *FallbackFormatString;
			}
			else
			{
				FallbackFormat = NAME_ADPCM;
				UE_LOG(LogAudio, Warning, TEXT("Audio:FallbackFormat is not defined, defaulting to '%s'."), *FallbackFormat.GetPlainNameString());
			}
			if (!AllWaveFormats.Contains(FallbackFormat) && AllWaveFormats.Num() > 0)
			{
				UE_LOG(LogAudio, Warning, TEXT("FallbackFormat '%s' not defined in 'AllWaveFormats'. Using first format listed '%s'"), *FallbackFormatString, *AllWaveFormats[0].ToString());
				FallbackFormat = AllWaveFormats[0];
			}
		}

		// PlatformFormat
		{
			FString PlatformFormatString;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/AudioFormatSettings.cpp:153

Scope (from outer to inner):

file
namespace    Audio
function     void FAudioFormatSettings::ReadConfiguration

Source code excerpt:

			if (!AllWaveFormats.Contains(PlatformFormat))
			{
				UE_LOG(LogAudio, Warning, TEXT("PlatformFormat '%s' not defined in 'AllWaveFormats'. Using fallback format '%s'"), *PlatformFormatString, *FallbackFormat.ToString());
				PlatformFormat = FallbackFormat;
			}
		}

		// PlatformStreamingFormat
		{
			FString PlatformStreamingFormatString;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/AudioFormatSettings.cpp:172

Scope (from outer to inner):

file
namespace    Audio
function     void FAudioFormatSettings::ReadConfiguration

Source code excerpt:

			if (!AllWaveFormats.Contains(PlatformStreamingFormat))
			{
				UE_LOG(LogAudio, Warning, TEXT("PlatformStreamingFormat '%s' not defined in 'AllWaveFormats'. Using fallback format '%s'"), *PlatformStreamingFormatString, *FallbackFormat.ToString());
				PlatformStreamingFormat = FallbackFormat;
			}
		}

		UE_LOG(LogAudio, Verbose, TEXT("AudioFormatSettings: TargetName='%s', AllWaveFormats=(%s), Hints=(%s), PlatformFormat='%s', PlatformStreamingFormat='%s', FallbackFormat='%s'"),
			*InPlatformIdentifierForLogging, *MakePrettyArrayToString(AllWaveFormats), *MakePrettyArrayToString(WaveFormatModuleHints), *PlatformFormat.ToString(), *PlatformStreamingFormat.ToString(), *FallbackFormat.ToString());	
	}

}// namespace Audio

#Loc: <Workspace>/Engine/Source/Runtime/TimeManagement/Public/FrameNumberNumericInterface.h:125

Scope (from outer to inner):

file
function     virtual TOptional<double> FromString

Source code excerpt:

		FFrameRate SourceFrameRate = DisplayRateAttr.Get();
		FFrameRate DestinationFrameRate = TickResolutionAttr.Get();
		EFrameNumberDisplayFormats FallbackFormat = DisplayFormatAttr.Get();

		// We allow input in any format (time, frames or timecode) and we just convert it into into the internal sequence resolution.
		// The user's input can be ambiguous though (does "5" mean 5 frames or 5 seconds?) so when we check each possible result we
		// also check to see if they explicitly specified that format, or if the evaluator just happens to be able to parse that.

		// All of these will convert into the frame resolution from the user's input before returning.

#Loc: <Workspace>/Engine/Source/Runtime/TimeManagement/Public/FrameNumberNumericInterface.h:148

Scope (from outer to inner):

file
function     virtual TOptional<double> FromString

Source code excerpt:

			// They've entered an ambiguous number, so we'll check the display format and see if we did successfully parse as that type. If it
			// was able to parse the input for the given display format, we return that.
			if (TimecodeResult.IsValid() && (FallbackFormat == EFrameNumberDisplayFormats::DropFrameTimecode || FallbackFormat == EFrameNumberDisplayFormats::NonDropFrameTimecode))
			{
				return TOptional<double>(TimecodeResult.GetValue().GetFrame().Value);
			}
			else if (TimeResult.IsValid() && FallbackFormat == EFrameNumberDisplayFormats::Seconds)
			{
				return TOptional<double>(TimeResult.GetValue().GetFrame().Value);
			}
			else if (FrameResult.IsValid() && FallbackFormat == EFrameNumberDisplayFormats::Frames)
			{
				return TOptional<double>(FrameResult.GetValue().GetFrame().Value);
			}

			static FBasicMathExpressionEvaluator Parser;

			// If not parsed, try the math expression evaluator
			if (FallbackFormat == EFrameNumberDisplayFormats::Seconds)
			{
				double TimeInSeconds = DestinationFrameRate.AsSeconds(FFrameTime::FromDecimal(InExistingValue));

				TValueOrError<double, FExpressionError> Result = Parser.Evaluate(*InString, TimeInSeconds);
				if (Result.IsValid())
				{

#Loc: <Workspace>/Engine/Source/Runtime/TimeManagement/Public/FrameNumberNumericInterface.h:176

Scope (from outer to inner):

file
function     virtual TOptional<double> FromString

Source code excerpt:

				}
			}
			else if (FallbackFormat == EFrameNumberDisplayFormats::Frames)
			{
				FFrameTime ExistingTime = FFrameRate::TransformTime(FFrameTime::FromDecimal(InExistingValue), DestinationFrameRate, SourceFrameRate);

				TValueOrError<double, FExpressionError> Result = Parser.Evaluate(*InString, (double)(ExistingTime.GetFrame().Value));
				if (Result.IsValid())
				{