-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathProgram.cs
148 lines (123 loc) · 4.9 KB
/
Program.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
////////////////////////////////////////////////////////////////////////////
//
// FlashCap - Independent camera capture library.
// Copyright (c) Kouji Matsui (@kozy_kekyo, @[email protected])
//
// Licensed under Apache-v2: https://opensource.org/licenses/Apache-2.0
//
////////////////////////////////////////////////////////////////////////////
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
namespace FlashCap.OneShot;
public static class Program
{
private static async Task<int> TakeOneShotToFileAsync(
string fileName, CancellationToken ct)
{
///////////////////////////////////////////////////////////////
// Initialize and detection capture devices.
// Step 1: Enumerate capture devices:
var devices = new CaptureDevices();
var descriptor0 = devices.EnumerateDescriptors().
// You could filter by device type and characteristics.
//Where(d => d.DeviceType == DeviceTypes.DirectShow). // Only DirectShow device.
FirstOrDefault();
if (descriptor0 == null)
{
Console.WriteLine($"Could not detect any capture interfaces.");
return 0;
}
#if false
// Step 2-1: Request video characteristics strictly:
// Will raise exception when parameters are not accepted.
var characteristics = new VideoCharacteristics(
PixelFormats.JPEG, 1920, 1080, 60);
#else
// Step 2-2: Or, you could choice from device descriptor:
var characteristics0 = descriptor0.Characteristics.
//Where(c => c.PixelFormat == PixelFormats.JPEG). // Only MJPEG characteristics.
FirstOrDefault(c => c.PixelFormat != PixelFormats.Unknown);
if (characteristics0 == null)
{
Console.WriteLine($"Could not select primary characteristics.");
return 0;
}
#endif
Console.WriteLine($"Selected capture device: {descriptor0}, {characteristics0}");
///////////////////////////////////////////////////////////////
// Start capture and get one image.
#if true
// Step 3: New interface: Simple take one shot.
var image = await descriptor0.TakeOneShotAsync(
characteristics0, ct);
Console.WriteLine($"Captured {image.Length} bytes.");
#else
// Equivalent implementation
// Step 3-1: Open the capture device with specific characteristics:
var tcs = new TaskCompletionSource<byte[]>();
using var captureDevice = await descriptor0.OpenAsync(
characteristics0,
bufferScope =>
{
////////////////////////////////////////////////
// Pixel buffer has arrived.
// Step 3-2: Copy image data binary:
var image = bufferScope.Buffer.CopyImage();
Console.WriteLine($"Captured {image.Length} bytes.");
// Step 3-3: Relay to outside continuation.
tcs.TrySetResult(image);
// If you output to each files from continuous image data,
// it would be easier to output directly to file here.
// In that case, use:
// * `isScattering` argument to true.
// * `maxQueuingFrames` argument.
// * `bufferScope.ReleaseNow()` method.
// and be careful not to cause frame dropping.
},
ct);
// Step 4: Start capturing:
await captureDevice.StartAsync(ct);
Console.WriteLine($"Device opened.");
// Step 5: Waiting to continue:
var image = await tcs.Task;
// Step 6: Stop capturing:
await captureDevice.StopAsync(ct);
Console.WriteLine($"Device stopped.");
#endif
///////////////////////////////////////////////////////////////
// Save image data to file.
// Step 7: Construct storing file name:
var extension = characteristics0.PixelFormat switch
{
PixelFormats.JPEG => ".jpg",
PixelFormats.PNG => ".png", // (Very rare device, I dont know)
_ => ".bmp",
};
var path = $"{fileName}{extension}";
// Step 8: Write to the file:
using var fs = new FileStream(
path,
FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite,
65536, true);
await fs.WriteAsync(image, 0, image.Length, ct);
await fs.FlushAsync(ct);
Console.WriteLine($"The image wrote to file {path}.");
return 0;
}
public static async Task<int> Main(string[] args)
{
try
{
return await TakeOneShotToFileAsync("oneshot", default);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return Marshal.GetHRForException(ex);
}
}
}