mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
37e1847464
A large refactoring commit for adding features and improve performance * Reuse internal converter and overlay compositor: Converter can be reused as long as input and display formats are not changed. Also overlay compositor reconstruction is required only if display format is changed * Don't wait for full GPU flush on resize or close: D3D12 swapchain requires GPU idle in order to resize backbuffer. Thus CPU side waiting is required for swapchain related commands to be finished. However, don't need to wait for full GPU flushing. * Support multiple sink on a single external window Keep installed subclass window procedure even if there's no associated our internal HWND. This will make window procedure hooking less racy. Then parent HWND's message will be transferred to our internal HWNDs if needed. * Adding support for window handle update Application can change target HWND even when videosink is playing or paused state. So, users can call gst_video_overlay_set_window_handle() against d3d12videosink anytime. The videosink will be able to update internal state and setup resource upon requested. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7013>
151 lines
4.2 KiB
C++
151 lines
4.2 KiB
C++
/* GStreamer
|
|
* Copyright (C) 2024 Seungha Yang <seungha@centricular.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "gstd3d12window.h"
|
|
#include "gstd3d12window-swapchain.h"
|
|
#include <atomic>
|
|
#include <mutex>
|
|
#include <condition_variable>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
#include <memory>
|
|
#include <d3d11on12.h>
|
|
#include <d2d1_3.h>
|
|
#include <wrl.h>
|
|
|
|
struct FullscreenState
|
|
{
|
|
std::atomic<bool> fullscreen_on_alt_enter = { false };
|
|
std::atomic<bool> requested_fullscreen = { false };
|
|
std::atomic<bool> applied_fullscreen = { false };
|
|
LONG restore_style = 0;
|
|
WINDOWPLACEMENT restore_placement = { };
|
|
};
|
|
|
|
class SwapChainProxy
|
|
{
|
|
public:
|
|
SwapChainProxy (GstD3D12Window * window, SIZE_T id);
|
|
~SwapChainProxy ();
|
|
|
|
void set_window_handles (HWND parent_hwnd, HWND child_hwnd);
|
|
HWND get_window_handle ();
|
|
SIZE_T get_id ();
|
|
bool has_parent ();
|
|
void on_destroy ();
|
|
void set_fullscreen_on_alt_enter (bool enable);
|
|
void toggle_fullscreen (bool enable);
|
|
void update_render_rect ();
|
|
void handle_fullscreen_change (bool is_fullscreen);
|
|
void handle_syskey_down ();
|
|
void handle_update_render_rect ();
|
|
void handle_key_event (UINT msg, WPARAM wparam, LPARAM lparam);
|
|
void handle_mouse_event (UINT msg, WPARAM wparam, LPARAM lparam);
|
|
void handle_swapchain_created ();
|
|
GstFlowReturn setup_swapchain (GstD3D12Device * device, DXGI_FORMAT format,
|
|
const GstVideoInfo * in_info, const GstVideoInfo * out_info,
|
|
GstStructure * conv_config);
|
|
GstFlowReturn resize_buffer ();
|
|
GstFlowReturn set_buffer (GstBuffer * buffer);
|
|
GstFlowReturn present ();
|
|
|
|
private:
|
|
std::shared_ptr<SwapChain> get_swapchain ();
|
|
|
|
private:
|
|
GstD3D12Window *window_ = nullptr;
|
|
SIZE_T id_ = 0;
|
|
HWND hwnd_ = nullptr;
|
|
HWND parent_hwnd_ = nullptr;
|
|
GThread *window_thread_ = nullptr;
|
|
FullscreenState fstate_;
|
|
std::shared_ptr<SwapChain> swapchain_;
|
|
|
|
std::recursive_mutex lock_;
|
|
};
|
|
|
|
class HwndServer
|
|
{
|
|
public:
|
|
HwndServer(const HwndServer &) = delete;
|
|
HwndServer& operator=(const HwndServer &) = delete;
|
|
static HwndServer * get_instance()
|
|
{
|
|
static HwndServer *inst = nullptr;
|
|
GST_D3D12_CALL_ONCE_BEGIN {
|
|
inst = new HwndServer ();
|
|
} GST_D3D12_CALL_ONCE_END;
|
|
|
|
return inst;
|
|
}
|
|
|
|
void register_window (GstD3D12Window * window);
|
|
void unregister_window (GstD3D12Window * window);
|
|
|
|
void unlock_window (GstD3D12Window * window);
|
|
void unlock_stop_window (GstD3D12Window * window);
|
|
|
|
GstFlowReturn create_child_hwnd (GstD3D12Window * window,
|
|
HWND parent_hwnd, SIZE_T & proxy_id);
|
|
|
|
void create_child_hwnd_finish (GstD3D12Window * window,
|
|
HWND parent_hwnd, SIZE_T proxy_id);
|
|
|
|
SIZE_T create_internal_window (GstD3D12Window * window);
|
|
|
|
void release_proxy (GstD3D12Window * window, SIZE_T proxy_id);
|
|
|
|
void forward_parent_message (HWND parent,
|
|
UINT msg, WPARAM wparam, LPARAM lparam);
|
|
|
|
void on_parent_destroy (HWND parent_hwnd);
|
|
void on_proxy_destroy (GstD3D12Window * window,
|
|
SIZE_T proxy_id);
|
|
|
|
std::shared_ptr<SwapChainProxy> get_proxy (GstD3D12Window * window,
|
|
SIZE_T proxy_id);
|
|
|
|
private:
|
|
enum CreateState
|
|
{
|
|
None,
|
|
Waiting,
|
|
Opened,
|
|
Closed,
|
|
};
|
|
|
|
struct State
|
|
{
|
|
std::mutex create_lock;
|
|
std::condition_variable create_cond;
|
|
std::atomic<SIZE_T> id = { 0 };
|
|
bool flushing = false;
|
|
CreateState create_state = CreateState::None;
|
|
std::shared_ptr<SwapChainProxy> proxy;
|
|
};
|
|
|
|
HwndServer () {}
|
|
~HwndServer () {}
|
|
std::recursive_mutex lock_;
|
|
std::unordered_map<GstD3D12Window *, std::shared_ptr<State>> state_;
|
|
std::unordered_map<HWND, std::vector<HWND>> parent_hwnd_map_;
|
|
};
|
|
|