public void StartLocalVideo(VideoMode videoMode)
{
if (_localVideoSamplingTask != null && !_localVideoSamplingTask.IsCompleted && _localVideoSamplingCancelTokenSource != null)
{
_localVideoSamplingCancelTokenSource.Cancel();
}
var videoSampler = new MFVideoSampler();
videoSampler.Init(videoMode.DeviceIndex, VideoSubTypesEnum.RGB24, videoMode.Width, videoMode.Height);
//videoSampler.InitFromFile();
//_audioChannel = new AudioChannel();
_localVideoSamplingCancelTokenSource = new CancellationTokenSource();
var cancellationToken = _localVideoSamplingCancelTokenSource.Token;
_localVideoSamplingTask = Task.Factory.StartNew(() =>
{
Thread.CurrentThread.Name = "vidsampler_" + videoMode.DeviceIndex + "_" + videoMode.Width + "_" + videoMode.Height;
var vpxEncoder = new VPXEncoder();
vpxEncoder.InitEncoder(Convert.ToUInt32(videoMode.Width), Convert.ToUInt32(videoMode.Height));
// var videoSampler = new MFVideoSampler();
//videoSampler.Init(videoMode.DeviceIndex, videoMode.Width, videoMode.Height);
// videoSampler.InitFromFile();
while (!_stop && !cancellationToken.IsCancellationRequested)
{
byte[] videoSample = null;
int result = videoSampler.GetSample(ref videoSample);
if (result == NAudio.MediaFoundation.MediaFoundationErrors.MF_E_HW_MFT_FAILED_START_STREAMING)
{
logger.Warn("A sample could not be acquired from the local webcam. Check that it is not already in use.");
OnLocalVideoError("A sample could not be acquired from the local webcam. Check that it is not already in use.");
break;
}
else if (result != 0)
{
logger.Warn("A sample could not be acquired from the local webcam. Check that it is not already in use. Error code: " + result);
OnLocalVideoError("A sample could not be acquired from the local webcam. Check that it is not already in use. Error code: " + result);
break;
}
else if (videoSample != null)
{
// This event sends the raw bitmap to the WPF UI.
if (OnLocalVideoSampleReady != null)
{
OnLocalVideoSampleReady(videoSample, videoSampler.Width, videoSampler.Height);
}
// This event encodes the sample and forwards it to the RTP manager for network transmission.
if (_rtpManager != null)
{
IntPtr rawSamplePtr = Marshal.AllocHGlobal(videoSample.Length);
Marshal.Copy(videoSample, 0, rawSamplePtr, videoSample.Length);
byte[] yuv = null;
unsafe
{
_imageConverter.ConvertRGBtoYUV((byte*)rawSamplePtr, VideoSubTypesEnum.RGB24, Convert.ToInt32(videoMode.Width), Convert.ToInt32(videoMode.Height), VideoSubTypesEnum.I420, ref yuv);
//_imageConverter.ConvertToI420((byte*)rawSamplePtr, VideoSubTypesEnum.RGB24, Convert.ToInt32(videoMode.Width), Convert.ToInt32(videoMode.Height), ref yuv);
}
Marshal.FreeHGlobal(rawSamplePtr);
IntPtr yuvPtr = Marshal.AllocHGlobal(yuv.Length);
Marshal.Copy(yuv, 0, yuvPtr, yuv.Length);
byte[] encodedBuffer = null;
unsafe
{
vpxEncoder.Encode((byte*)yuvPtr, yuv.Length, _encodingSample++, ref encodedBuffer);
}
Marshal.FreeHGlobal(yuvPtr);
//if(encodedBuffer )
_rtpManager.LocalVideoSampleReady(encodedBuffer);
}
}
}
videoSampler.Stop();
vpxEncoder.Dispose();
}, cancellationToken);
_localAudioSamplingTask = Task.Factory.StartNew(() =>
{
Thread.CurrentThread.Name = "audsampler_" + videoMode.DeviceIndex;
while (!_stop && !cancellationToken.IsCancellationRequested)
{
byte[] audioSample = null;
int result = videoSampler.GetAudioSample(ref audioSample);
if (result == NAudio.MediaFoundation.MediaFoundationErrors.MF_E_HW_MFT_FAILED_START_STREAMING)
{
logger.Warn("An audio sample could not be acquired from the local source. Check that it is not already in use.");
//OnLocalVideoError("A sample could not be acquired from the local webcam. Check that it is not already in use.");
break;
}
else if (result != 0)
{
logger.Warn("An audio sample could not be acquired from the local source. Check that it is not already in use. Error code: " + result);
//OnLocalVideoError("A sample could not be acquired from the local webcam. Check that it is not already in use. Error code: " + result);
break;
}
else if (audioSample != null)
{
if (_audioChannel != null)
{
_audioChannel.AudioSampleReceived(audioSample, 0);
}
}
}
}, cancellationToken);
}