diff --git a/starboard/shared/win32/media_transform.cc b/starboard/shared/win32/media_transform.cc index 499454d2c95e..4b8609ddecd5 100644 --- a/starboard/shared/win32/media_transform.cc +++ b/starboard/shared/win32/media_transform.cc @@ -50,6 +50,9 @@ MediaTransform::MediaTransform(CLSID clsid) if (FAILED(hr) || !transform_) { transform_ = nullptr; state_ = kDrained; + transform_create_error_message_ = + "Could not create decoder transform. " + + ::starboard::shared::win32::HResultToString(hr); } } @@ -309,6 +312,10 @@ HRESULT MediaTransform::SendMessage(MFT_MESSAGE_TYPE msg, return transform_->ProcessMessage(msg, data); } +std::string MediaTransform::GetTransformCreateError() const { + return transform_create_error_message_; +} + void MediaTransform::Reset() { if (stream_begun_) { SendMessage(MFT_MESSAGE_COMMAND_FLUSH); diff --git a/starboard/shared/win32/media_transform.h b/starboard/shared/win32/media_transform.h index ecc9abd81e47..d939998f51d1 100644 --- a/starboard/shared/win32/media_transform.h +++ b/starboard/shared/win32/media_transform.h @@ -20,6 +20,7 @@ #include #include +#include #include #include "starboard/media.h" @@ -84,6 +85,8 @@ class MediaTransform { HRESULT SendMessage(MFT_MESSAGE_TYPE msg, ULONG_PTR data = 0); + std::string GetTransformCreateError() const; + // Reset the media transform to its original state. void Reset(); @@ -106,6 +109,7 @@ class MediaTransform { bool stream_begun_; bool discontinuity_; bool throttle_inputs_; + std::string transform_create_error_message_; }; } // namespace win32 diff --git a/starboard/shared/win32/video_decoder.cc b/starboard/shared/win32/video_decoder.cc index ac7dc8133deb..151cb5ebf73c 100644 --- a/starboard/shared/win32/video_decoder.cc +++ b/starboard/shared/win32/video_decoder.cc @@ -101,11 +101,14 @@ std::unique_ptr CreateVideoTransform( const GUID& decoder_guid, const GUID& input_guid, const GUID& output_guid, - const IMFDXGIDeviceManager* device_manager) { + const IMFDXGIDeviceManager* device_manager, + std::string* error_message) { + SB_DCHECK(error_message); std::unique_ptr media_transform( new MediaTransform(decoder_guid)); if (!media_transform->HasValidTransform()) { // Decoder Transform setup failed + *error_message = media_transform->GetTransformCreateError(); return std::unique_ptr(); } media_transform->EnableInputThrottle(true); @@ -113,6 +116,7 @@ std::unique_ptr CreateVideoTransform( ComPtr attributes = media_transform->GetAttributes(); if (!attributes) { // Decoder Transform setup failed + *error_message = "Invalid MediaTransform attributes"; return std::unique_ptr(); } @@ -128,6 +132,8 @@ std::unique_ptr CreateVideoTransform( hr = attributes->SetUINT32(CODECAPI_AVDecVideoAcceleration_H264, FALSE); if (FAILED(hr)) { SB_LOG(WARNING) << "Unable to disable DXVA."; + *error_message = "Unable to disable DXVA. " + + ::starboard::shared::win32::HResultToString(hr); return std::unique_ptr(); } } else { @@ -143,11 +149,13 @@ std::unique_ptr CreateVideoTransform( // Tell the decoder to allocate resources for the maximum resolution in // order to minimize glitching on resolution changes. if (FAILED(attributes->SetUINT32(MF_MT_DECODER_USE_MAX_RESOLUTION, 1))) { + *error_message = "Cannot allocate resources for maximum resolution."; return std::unique_ptr(); } ComPtr input_type; if (FAILED(MFCreateMediaType(&input_type)) || !input_type) { + *error_message = "Invalid IMFMediaType."; return std::unique_ptr(); } CheckResult(input_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)); @@ -278,11 +286,13 @@ void VideoDecoder::Initialize(const DecoderStatusCB& decoder_status_cb, SB_DCHECK(error_cb); decoder_status_cb_ = decoder_status_cb; error_cb_ = error_cb; + std::string error_message; if (video_device_) { - InitializeCodec(); + InitializeCodec(&error_message); } if (!decoder_) { - error_cb_(kSbPlayerErrorDecode, "Cannot initialize codec."); + error_cb_(kSbPlayerErrorDecode, + "Cannot initialize codec. Error: " + error_message); } } @@ -425,43 +435,50 @@ SbDecodeTarget VideoDecoder::CreateDecodeTarget() { return decode_target; } -void VideoDecoder::InitializeCodec() { +void VideoDecoder::InitializeCodec(std::string* error_message) { + SB_DCHECK(error_message); std::unique_ptr media_transform; // If this is updated then media_is_video_supported.cc also needs to be // updated. switch (video_codec_) { case kSbMediaVideoCodecH264: { - media_transform = - CreateVideoTransform(CLSID_MSH264DecoderMFT, MFVideoFormat_H264, - MFVideoFormat_NV12, device_manager_.Get()); + media_transform = CreateVideoTransform( + CLSID_MSH264DecoderMFT, MFVideoFormat_H264, MFVideoFormat_NV12, + device_manager_.Get(), error_message); priming_output_count_ = 0; if (!media_transform) { SB_LOG(WARNING) << "H264 hardware decoder creation failed."; + *error_message = + "H264 hardware decoder creation failed. " + *error_message; return; } break; } case kSbMediaVideoCodecVp9: { if (IsHardwareVp9DecoderSupported()) { - media_transform = - CreateVideoTransform(CLSID_MSVPxDecoder, MFVideoFormat_VP90, - MFVideoFormat_NV12, device_manager_.Get()); + media_transform = CreateVideoTransform( + CLSID_MSVPxDecoder, MFVideoFormat_VP90, MFVideoFormat_NV12, + device_manager_.Get(), error_message); priming_output_count_ = kVp9PrimingFrameCount; } if (!media_transform) { SB_LOG(WARNING) << "VP9 hardware decoder creation failed."; + *error_message = + "VP9 hardware decoder creation failed. " + *error_message; return; } break; } case kSbMediaVideoCodecAv1: { - media_transform = - CreateVideoTransform(MFVideoFormat_AV1, MFVideoFormat_AV1, - MFVideoFormat_NV12, device_manager_.Get()); + media_transform = CreateVideoTransform( + MFVideoFormat_AV1, MFVideoFormat_AV1, MFVideoFormat_NV12, + device_manager_.Get(), error_message); priming_output_count_ = 0; if (!media_transform) { SB_LOG(WARNING) << "AV1 hardware decoder creation failed."; + *error_message = + "AV1 hardware decoder creation failed. " + *error_message; return; } break; diff --git a/starboard/shared/win32/video_decoder.h b/starboard/shared/win32/video_decoder.h index c54336253c01..90d0f70f0e8f 100644 --- a/starboard/shared/win32/video_decoder.h +++ b/starboard/shared/win32/video_decoder.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "starboard/common/mutex.h" #include "starboard/common/ref_counted.h" @@ -100,7 +101,7 @@ class VideoDecoder return true; } - void InitializeCodec(); + void InitializeCodec(std::string* error_message); void ShutdownCodec(); static void ReleaseDecodeTargets(void* context);