This repository was archived by the owner on Sep 25, 2018. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathCameraStreamSource.cs
More file actions
177 lines (143 loc) · 6.38 KB
/
Copy pathCameraStreamSource.cs
File metadata and controls
177 lines (143 loc) · 6.38 KB
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
/*
* Copyright © 2013 Nokia Corporation. All rights reserved.
* Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation.
* Other product and company names mentioned herein may be trademarks
* or trade names of their respective owners.
* See LICENSE.TXT for license information.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Threading;
using Windows.Foundation;
namespace RealtimeFilterDemo
{
/// <summary>
/// Filtered camera stream source for a media element. Feeds the media element with frames filtered with a ICameraEffect implementation.
/// </summary>
public class CameraStreamSource : MediaStreamSource
{
private readonly Dictionary<MediaSampleAttributeKeys, string> _emptyAttributes = new Dictionary<MediaSampleAttributeKeys, string>();
private MediaStreamDescription _videoStreamDescription = null;
private DispatcherTimer _frameRateTimer = null;
private MemoryStream _frameStream = null;
private ICameraEffect _cameraEffect = null;
private long _currentTime = 0;
private int _frameStreamOffset = 0;
private int _frameTime = 0;
private int _frameCount = 0;
private Size _frameSize = new Size(0, 0);
private int _frameBufferSize = 0;
private byte[] _frameBuffer = null;
/// <summary>
/// Occurs when rendering frame rate changes.
/// </summary>
public event EventHandler<int> FrameRateChanged;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="_cameraEffect">Camera effect to use.</param>
/// <param name="size">Size of the media element where the stream is rendered to.</param>
public CameraStreamSource(ICameraEffect cameraEffect, Size size)
{
_cameraEffect = cameraEffect;
_frameSize = size;
}
/// <summary>
/// Initialises the data structures to pass data to the media pipeline via the MediaStreamSource.
/// </summary>
protected override void OpenMediaAsync()
{
// General properties
_frameBufferSize = (int)_frameSize.Width * (int)_frameSize.Height * 4; // RGBA
_frameBuffer = new byte[_frameBufferSize];
_frameStream = new MemoryStream(_frameBuffer);
// Media stream attributes
var mediaStreamAttributes = new Dictionary<MediaStreamAttributeKeys, string>();
mediaStreamAttributes[MediaStreamAttributeKeys.VideoFourCC] = "RGBA";
mediaStreamAttributes[MediaStreamAttributeKeys.Width] = ((int)_frameSize.Width).ToString();
mediaStreamAttributes[MediaStreamAttributeKeys.Height] = ((int)_frameSize.Height).ToString();
_videoStreamDescription = new MediaStreamDescription(MediaStreamType.Video, mediaStreamAttributes);
// Media stream descriptions
var mediaStreamDescriptions = new List<MediaStreamDescription>();
mediaStreamDescriptions.Add(_videoStreamDescription);
// Media source attributes
var mediaSourceAttributes = new Dictionary<MediaSourceAttributesKeys, string>();
mediaSourceAttributes[MediaSourceAttributesKeys.Duration] = TimeSpan.FromSeconds(0).Ticks.ToString(CultureInfo.InvariantCulture);
mediaSourceAttributes[MediaSourceAttributesKeys.CanSeek] = false.ToString();
_frameTime = (int)TimeSpan.FromSeconds((double)0).Ticks;
// Start frame rate timer
_frameRateTimer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) };
_frameRateTimer.Tick += FrameRateTimer_Tick;
_frameRateTimer.Start();
// Report that we finished initializing its internal state and can now pass in frame samples
ReportOpenMediaCompleted(mediaSourceAttributes, mediaStreamDescriptions);
}
protected override void CloseMedia()
{
if (_frameStream != null)
{
_frameStream.Close();
_frameStream = null;
}
if (_frameRateTimer != null)
{
_frameRateTimer.Stop();
_frameRateTimer.Tick -= FrameRateTimer_Tick;
_frameRateTimer = null;
}
_frameStreamOffset = 0;
_frameTime = 0;
_frameCount = 0;
_frameBufferSize = 0;
_frameBuffer = null;
_videoStreamDescription = null;
_currentTime = 0;
}
/// <summary>
/// Processes camera frameBuffer using the set effect and provides media element with a filtered frameBuffer.
/// </summary>
protected override void GetSampleAsync(MediaStreamType mediaStreamType)
{
var task = _cameraEffect.GetNewFrameAndApplyEffect(_frameBuffer.AsBuffer(), _frameSize);
// When asynchroneous call completes, proceed by reporting about the sample completion
task.ContinueWith((action) =>
{
if (_frameStream != null)
{
_frameStream.Position = 0;
_currentTime += _frameTime;
_frameCount++;
var sample = new MediaStreamSample(_videoStreamDescription, _frameStream, _frameStreamOffset, _frameBufferSize, _currentTime, _emptyAttributes);
ReportGetSampleCompleted(sample);
}
});
}
protected override void GetDiagnosticAsync(MediaStreamSourceDiagnosticKind diagnosticKind)
{
throw new NotImplementedException();
}
protected override void SeekAsync(long seekToTime)
{
_currentTime = seekToTime;
ReportSeekCompleted(_currentTime);
}
protected override void SwitchMediaStreamAsync(MediaStreamDescription mediaStreamDescription)
{
throw new NotImplementedException();
}
private void FrameRateTimer_Tick(object sender, EventArgs e)
{
if (FrameRateChanged != null)
{
FrameRateChanged(this, _frameCount);
}
_frameCount = 0;
}
}
}