1 /* GStreamer 2 * Copyright (C) 2020 Seungha Yang <seungha@centricular.com> 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public 15 * License along with this library; if not, write to the 16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20 #ifndef __GST_MEDIA_CAPTURE_WRAPPER_H__ 21 #define __GST_MEDIA_CAPTURE_WRAPPER_H__ 22 23 #include <gst/gst.h> 24 #include <wrl.h> 25 #include <wrl/wrappers/corewrappers.h> 26 #include <windows.media.capture.h> 27 #include <vector> 28 #include <memory> 29 #include <string> 30 #include <functional> 31 #include <mutex> 32 #include <condition_variable> 33 34 using namespace Microsoft::WRL; 35 using namespace Microsoft::WRL::Wrappers; 36 37 using namespace ABI::Windows::Foundation; 38 using namespace ABI::Windows::UI::Core; 39 using namespace ABI::Windows::Media::Capture; 40 using namespace ABI::Windows::Media::Capture::Frames; 41 using namespace ABI::Windows::Graphics::Imaging; 42 43 /* Store Format info and its caps representation */ 44 class GstWinRTMediaDescription 45 { 46 public: 47 GstWinRTMediaDescription(); 48 GstWinRTMediaDescription(const GstWinRTMediaDescription& other); 49 ~GstWinRTMediaDescription(); 50 void Release(); 51 bool IsValid() const; 52 HRESULT Fill(HString &source_id, 53 const ComPtr<IMediaCaptureVideoProfileMediaDescription>& desc, 54 unsigned int info_index, 55 unsigned int desc_index); 56 57 GstWinRTMediaDescription& operator=(const GstWinRTMediaDescription& rhs) 58 { 59 if (this == &rhs) 60 return *this; 61 62 Release(); 63 if (rhs.source_id_.IsValid()) 64 rhs.source_id_.CopyTo(source_id_.GetAddressOf()); 65 if (rhs.subtype_.IsValid()) 66 rhs.subtype_.CopyTo(subtype_.GetAddressOf()); 67 gst_caps_replace (&caps_, rhs.caps_); 68 69 return *this; 70 } 71 72 public: 73 HString source_id_; 74 /* TODO: need to cover audio too */ 75 HString subtype_; 76 /* Source ID which is mapped to MediaFormatSource */ 77 GstCaps *caps_; 78 }; 79 80 /* holds GstWinRTMediaFrameSourceInfo, corresponding to per device info */ 81 class GstWinRTMediaFrameSourceGroup 82 { 83 public: 84 GstWinRTMediaFrameSourceGroup(); 85 GstWinRTMediaFrameSourceGroup(const GstWinRTMediaFrameSourceGroup& other); 86 ~GstWinRTMediaFrameSourceGroup(); 87 void Release(); 88 bool Contain(const GstWinRTMediaDescription &desc); 89 HRESULT Fill(const ComPtr<IMediaFrameSourceGroup> &source_group, 90 unsigned int index); 91 92 GstWinRTMediaFrameSourceGroup& operator=(const GstWinRTMediaFrameSourceGroup& rhs) 93 { 94 if (this == &rhs) 95 return *this; 96 97 Release(); 98 id_ = rhs.id_; 99 display_name_ = rhs.display_name_; 100 source_group_ = rhs.source_group_; 101 source_list_ = rhs.source_list_; 102 103 return *this; 104 } 105 106 public: 107 std::string id_; 108 std::string display_name_; 109 ComPtr<IMediaFrameSourceGroup> source_group_; 110 std::vector<GstWinRTMediaDescription> source_list_; 111 }; 112 113 typedef struct 114 { 115 HRESULT (*frame_arrived) (IMediaFrameReference * frame, 116 void * user_data); 117 HRESULT (*failed) (const std::string &error, 118 UINT32 error_code, 119 void * user_data); 120 } MediaCaptureWrapperCallbacks; 121 class MediaCaptureWrapper 122 { 123 public: 124 MediaCaptureWrapper(gpointer dispatcher); 125 ~MediaCaptureWrapper(); 126 127 void RegisterCb(const MediaCaptureWrapperCallbacks &cb, 128 void * user_data); 129 130 /* Enumerating available source devices */ 131 /* Fill enumerated device infos into list */ 132 HRESULT EnumrateFrameSourceGroup(std::vector<GstWinRTMediaFrameSourceGroup> &group_list); 133 /* Select target device which should be one of enumerated be fore */ 134 HRESULT SetSourceGroup(const GstWinRTMediaFrameSourceGroup &group); 135 /* Select target format (resolution, video format) to use */ 136 HRESULT SetMediaDescription(const GstWinRTMediaDescription &desc); 137 138 /* Start and Stop capturing operation */ 139 HRESULT StartCapture(); 140 HRESULT StopCapture(); 141 HRESULT GetAvailableDescriptions(std::vector<GstWinRTMediaDescription> &desc_list); 142 143 private: 144 ComPtr<IMediaCapture> media_capture_; 145 ComPtr<IMediaFrameReader> frame_reader_; 146 ComPtr<ICoreDispatcher> dispatcher_; 147 bool init_done_; 148 std::mutex lock_; 149 std::condition_variable cond_; 150 151 EventRegistrationToken token_frame_arrived_; 152 EventRegistrationToken token_capture_failed_; 153 154 std::unique_ptr<GstWinRTMediaFrameSourceGroup> source_group_; 155 std::unique_ptr<GstWinRTMediaDescription> media_desc_; 156 MediaCaptureWrapperCallbacks user_cb_; 157 void *user_data_; 158 159 private: 160 HRESULT openMediaCapture(); 161 HRESULT mediaCaptureInitPre(); 162 HRESULT mediaCaptureInitPost(ComPtr<IAsyncAction> init_async, 163 ComPtr<IMediaCapture> media_capture); 164 HRESULT startCapture(); 165 HRESULT stopCapture(); 166 HRESULT onFrameArrived(IMediaFrameReader *reader, 167 IMediaFrameArrivedEventArgs *args); 168 HRESULT onCaptureFailed(IMediaCapture *capture, 169 IMediaCaptureFailedEventArgs *args); 170 static HRESULT enumrateFrameSourceGroup(std::vector<GstWinRTMediaFrameSourceGroup> &list); 171 }; 172 173 HRESULT 174 FindCoreDispatcherForCurrentThread(ICoreDispatcher ** dispatcher); 175 176 bool 177 WinRTCapsCompareFunc(const GstWinRTMediaDescription & a, 178 const GstWinRTMediaDescription & b); 179 180 #endif /* __GST_MEDIA_CAPTURE_WRAPPER_H__ */