1 // Header for standard system include files.
2 
3 // Copyright (c) Microsoft. All rights reserved.
4 //
5 // The MIT License (MIT)
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files(the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions :
13 //
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 // THE SOFTWARE.
24 
25 #pragma once
26 
27 #include <collection.h>
28 #include <ppltasks.h>
29 
30 #include <wrl\implements.h>
31 #include <wrl\wrappers\corewrappers.h>
32 #include <Roerrorapi.h>
33 
34 #include <queue>
35 #include <sstream>
36 
37 #include <robuffer.h>
38 
39 #include <mfapi.h>
40 #include <mfidl.h>
41 #include <Mferror.h>
42 
43 #include <windows.media.h>
44 #include <windows.media.mediaproperties.h>
45 
46 namespace AWM = ::ABI::Windows::Media;
47 namespace AWMMp = ::ABI::Windows::Media::MediaProperties;
48 namespace AWFC = ::ABI::Windows::Foundation::Collections;
49 namespace MW = ::Microsoft::WRL;
50 namespace MWD = ::Microsoft::WRL::Details;
51 namespace MWW = ::Microsoft::WRL::Wrappers;
52 namespace WMC = ::Windows::Media::Capture;
53 namespace WF = ::Windows::Foundation;
54 namespace WMMp = ::Windows::Media::MediaProperties;
55 namespace WSS = ::Windows::Storage::Streams;
56 
57 // Exception-based error handling
58 #define CHK(statement)  {HRESULT _hr = (statement); if (FAILED(_hr)) { throw ref new Platform::COMException(_hr); };}
59 #define CHKNULL(p)  {if ((p) == nullptr) { throw ref new Platform::NullReferenceException(L#p); };}
60 
61 // Exception-free error handling
62 #define CHK_RETURN(statement) {hr = (statement); if (FAILED(hr)) { return hr; };}
63 
64 // Cast a C++/CX msartpointer to an ABI smartpointer
65 template<typename T, typename U>
66 MW::ComPtr<T> As(U^ in)
67 {
68     MW::ComPtr<T> out;
69     CHK(reinterpret_cast<IInspectable*>(in)->QueryInterface(IID_PPV_ARGS(&out)));
70     return out;
71 }
72 
73 // Cast an ABI smartpointer
74 template<typename T, typename U>
As(const Microsoft::WRL::ComPtr<U> & in)75 Microsoft::WRL::ComPtr<T> As(const Microsoft::WRL::ComPtr<U>& in)
76 {
77     Microsoft::WRL::ComPtr<T> out;
78     CHK(in.As(&out));
79     return out;
80 }
81 
82 // Cast an ABI smartpointer
83 template<typename T, typename U>
As(U * in)84 Microsoft::WRL::ComPtr<T> As(U* in)
85 {
86     Microsoft::WRL::ComPtr<T> out;
87     CHK(in->QueryInterface(IID_PPV_ARGS(&out)));
88     return out;
89 }
90 
91 // Get access to bytes in IBuffer
92 inline unsigned char* GetData(_In_ WSS::IBuffer^ buffer)
93 {
94     unsigned char* bytes = nullptr;
95     CHK(As<WSS::IBufferByteAccess>(buffer)->Buffer(&bytes));
96     return bytes;
97 }
98 
99 // Class to start and shutdown Media Foundation
100 class AutoMF
101 {
102 public:
AutoMF()103     AutoMF()
104         : _bInitialized(false)
105     {
106         CHK(MFStartup(MF_VERSION));
107     }
108 
~AutoMF()109     ~AutoMF()
110     {
111         if (_bInitialized)
112         {
113             (void)MFShutdown();
114         }
115     }
116 
117 private:
118     bool _bInitialized;
119 };
120 
121 // Class to track error origin
122 template <size_t N>
OriginateError(__in HRESULT hr,__in wchar_t const (& str)[N])123 HRESULT OriginateError(__in HRESULT hr, __in wchar_t const (&str)[N])
124 {
125     if (FAILED(hr))
126     {
127         ::RoOriginateErrorW(hr, N - 1, str);
128     }
129     return hr;
130 }
131 
132 // Class to track error origin
OriginateError(__in HRESULT hr)133 inline HRESULT OriginateError(__in HRESULT hr)
134 {
135     if (FAILED(hr))
136     {
137         ::RoOriginateErrorW(hr, 0, nullptr);
138     }
139     return hr;
140 }
141 
142 // Converts exceptions into HRESULTs
143 template <typename Lambda>
ExceptionBoundary(Lambda && lambda)144 HRESULT ExceptionBoundary(Lambda&& lambda)
145 {
146     try
147     {
148         lambda();
149         return S_OK;
150     }
151     catch (Platform::Exception^ e)
152     {
153         return e->HResult;
154     }
155     catch (const std::bad_alloc&)
156     {
157         return E_OUTOFMEMORY;
158     }
159     catch (const std::exception&)
160     {
161         return E_FAIL;
162     }
163 }
164 
165 // Wraps an IMFSample in a C++/CX class to be able to define a callback delegate
166 ref class MediaSample sealed
167 {
168 internal:
169     MW::ComPtr<IMFSample> Sample;
170 };
171 
172 delegate void MediaSampleHandler(MediaSample^ sample);