forked from eden-emu/eden
		
	hwopus: Implement OpenHardwareOpusDecoderForMultiStreamEx and DecodeInterleavedForMultiStream
Allows MLB The Show 22 to boot. Fixes https://github.com/yuzu-emu/yuzu/issues/7911.
This commit is contained in:
		
							parent
							
								
									e392005f94
								
							
						
					
					
						commit
						a0a93f966d
					
				
					 2 changed files with 51 additions and 3 deletions
				
			
		|  | @ -174,7 +174,7 @@ public: | ||||||
|             {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleavedWithPerfAndResetOld"}, |             {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleavedWithPerfAndResetOld"}, | ||||||
|             {7, nullptr, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"}, |             {7, nullptr, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"}, | ||||||
|             {8, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"}, |             {8, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"}, | ||||||
|             {9, nullptr, "DecodeInterleavedForMultiStream"}, |             {9, &IHardwareOpusDecoderManager::DecodeInterleavedForMultiStream, "DecodeInterleavedForMultiStream"}, | ||||||
|         }; |         }; | ||||||
|         // clang-format on
 |         // clang-format on
 | ||||||
| 
 | 
 | ||||||
|  | @ -206,6 +206,16 @@ private: | ||||||
|         decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior); |         decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     void DecodeInterleavedForMultiStream(HLERequestContext& ctx) { | ||||||
|  |         LOG_DEBUG(Audio, "called"); | ||||||
|  | 
 | ||||||
|  |         IPC::RequestParser rp{ctx}; | ||||||
|  |         const auto extra_behavior = rp.Pop<bool>() ? OpusDecoderState::ExtraBehavior::ResetContext | ||||||
|  |                                                    : OpusDecoderState::ExtraBehavior::None; | ||||||
|  | 
 | ||||||
|  |         decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     OpusDecoderState decoder_state; |     OpusDecoderState decoder_state; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -354,6 +364,40 @@ void HwOpus::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) { | ||||||
|         system, OpusDecoderState{std::move(decoder), sample_rate, channel_count}); |         system, OpusDecoderState{std::move(decoder), sample_rate, channel_count}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void HwOpus::OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx) { | ||||||
|  |     OpusMultiStreamParametersEx params; | ||||||
|  |     std::memcpy(¶ms, ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); | ||||||
|  | 
 | ||||||
|  |     const auto& sample_rate = params.sample_rate; | ||||||
|  |     const auto& channel_count = params.channel_count; | ||||||
|  | 
 | ||||||
|  |     LOG_INFO( | ||||||
|  |         Audio, | ||||||
|  |         "called with sample_rate={}, channel_count={}, number_streams={}, number_stereo_streams={}", | ||||||
|  |         sample_rate, channel_count, params.number_streams, params.number_stereo_streams); | ||||||
|  | 
 | ||||||
|  |     ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 || | ||||||
|  |                    sample_rate == 12000 || sample_rate == 8000, | ||||||
|  |                "Invalid sample rate"); | ||||||
|  | 
 | ||||||
|  |     int error = 0; | ||||||
|  |     OpusDecoderPtr decoder{opus_multistream_decoder_create( | ||||||
|  |         sample_rate, static_cast<int>(channel_count), params.number_streams, | ||||||
|  |         params.number_stereo_streams, params.channel_mappings.data(), &error)}; | ||||||
|  |     if (error != OPUS_OK || decoder == nullptr) { | ||||||
|  |         LOG_ERROR(Audio, "Failed to create Opus decoder (error={}).", error); | ||||||
|  |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |         // TODO(ogniK): Use correct error code
 | ||||||
|  |         rb.Push(ResultUnknown); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  |     rb.PushIpcInterface<IHardwareOpusDecoderManager>( | ||||||
|  |         system, OpusDecoderState{std::move(decoder), sample_rate, channel_count}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { | HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         {0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"}, |         {0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"}, | ||||||
|  | @ -362,7 +406,8 @@ HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { | ||||||
|         {3, nullptr, "GetWorkBufferSizeForMultiStream"}, |         {3, nullptr, "GetWorkBufferSizeForMultiStream"}, | ||||||
|         {4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"}, |         {4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"}, | ||||||
|         {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"}, |         {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"}, | ||||||
|         {6, nullptr, "OpenHardwareOpusDecoderForMultiStreamEx"}, |         {6, &HwOpus::OpenHardwareOpusDecoderForMultiStreamEx, | ||||||
|  |          "OpenHardwareOpusDecoderForMultiStreamEx"}, | ||||||
|         {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"}, |         {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"}, | ||||||
|         {8, nullptr, "GetWorkBufferSizeExEx"}, |         {8, nullptr, "GetWorkBufferSizeExEx"}, | ||||||
|         {9, nullptr, "GetWorkBufferSizeForMultiStreamExEx"}, |         {9, nullptr, "GetWorkBufferSizeForMultiStreamExEx"}, | ||||||
|  |  | ||||||
|  | @ -18,8 +18,10 @@ struct OpusMultiStreamParametersEx { | ||||||
|     u32 number_stereo_streams; |     u32 number_stereo_streams; | ||||||
|     u32 use_large_frame_size; |     u32 use_large_frame_size; | ||||||
|     u32 padding; |     u32 padding; | ||||||
|     std::array<u32, 64> channel_mappings; |     std::array<u8, 0x100> channel_mappings; | ||||||
| }; | }; | ||||||
|  | static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118, | ||||||
|  |               "OpusMultiStreamParametersEx has incorrect size"); | ||||||
| 
 | 
 | ||||||
| class HwOpus final : public ServiceFramework<HwOpus> { | class HwOpus final : public ServiceFramework<HwOpus> { | ||||||
| public: | public: | ||||||
|  | @ -29,6 +31,7 @@ public: | ||||||
| private: | private: | ||||||
|     void OpenHardwareOpusDecoder(HLERequestContext& ctx); |     void OpenHardwareOpusDecoder(HLERequestContext& ctx); | ||||||
|     void OpenHardwareOpusDecoderEx(HLERequestContext& ctx); |     void OpenHardwareOpusDecoderEx(HLERequestContext& ctx); | ||||||
|  |     void OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx); | ||||||
|     void GetWorkBufferSize(HLERequestContext& ctx); |     void GetWorkBufferSize(HLERequestContext& ctx); | ||||||
|     void GetWorkBufferSizeEx(HLERequestContext& ctx); |     void GetWorkBufferSizeEx(HLERequestContext& ctx); | ||||||
|     void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx); |     void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 FearlessTobi
						FearlessTobi