| // Copyright 2017 The Cobalt Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef STARBOARD_SHARED_WIN32_VIDEO_DECODER_H_ |
| #define STARBOARD_SHARED_WIN32_VIDEO_DECODER_H_ |
| |
| #include <D3d11_1.h> |
| #include <wrl/client.h> |
| |
| #include <atomic> |
| #include <list> |
| #include <memory> |
| |
| #include "starboard/common/mutex.h" |
| #include "starboard/common/ref_counted.h" |
| #include "starboard/common/scoped_ptr.h" |
| #include "starboard/configuration.h" |
| #include "starboard/decode_target.h" |
| #include "starboard/shared/starboard/media/media_util.h" |
| #include "starboard/shared/starboard/player/filter/video_decoder_internal.h" |
| #include "starboard/shared/starboard/thread_checker.h" |
| #include "starboard/shared/win32/decrypting_decoder.h" |
| #include "starboard/thread.h" |
| |
| namespace starboard { |
| namespace shared { |
| namespace win32 { |
| |
| class VideoDecoder |
| : public ::starboard::shared::starboard::player::filter::VideoDecoder { |
| public: |
| VideoDecoder(SbMediaVideoCodec video_codec, |
| SbPlayerOutputMode output_mode, |
| SbDecodeTargetGraphicsContextProvider* graphics_context_provider, |
| SbDrmSystem drm_system, |
| bool is_hdr_supported = false); |
| ~VideoDecoder() override; |
| |
| // Queries for support without creating the vp9 decoder. The function caches |
| // the result for the first call. Note that the first call to this function |
| // isn't thread safe and is supposed to be called on startup. |
| static bool IsHardwareVp9DecoderSupported(bool is_hdr_required = false); |
| |
| bool IsHdrSupported() const { return is_hdr_supported_; } |
| |
| // Implement VideoDecoder interface. |
| void Initialize(const DecoderStatusCB& decoder_status_cb, |
| const ErrorCB& error_cb) override; |
| size_t GetPrerollFrameCount() const override; |
| int64_t GetPrerollTimeout() const override { return kSbInt64Max; } |
| size_t GetMaxNumberOfCachedFrames() const override; |
| |
| void WriteInputBuffers(const InputBuffers& input_buffers) override; |
| void WriteEndOfStream() override; |
| void Reset() override; |
| SbDecodeTarget GetCurrentDecodeTarget() override; |
| |
| private: |
| typedef ::starboard::shared::starboard::media::VideoStreamInfo |
| VideoStreamInfo; |
| |
| template <typename T> |
| using ComPtr = Microsoft::WRL::ComPtr<T>; |
| |
| struct Event { |
| enum Type { |
| kWriteInputBuffer, |
| kWriteEndOfStream, |
| }; |
| Type type; |
| scoped_refptr<InputBuffer> input_buffer; |
| }; |
| |
| struct Output { |
| Output(int64_t time, |
| const RECT& video_area, |
| const ComPtr<IMFSample>& video_sample) |
| : time(time), video_area(video_area), video_sample(video_sample) {} |
| int64_t time; |
| RECT video_area; |
| ComPtr<IMFSample> video_sample; |
| }; |
| |
| // This function returns false if HDR video is played, but HDR support is |
| // lost. Otherwise it returns true. For inherited class it also updates HDMI |
| // color metadata and sets HDR mode for Angle, if the video stream is HDR |
| // stream. |
| virtual bool TryUpdateOutputForHdrVideo(const VideoStreamInfo& stream_info) { |
| return true; |
| } |
| |
| void InitializeCodec(); |
| void ShutdownCodec(); |
| static void ReleaseDecodeTargets(void* context); |
| |
| void UpdateVideoArea(const ComPtr<IMFMediaType>& media); |
| scoped_refptr<VideoFrame> CreateVideoFrame(const ComPtr<IMFSample>& sample); |
| void DeleteVideoFrame(VideoFrame* video_frame); |
| SbDecodeTarget CreateDecodeTarget(); |
| |
| void EnsureDecoderThreadRunning(); |
| void StopDecoderThread(); |
| void DecoderThreadRun(); |
| static void* DecoderThreadEntry(void* context); |
| |
| ::starboard::shared::starboard::ThreadChecker thread_checker_; |
| |
| // These variables will be initialized inside ctor or Initialize() and will |
| // not be changed during the life time of this class. |
| const SbMediaVideoCodec video_codec_; |
| DecoderStatusCB decoder_status_cb_; |
| ErrorCB error_cb_; |
| SbDecodeTargetGraphicsContextProvider* graphics_context_provider_; |
| SbDrmSystem const drm_system_; |
| |
| // These are platform-specific objects required to create and use a codec. |
| ComPtr<ID3D11Device> d3d_device_; |
| ComPtr<IMFDXGIDeviceManager> device_manager_; |
| ComPtr<ID3D11VideoDevice1> video_device_; |
| ComPtr<ID3D11VideoContext> video_context_; |
| ComPtr<ID3D11VideoProcessorEnumerator> video_enumerator_; |
| ComPtr<ID3D11VideoProcessor> video_processor_; |
| |
| scoped_ptr<DecryptingDecoder> decoder_; |
| RECT video_area_; |
| |
| SbThread decoder_thread_ = kSbThreadInvalid; |
| volatile bool decoder_thread_stop_requested_ = false; |
| bool decoder_thread_stopped_ = false; |
| Mutex thread_lock_; |
| std::list<std::unique_ptr<Event> > thread_events_; |
| |
| // This structure shadows the list of outstanding frames held by the host. |
| // When a new output is added to this structure, the host should be notified |
| // of a new VideoFrame. When the host deletes the VideoFrame, the delete |
| // callback is used to update this structure. The VideoDecoder may need to |
| // delete outputs without notifying the host. In such a situation, the host's |
| // VideoFrames will be invalid if they still require the IMFSample; it's |
| // possible that the VideoFrame was converted to a texture already, so it |
| // will continue to be valid since the IMFSample is no longer needed. |
| Mutex outputs_reset_lock_; |
| std::list<Output> thread_outputs_; |
| |
| // To workaround the startup hitch for VP9, exercise the decoder for a |
| // certain number of frames while prerolling the initial playback. |
| int priming_output_count_; |
| |
| SbDecodeTarget current_decode_target_ = kSbDecodeTargetInvalid; |
| std::list<SbDecodeTarget> prev_decode_targets_; |
| |
| bool is_hdr_supported_; |
| std::atomic_bool error_occured_ = {false}; |
| }; |
| |
| } // namespace win32 |
| } // namespace shared |
| } // namespace starboard |
| |
| #endif // STARBOARD_SHARED_WIN32_VIDEO_DECODER_H_ |