public async void SeparateThreadToSaveVideoStream() { while (isRecording == true) { //thread is counting //sometimes stuck at thread at frame : 0, depending on the window chosen to record //meaning OnFrameArrived is not called if (parent != null) { DateTime currentTimeLocal = DateTime.Now; TimeSpan elpasedTimeLocal = currentTimeLocal - initialRecordTime; string debugstr = "At frame: " + counter.ToString() + " Threadcounter: " + threadcounter.ToString(); //debugstr += " StreamSize: " + ((int)(videostream.Size / 1024.0)).ToString() + "KB TimeElapsed: " + ((int)elpasedTimeLocal.TotalSeconds).ToString(); debugstr += " StreamSize: " + ((int)(totalMemoryUsed / 1024.0)).ToString() + " KB"; debugstr += " TimeElapsed: " + ((int)elpasedTimeLocal.TotalSeconds).ToString(); parent.msg(debugstr); } threadcounter++; if (threadcounter > 200000) { threadcounter = 0; } if (currentFrame != null) { CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromDirect3D11Surface( canvasDevice, currentFrame.Surface); using (var inputstream = new InMemoryRandomAccessStream()) { CancellationToken ct = new CancellationToken(); await canvasBitmap.SaveAsync(inputstream, CanvasBitmapFileFormat.Png, 1f).AsTask(ct); ulong currentFrameLength = inputstream.Size; _currentVideoStreamPos = 0; totalMemoryUsed += currentFrameLength; DateTime currentTimeLocal = DateTime.Now; TimeSpan diff = currentTimeLocal - previousRecordTime; previousRecordTime = currentTimeLocal; UnpackItem unpackItem = new UnpackItem(); unpackItem.pos = _currentVideoStreamPos; unpackItem.length = currentFrameLength; unpackItem.frameTime = diff; unpackItem.compressedBuffer = new Windows.Storage.Streams.Buffer((uint)inputstream.Size); inputstream.Seek(0); await inputstream.ReadAsync(unpackItem.compressedBuffer, (uint)inputstream.Size, InputStreamOptions.None); //read from stream to buffer await inputstream.FlushAsync(); unpackList.Add(unpackItem); } currentFrame?.Dispose(); currentFrame = null; //need this line so this thread will continue loop when new frame is not yet ready } else { Thread.Sleep(10); } } //await CloseVideoStream(); int len = unpackList.Count; DateTime currentTime = DateTime.Now; TimeSpan elpasedTime = currentTime - initialRecordTime; string debugstrx = "Num frame: " + len.ToString() + " Threadcounter: " + threadcounter.ToString(); debugstrx += " TimeElapsed: " + ((int)elpasedTime.TotalSeconds).ToString(); if (elpasedTime.TotalSeconds > 0) { debugstrx += " Frame Rate (fps) : " + (len / (double)elpasedTime.TotalSeconds).ToString(); } if (parent != null) { parent.StartWritingReport(debugstrx); } //await UnpackVideoStream(); }
/// <summary> /// //Encoding a Win2D surface (CanvasRenderTarget) as a video frame /// </summary> private async void OnMSSSampleRequested(MediaStreamSource sender, MediaStreamSourceSampleRequestedEventArgs args) { if (parent != null) { parent.StartWritingOutput("OnSampleRequested " + frameCounter.ToString(), 0); } if (unpackList == null) { if (parent != null) { parent.StartWritingOutput("Unpack List Null Error!", 1); } //this will stop the encoding args.Request.Sample = null; return; } int len = unpackList.Count; if (frameCounter >= len) { if (parent != null) { parent.StartWritingOutput("Encoding Completed.", 1); } //this will stop the encoding args.Request.Sample = null; return; } if ((frameCounter < 0) || (0 == len)) { if (parent != null) { parent.StartWritingOutput("Invalid Frame", 1); } //this will stop the encoding args.Request.Sample = null; return; } //need deferral because CanvasBitmap.LoadAsync takes some time to complete ? var deferral = args.Request.GetDeferral(); /// UnpackItem unpackItem = unpackList[frameCounter]; Windows.Storage.Streams.Buffer buffer = unpackItem.compressedBuffer; InMemoryRandomAccessStream inMemoryRandomAccessStream = null; using (inMemoryRandomAccessStream = new InMemoryRandomAccessStream()) { await inMemoryRandomAccessStream.WriteAsync(buffer); await inMemoryRandomAccessStream.FlushAsync(); inMemoryRandomAccessStream.Seek(0); CanvasBitmap tempBitmap = null; try { tempBitmap = await CanvasBitmap.LoadAsync(CanvasDevice.GetSharedDevice(), inMemoryRandomAccessStream); } catch (Exception e) { if (parent != null) { parent.StartWritingOutput("CBM Error : " + e.Message, 1); } } if (tempBitmap != null) { CanvasRenderTarget canvasRenderTarget = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), tempBitmap.SizeInPixels.Width, tempBitmap.SizeInPixels.Height, tempBitmap.Dpi); using (CanvasDrawingSession session = canvasRenderTarget.CreateDrawingSession()) { session.Clear(Colors.Black); //session.DrawEllipse(new System.Numerics.Vector2(120 + frameCounter * 2, 100), 30, 20, Colors.White); session.DrawImage(tempBitmap); } TimeSpan timeLapsed = unpackItem.frameTime; Timestamp += timeLapsed; //set sample after defferal ? nope ....stop at 1st frame... MediaStreamSample sample = MediaStreamSample.CreateFromDirect3D11Surface(canvasRenderTarget, Timestamp); args.Request.Sample = sample; deferral.Complete(); } else { args.Request.Sample = null; deferral.Complete(); } frameCounter++; } }
public async Task UnpackToMp4() { MediaComposition mediacomposition = new MediaComposition(); StorageFolder pictureFolder = KnownFolders.SavedPictures; { int len = simpleRecorder.unpackList.Count; for (int i = 0; i < len; i++) { UnpackItem unpackItem = simpleRecorder.unpackList[i]; Windows.Storage.Streams.Buffer buffer = unpackItem.compressedBuffer; InMemoryRandomAccessStream inMemoryRandomAccessStream = null; using (inMemoryRandomAccessStream = new InMemoryRandomAccessStream()) { await inMemoryRandomAccessStream.WriteAsync(buffer); await inMemoryRandomAccessStream.FlushAsync(); inMemoryRandomAccessStream.Seek(0); CanvasBitmap tempBitmap = await CanvasBitmap.LoadAsync(CanvasDevice.GetSharedDevice(), inMemoryRandomAccessStream); if (tempBitmap != null) { CanvasRenderTarget canvasRenderTarget = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), tempBitmap.SizeInPixels.Width, tempBitmap.SizeInPixels.Height, 96); using (CanvasDrawingSession session = canvasRenderTarget.CreateDrawingSession()) { session.Clear(Colors.Black); session.DrawImage(tempBitmap); TimeSpan frameTime30Mil = TimeSpan.FromMilliseconds(30f); TimeSpan frameTime = unpackItem.frameTime; //if (frameTime < frameTime30Mil) // frameTime = frameTime30Mil; MediaClip mediaclip = MediaClip.CreateFromSurface(canvasRenderTarget, frameTime); mediacomposition.Clips.Add(mediaclip); } string str = "Adding Clips " + (i + 1).ToString() + " / " + len.ToString(); if (i == len - 1) { str += " ... Please wait for file rendering ..."; } TextOutput.Text = str; } } //free up memory recources as each frame is unpacked if (unpackItem.compressedBuffer != null) { unpackItem.compressedBuffer = null; } } //for } StorageFile mp4file = null; if (simpleRecorder.savefile != null) { mp4file = simpleRecorder.savefile; } else { string mp4filename = "SavedVideo" + ".mp4"; mp4file = await pictureFolder.CreateFileAsync( mp4filename, CreationCollisionOption.ReplaceExisting); } //await mediacomposition.RenderToFileAsync(mp4file, MediaTrimmingPreference.Precise, MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD720p)); var rendering = mediacomposition.RenderToFileAsync(mp4file, MediaTrimmingPreference.Precise, MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD720p)); rendering.Progress += ProgressReport; rendering.Completed += CompletedReport; }