forked from andrewkirillov/AForge.NET
-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathVideoFileSource.h
285 lines (261 loc) · 8.56 KB
/
VideoFileSource.h
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
// AForge FFMPEG Library
// AForge.NET framework
// http://www.aforgenet.com/framework/
//
// Copyright © AForge.NET, 2009-2011
// contacts@aforgenet.com
//
#pragma once
using namespace System;
using namespace System::Drawing;
using namespace System::Drawing::Imaging;
using namespace System::Threading;
using namespace AForge::Video;
namespace AForge { namespace Video { namespace FFMPEG
{
/// <summary>
/// Video source for video files.
/// </summary>
///
/// <remarks><para>The video source provides access to video files using <a href="http://www.ffmpeg.org/">FFmpeg</a> library.</para>
///
/// <para><note>The class provides video only. Sound is not supported.</note></para>
///
/// <para><note>The class ignores presentation time of video frames while retrieving them from
/// video file. Instead it provides video frames according to the FPS rate of the video file
/// or the configured <see cref="FrameInterval"/>.</note></para>
///
/// <para><note>Make sure you have <b>FFmpeg</b> binaries (DLLs) in the output folder of your application in order
/// to use this class successfully. <b>FFmpeg</b> binaries can be found in Externals folder provided with AForge.NET
/// framework's distribution.</note></para>
///
/// <para>Sample usage:</para>
/// <code>
/// // create video source
/// VideoFileSource videoSource = new VideoFileSource( fileName );
/// // set NewFrame event handler
/// videoSource.NewFrame += new NewFrameEventHandler( video_NewFrame );
/// // start the video source
/// videoSource.Start( );
/// // ...
///
/// // New frame event handler, which is invoked on each new available video frame
/// private void video_NewFrame( object sender, NewFrameEventArgs eventArgs )
/// {
/// // get new frame
/// Bitmap bitmap = eventArgs.Frame;
/// // process the frame
/// }
/// </code>
/// </remarks>
///
public ref class VideoFileSource : IVideoSource
{
public:
/// <summary>
/// New frame event.
/// </summary>
///
/// <remarks><para>Notifies clients about new available frame from video source.</para>
///
/// <para><note>Since video source may have multiple clients, each client is responsible for
/// making a copy (cloning) of the passed video frame, because the video source disposes its
/// own original copy after notifying of clients.</note></para>
/// </remarks>
///
virtual event NewFrameEventHandler^ NewFrame;
/// <summary>
/// Video source error event.
/// </summary>
///
/// <remarks>This event is used to notify clients about any type of errors occurred in
/// video source object, for example internal exceptions.</remarks>
///
virtual event VideoSourceErrorEventHandler^ VideoSourceError;
/// <summary>
/// Video playing finished event.
/// </summary>
///
/// <remarks><para>This event is used to notify clients that the video playing has finished.</para>
/// </remarks>
///
virtual event PlayingFinishedEventHandler^ PlayingFinished;
/// <summary>
/// Video source.
/// </summary>
///
/// <remarks><para>Video file name to play.</para></remarks>
///
property String^ Source
{
virtual String^ get( )
{
return m_fileName;
}
void set( String^ fileName )
{
m_fileName = fileName;
}
}
/// <summary>
/// Received frames count.
/// </summary>
///
/// <remarks>Number of frames the video source provided from the moment of the last
/// access to the property.
/// </remarks>
///
property int FramesReceived
{
virtual int get( )
{
int frames = m_framesReceived;
m_framesReceived = 0;
return frames;
}
}
/// <summary>
/// Received bytes count.
/// </summary>
///
/// <remarks>Number of bytes the video source provided from the moment of the last
/// access to the property.
/// </remarks>
///
property long long BytesReceived
{
virtual long long get( )
{
return 0;
}
}
/// <summary>
/// State of the video source.
/// </summary>
///
/// <remarks>Current state of video source object - running or not.</remarks>
///
property bool IsRunning
{
virtual bool get( )
{
if ( m_workerThread != nullptr )
{
// check if the thread is still running
if ( m_workerThread->Join( 0 ) == false )
return true;
Free( );
}
return false;
}
}
/// <summary>
/// Frame interval.
/// </summary>
///
/// <remarks><para>The property sets the interval in milliseconds between frames. If the property is
/// set to 100, then the desired frame rate will be 10 frames per second.</para>
///
/// <para><note>Setting this property to 0 leads to no delay between video frames - frames
/// are read as fast as possible.</note></para>
///
/// <para><note>Setting this property has effect only when <see cref="FrameIntervalFromSource"/>
/// is set to <see langword="false"/>.</note></para>
///
/// <para>Default value is set to <b>0</b>.</para>
/// </remarks>
///
property int FrameInterval
{
int get( )
{
return m_frameInterval;
}
void set( int frameInterval )
{
m_frameInterval = frameInterval;
}
}
/// <summary>
/// Get frame interval from source or use manually specified.
/// </summary>
///
/// <remarks><para>The property specifies which frame rate to use for video playing.
/// If the property is set to <see langword="true"/>, then video is played
/// with original frame rate, which is set in source video file. If the property is
/// set to <see langword="false"/>, then custom frame rate is used, which is
/// calculated based on the manually specified <see cref="FrameInterval">frame interval</see>.</para>
///
/// <para>Default value is set to <see langword="true"/>.</para>
/// </remarks>
///
property bool FrameIntervalFromSource
{
bool get( )
{
return m_frameIntervalFromSource;
}
void set( bool fpsFromSource )
{
m_frameIntervalFromSource = fpsFromSource;
}
}
public:
/// <summary>
/// Initializes a new instance of the <see cref="VideoFileSource"/> class.
/// </summary>
///
VideoFileSource( String^ fileName );
/// <summary>
/// Start video source.
/// </summary>
///
/// <remarks>Starts video source and return execution to caller. Video source
/// object creates background thread and notifies about new frames with the
/// help of <see cref="NewFrame"/> event.</remarks>
///
/// <exception cref="ArgumentException">Video source is not specified.</exception>
///
virtual void Start( );
/// <summary>
/// Signal video source to stop its work.
/// </summary>
///
/// <remarks>Signals video source to stop its background thread, stop to
/// provide new frames and free resources.</remarks>
///
virtual void SignalToStop( );
/// <summary>
/// Wait for video source has stopped.
/// </summary>
///
/// <remarks>Waits for source stopping after it was signalled to stop using
/// <see cref="SignalToStop"/> method.</remarks>
///
virtual void WaitForStop( );
/// <summary>
/// Stop video source.
/// </summary>
///
/// <remarks><para>Stops video source aborting its thread.</para>
///
/// <para><note>Since the method aborts background thread, its usage is highly not preferred
/// and should be done only if there are no other options. The correct way of stopping camera
/// is <see cref="SignalToStop">signaling it stop</see> and then
/// <see cref="WaitForStop">waiting</see> for background thread's completion.</note></para>
/// </remarks>
///
virtual void Stop( );
private:
String^ m_fileName;
Thread^ m_workerThread;
ManualResetEvent^ m_needToStop;
int m_framesReceived;
int m_bytesReceived;
bool m_frameIntervalFromSource;
int m_frameInterval;
private:
void Free( );
void WorkerThreadHandler( );
};
} } }