-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathctlTantaVideoPickerViaReader.cs
290 lines (261 loc) · 13.7 KB
/
ctlTantaVideoPickerViaReader.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using MediaFoundation;
using MediaFoundation.ReadWrite;
using MediaFoundation.Misc;
using MediaFoundation.Transform;
using MediaFoundation.Alt;
using OISCommon;
using TantaCommon;
/// +------------------------------------------------------------------------------------------------------------------------------+
/// ¦ TERMS OF USE: MIT License ¦
/// +------------------------------------------------------------------------------------------------------------------------------¦
/// ¦Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation ¦
/// ¦files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, ¦
/// ¦modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software¦
/// ¦is furnished to do so, subject to the following conditions: ¦
/// ¦ ¦
/// ¦The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.¦
/// ¦ ¦
/// ¦THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE ¦
/// ¦WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ¦
/// ¦COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ¦
/// ¦ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ¦
/// +------------------------------------------------------------------------------------------------------------------------------+
/// Notes
/// Some parts of this code may be derived from the samples which ships with the MF.Net dll. These are
/// in turn derived from the original Microsoft samples. These have been placed in the public domain
/// without copyright.
///
/// The MF.Net library itself is licensed under the GNU Library or Lesser General Public License version 2.0 (LGPLv2)
///
/// SUPER IMPORTANT NOTE: You MUST use the [MTAThread] to decorate your entry point method. If you use the default [STAThread]
/// you may get errors. See the Program.cs file for details.
/// The function of this control is to display the video devices on a system and their associated video formats. The user
/// can choose a specific supported format from a list. The selected format will be communicated back to the owner via an event.
/// /// This version uses a Source Reader to find the available video media types. There
/// is an alternative version which uses the Media Source (see the ctlTantaVideoPicker control).
namespace TantaCommon
{
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// A class to display the video devices on a system and their associated
/// video formats. Note that available formats vary widely between video
/// devices (and device drivers)
/// </summary>
/// <history>
/// 01 Nov 18 Cynic - Started
/// </history>
public partial class ctlTantaVideoPickerViaReader : ctlOISBase
{
// this is the delegate we use to pass back picked device information
public delegate void VideoDevicePickedEventHandler(object sender, TantaMFDevice videoDevice);
public VideoDevicePickedEventHandler VideoDevicePickedEvent = null;
// this is the delegate we use to pass back picked video format information
public delegate void VideoFormatPickedEventHandler(object sender, TantaMFVideoFormatContainer videoFormatCont);
public VideoFormatPickedEventHandler VideoFormatPickedEvent = null;
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Constructor
/// </summary>
/// <history>
/// 01 Nov 18 Cynic - Started
/// </history>
public ctlTantaVideoPickerViaReader()
{
InitializeComponent();
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Displays the video devices on the system. Expects the MF system to have
/// been started.
/// </summary>
/// <history>
/// 01 Nov 18 Cynic - Started
/// </history>
public void DisplayVideoCaptureDevices()
{
StringBuilder sb = new StringBuilder();
// Query MF for the devices, can also use MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID
// here to see the audio capture devices
List<TantaMFDevice> vcDevices = TantaWMFUtils.GetDevicesByCategory(MFAttributesClsid.MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, CLSID.MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
if (vcDevices == null) return;
foreach (TantaMFDevice mfDevice in vcDevices)
{
sb.Append("FriendlyName:" + mfDevice.FriendlyName);
sb.Append("\r\n");
sb.Append("Symbolic Name:" + mfDevice.SymbolicName);
sb.Append("\r\n");
sb.Append("\r\n");
}
// add all known devices
comboBoxCaptureDevices.DataSource = vcDevices;
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Gets the currently chosen device
/// </summary>
/// <history>
/// 01 Nov 18 Cynic - Started
/// </history>
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public TantaMFDevice CurrentDevice
{
get
{
return (TantaMFDevice)comboBoxCaptureDevices.SelectedItem;
}
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Handle a selected index changed on our video capture device combo box
/// </summary>
/// <history>
/// 01 Nov 18 Cynic - Started
/// </history>
private void comboBoxCaptureDevices_SelectedIndexChanged(object sender, EventArgs e)
{
// reset this
// display this
DisplayVideoFormatsForCurrentCaptureDevice();
// just send an event
if (VideoDevicePickedEvent != null) VideoDevicePickedEvent(this, CurrentDevice);
// just send a clearing event
if (VideoFormatPickedEvent != null) VideoFormatPickedEvent(this, null);
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Displays the video formats for the currently selected video device. This
/// is more complicated than it looks. We have to open the video source, convert
/// that to a Media Source and then interrogate the that source to find a list
/// of video formats.
/// </summary>
/// <history>
/// 01 Nov 18 Cynic - Started
/// </history>
private void DisplayVideoFormatsForCurrentCaptureDevice()
{
IMFSourceReaderAsync tmpSourceReader = null;
List<TantaMFVideoFormatContainer> formatList;
HResult hr;
try
{
// clear what we have now
listViewSupportedFormats.Clear();
// reset this
listViewSupportedFormats.ListViewItemSorter = null;
// get the currently selected device
TantaMFDevice currentDevice = (TantaMFDevice)comboBoxCaptureDevices.SelectedItem;
if (currentDevice == null) return;
// open up the media source
tmpSourceReader = TantaWMFUtils.CreateSourceReaderAsyncFromDevice(currentDevice, null);
if (tmpSourceReader == null)
{
throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice, CreateSourceReaderAsyncFromDevice did not return a media source. Cannot continue.");
}
// now get a list of all supported formats from the video device
hr = TantaMediaTypeInfo.GetSupportedVideoFormatsFromSourceReaderInFormatContainers(currentDevice, tmpSourceReader, 100, out formatList);
if (hr != HResult.S_OK)
{
throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice, GetSupportedVideoFormatsFromSourceReaderInFormatContainers failed. HR=" + hr.ToString());
}
if (formatList == null)
{
throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice, GetSupportedVideoFormatsFromSourceReaderInFormatContainers did not return a format list. Cannot continue.");
}
// now display the formats
foreach (TantaMFVideoFormatContainer videoFormat in formatList)
{
ListViewItem lvi = new ListViewItem(new[] { videoFormat.SubTypeAsString, videoFormat.FrameSizeAsString, videoFormat.FrameRateAsString, videoFormat.FrameRateMaxAsString, videoFormat.AllAttributes });
lvi.Tag = videoFormat;
listViewSupportedFormats.Items.Add(lvi);
}
listViewSupportedFormats.Columns.Add("Type", 70);
listViewSupportedFormats.Columns.Add("FrameSize WxH", 100);
listViewSupportedFormats.Columns.Add("FrameRate f/s", 100);
listViewSupportedFormats.Columns.Add("FrameRateMax f/s", 100);
listViewSupportedFormats.Columns.Add("All Attributes", 2500);
}
finally
{
if (tmpSourceReader != null)
{
// close and release
Marshal.ReleaseComObject(tmpSourceReader);
tmpSourceReader = null;
}
}
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Handles a selected index changed on a video format in the list view
/// </summary>
/// <history>
/// 01 Nov 18 Cynic - Started
/// </history>
private void listViewSupportedFormats_SelectedIndexChanged(object sender, EventArgs e)
{
// just send a clearing event
if (VideoFormatPickedEvent != null) VideoFormatPickedEvent(this, null);
if (CurrentDevice == null) return;
TantaMFVideoFormatContainer selectedVideoFormat = GetSelectedVideoFormatContainer();
if (selectedVideoFormat == null) return;
// just send the event
if (VideoFormatPickedEvent != null) VideoFormatPickedEvent(this, GetSelectedVideoFormatContainer());
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Gets the selected Video Format Container. Will return null.
/// </summary>
/// <returns>the selected video format container or null for fail</returns>
/// <history>
/// 01 Nov 18 Cynic - Started
/// </history>
private TantaMFVideoFormatContainer GetSelectedVideoFormatContainer()
{
if (listViewSupportedFormats.SelectedItems.Count == 0) return null;
ListViewItem lvi = listViewSupportedFormats.SelectedItems[0];
if (lvi == null) return null;
if (lvi.Tag == null) return null;
if ((lvi.Tag is TantaMFVideoFormatContainer) == false) return null;
return (lvi.Tag as TantaMFVideoFormatContainer);
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Handles a double click on a video format in the list view
/// </summary>
/// <history>
/// 01 Nov 18 Cynic - Started
/// </history>
private void listViewSupportedFormats_DoubleClick(object sender, EventArgs e)
{
LogMessage("listViewSupportedFormats_DoubleClick");
// send the event to report this
if (VideoFormatPickedEvent != null) VideoFormatPickedEvent(this, GetSelectedVideoFormatContainer());
}
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
/// <summary>
/// Handles a double click on the list view. We do the sorting here
/// </summary>
/// <history>
/// 01 Nov 18 Cynic - Started
/// </history>
private void listViewSupportedFormats_ColumnClick(object sender, ColumnClickEventArgs e)
{
// Set the ListViewItemSorter property to a new ListViewItemComparer
// object.
listViewSupportedFormats.ListViewItemSorter = new ListViewItemCompareAsText(e.Column);
// Call the sort method to manually sort.
listViewSupportedFormats.Sort();
}
}
}