I use C# to make a screen sharing program, refer to this script SimpleRecorder. Utilizes Windows.Graphics.Capture and Windows.Media.Transcoding. This is the important part of the code of the Encoder class:
private async Task EncodeInternalAsync(IRandomAccessStream stream, uint width, uint height, uint bitrateInBps, uint frameRate)
{
if (!_isRecording)
{
_isRecording = true;
_frameGenerator = new CaptureFrameWait(
_device,
_captureItem,
_captureItem.Size);
using (_frameGenerator)
{
var encodingProfile = new MediaEncodingProfile();
encodingProfile.Container.Subtype = "MPEG4";
encodingProfile.Video.Subtype = "H264";
encodingProfile.Video.Width = width;
encodingProfile.Video.Height = height;
encodingProfile.Video.Bitrate = bitrateInBps;
encodingProfile.Video.FrameRate.Numerator = frameRate;
encodingProfile.Video.FrameRate.Denominator = 1;
encodingProfile.Video.PixelAspectRatio.Numerator = 1;
encodingProfile.Video.PixelAspectRatio.Denominator = 1;
var transcode = await _transcoder.PrepareMediaStreamSourceTranscodeAsync(_mediaStreamSource, randomAccessStream, encodingProfile);
await transcode.TranscodeAsync();
}
}
}
private void CreateMediaObjects()
{
// Create our encoding profile based on the size of the item
int width = _captureItem.Size.Width;
int height = _captureItem.Size.Height;
// Describe our input: uncompressed BGRA8 buffers
var videoProperties = VideoEncodingProperties.CreateUncompressed(MediaEncodingSubtypes.Bgra8, (uint)width, (uint)height);
_videoDescriptor = new VideoStreamDescriptor(videoProperties);
// Create our MediaStreamSource
_mediaStreamSource = new MediaStreamSource(_videoDescriptor);
_mediaStreamSource.BufferTime = TimeSpan.FromSeconds(0);
_mediaStreamSource.Starting += OnMediaStreamSourceStarting;
_mediaStreamSource.SampleRequested += OnMediaStreamSourceSampleRequested;
// Create our transcoder
_transcoder = new MediaTranscoder();
_transcoder.HardwareAccelerationEnabled = true;
}
private void OnMediaStreamSourceSampleRequested(MediaStreamSource sender, MediaStreamSourceSampleRequestedEventArgs args)
{
if (_isRecording && !_closed)
{
try
{
using (var frame = _frameGenerator.WaitForNewFrame())
{
if (frame == null)
{
args.Request.Sample = null;
DisposeInternal();
return;
}
var timeStamp = frame.SystemRelativeTime;
var sample = MediaStreamSample.CreateFromDirect3D11Surface(frame.Surface, timeStamp);
args.Request.Sample = sample;
}
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
Debug.WriteLine(e.StackTrace);
Debug.WriteLine(e);
args.Request.Sample = null;
DisposeInternal();
}
}
else
{
args.Request.Sample = null;
DisposeInternal();
}
}
However, this code var transcode = await _transcoder.PrepareMediaStreamSourceTranscodeAsync(_mediaStreamSource, randomAccessStream, encodingProfile); await transcode.TranscodeAsync();
can only be stored in a file memory and does not allow me to send video streams in real time through UDP multicast.
I think I need to respond to an event after completing the encoding of a frame and obtain the byte[] of this frame. I'm struggling because I don't have much experience with screen sharing.