[英]Pausing / Resuming Screen recording with Windows Graphics Capture API
我正在使用Windows Graphics Capture API 在 C# 構建一個屏幕錄制應用程序。我正在使用這個腳本。 我可以 select 監控並可以將其錄制到 mp4 文件。 我正在嘗試添加暫停/恢復功能。
這是啟動錄音的主要代碼 Window
try
{
newFile = GetTempFile();
using (var stream = new FileStream(newFile, FileMode.CreateNew).AsRandomAccessStream())
using (_encoder = new Encoder(_device, item))
{
await _encoder.EncodeAsync(
stream,
width, height, bitrate,
frameRate);
}
}
catch (Exception ex)
{
//
}
這是上面使用的編碼器 class的主要 function
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, stream, encodingProfile);
await transcode.TranscodeAsync();
}
}
}
最后這是CaptureFrameWait class 中的初始化器 function
private void InitializeCapture(SizeInt32 size)
{
_framePool = Direct3D11CaptureFramePool.CreateFreeThreaded(
_device,
DirectXPixelFormat.B8G8R8A8UIntNormalized,
1,
size);
_framePool.FrameArrived += OnFrameArrived;
_session = _framePool.CreateCaptureSession(_item);
_session.IsBorderRequired = false;
_session.StartCapture();
}
我們如何修改它以暫停錄制? 我試圖在暫停時處理_framepool和_session對象,並在CaptureFrameWait class 中的恢復時再次初始化它們,如下所示。 它工作正常,但有時 TranscodeAsync function 在暫停期間終止並結束錄制。 我們怎樣才能避免這種情況?
bool _paused = false;
public void PauseSession(bool status)
{
if (status) {
_paused = true;
_framePool?.Dispose();
_session?.Dispose();
}
else {
InitializeCapture(_size);
_paused = false;
}
}
一種解決方案是延期。 醫生說:
然后 MediaStreamSource 將等待您提供 MediaStreamSample,直到您將延遲標記為完成。
因此,例如,將兩個私有成員添加到Encoder
class 和兩個方法:
private MediaStreamSourceSampleRequestedEventArgs _args;
private MediaStreamSourceSampleRequestDeferral _def;
public bool IsPaused { get; private set; }
public void Pause()
{
IsPaused = true;
}
public void Resume()
{
IsPaused = false;
// complete the request we saved earlier
OnMediaStreamSourceSampleRequested(_mediaStreamSource, _args);
}
並像這樣修改OnMediaStreamSourceSampleRequested
方法(我在其中發表評論):
private void OnMediaStreamSourceSampleRequested(MediaStreamSource sender, MediaStreamSourceSampleRequestedEventArgs args)
{
if (_isRecording && !_closed)
{
// if paused get a deferral and save the current arguments.
// OnMediaStreamSourceSampleRequested will not be called again until we complete the deferral
if (IsPaused)
{
_def = args.Request.GetDeferral();
_args = args;
return;
}
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;
// when called again (manually by us) complete the work
// and reset members
if (_def != null)
{
_def.Complete();
_def = null;
_args = null;
}
}
}
catch (Exception e)
{
...
}
}
else
{
...
}
}
另一種解決方案是簡單地凍結幀時間戳,因此添加這些成員:
private TimeSpan _pausedTimestamp;
public bool IsPaused { get; private set; }
public void Pause()
{
IsPaused = true;
}
public void Resume()
{
IsPaused = false;
}
並像這樣修改OnMediaStreamSourceSampleRequested
方法(我在其中發表評論):
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;
}
// if paused, "freeze" the timestamp
TimeSpan timeStamp;
if (IsPaused)
{
timeStamp = _pausedTimestamp;
}
else
{
timeStamp = frame.SystemRelativeTime;
_pausedTimestamp = timeStamp;
}
var sample = MediaStreamSample.CreateFromDirect3D11Surface(frame.Surface, timeStamp);
args.Request.Sample = sample;
}
}
catch (Exception e)
{
...
}
}
else
{
...
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.