Skip to content

Commit 803dfb9

Browse files
committed
Fixed asynchronous processing.
1 parent 8ff15b8 commit 803dfb9

File tree

1 file changed

+120
-71
lines changed

1 file changed

+120
-71
lines changed

Assets/NatCorderWithOpenCVForUnityExample/VideoRecordingExample/VideoRecordingExample.cs

+120-71
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
using OpenCVForUnity.UnityUtils.Helper;
99
using System;
1010
using System.Collections;
11+
using System.Threading;
12+
using System.Threading.Tasks;
1113
using UnityEngine;
1214
using UnityEngine.SceneManagement;
1315
using UnityEngine.UI;
@@ -128,8 +130,9 @@ public class VideoRecordingExample : MonoBehaviour
128130

129131
IClock recordingClock;
130132

131-
const float MAX_RECORDING_TIME = 10f;
132-
// Seconds
133+
CancellationTokenSource cancellationTokenSource;
134+
135+
const int MAX_RECORDING_TIME = 10; // Seconds
133136

134137
string videoPath = "";
135138

@@ -139,6 +142,8 @@ public class VideoRecordingExample : MonoBehaviour
139142

140143
bool isVideoRecording;
141144

145+
bool isFinishWriting;
146+
142147
int frameCount;
143148

144149
int recordEveryNthFrame;
@@ -253,7 +258,7 @@ public void OnWebCamTextureToMatHelperDisposed()
253258
{
254259
Debug.Log("OnWebCamTextureToMatHelperDisposed");
255260

256-
StopRecording();
261+
CancelRecording();
257262
StopVideo();
258263

259264
if (texture != null)
@@ -283,7 +288,7 @@ void Update()
283288
if (applyComicFilter)
284289
comicFilter.Process(rgbaMat, rgbaMat);
285290

286-
if (isVideoRecording)
291+
if (isVideoRecording && !isFinishWriting)
287292
{
288293
textPos.x = 5;
289294
textPos.y = rgbaMat.rows() - 70;
@@ -313,7 +318,7 @@ void Update()
313318
Utils.fastMatToTexture2D(rgbaMat, texture);
314319

315320
// Record frames
316-
if (videoRecorder != null && isVideoRecording && frameCount++ % recordEveryNthFrame == 0)
321+
if (videoRecorder != null && (isVideoRecording && !isFinishWriting) && frameCount++ % recordEveryNthFrame == 0)
317322
{
318323
videoRecorder.CommitFrame((IntPtr)rgbaMat.dataAddr(), recordingClock.timestamp);
319324
}
@@ -325,9 +330,9 @@ void Update()
325330
}
326331
}
327332

328-
private void StartRecording()
333+
private async Task StartRecording()
329334
{
330-
if (isVideoPlaying || isVideoRecording)
335+
if (isVideoPlaying || isVideoRecording || isFinishWriting)
331336
return;
332337

333338
Debug.Log("StartRecording ()");
@@ -344,7 +349,7 @@ private void StartRecording()
344349
videoBitrate = (int)(960 * 540 * 11.4f);
345350
frameDuration = 0.1f;
346351

347-
// Start recording
352+
// Create video recorder
348353
recordingClock = new RealtimeClock();
349354
if (container == ContainerPreset.MP4)
350355
{
@@ -387,73 +392,125 @@ private void StartRecording()
387392
}
388393
frameCount = 0;
389394

395+
396+
397+
// Start recording
398+
isVideoRecording = true;
399+
400+
HideAllVideoUI();
401+
recordVideoButton.interactable = true;
402+
recordVideoButton.GetComponentInChildren<UnityEngine.UI.Text>().color = Color.red;
403+
404+
CreateSettingInfo();
405+
390406
// Start microphone and create audio input
391407
if (recordMicrophoneAudio)
392408
{
393-
StartMicrophone();
409+
await StartMicrophone();
394410
audioInput = new AudioInput(videoRecorder, recordingClock, microphoneSource, true);
395411
}
396412

397-
StartCoroutine("Countdown");
413+
// Start countdown
414+
cancellationTokenSource = new CancellationTokenSource();
415+
try
416+
{
417+
Debug.Log("Countdown start.");
418+
await CountdownAsync(
419+
sec =>
420+
{
421+
string str = "Recording";
422+
for (int i = 0; i < sec; i++)
423+
{
424+
str += ".";
425+
}
398426

399-
HideAllVideoUI();
400-
recordVideoButton.interactable = true;
401-
recordVideoButton.GetComponentInChildren<UnityEngine.UI.Text>().color = Color.red;
427+
if (fpsMonitor != null) fpsMonitor.consoleText = str;
402428

403-
CreateSettingInfo();
429+
}, MAX_RECORDING_TIME, cancellationTokenSource.Token);
430+
Debug.Log("Countdown end.");
431+
}
432+
catch (OperationCanceledException e)
433+
{
434+
if (e.CancellationToken == cancellationTokenSource.Token)
435+
{
436+
Debug.Log("Countdown canceled.");
437+
}
438+
}
439+
cancellationTokenSource.Dispose();
440+
cancellationTokenSource = null;
404441

405-
isVideoRecording = true;
442+
if (this != null && isActiveAndEnabled)
443+
await FinishRecording();
406444
}
407445

408-
private void StartMicrophone()
446+
private void CancelRecording()
409447
{
410-
// Create a microphone clip
411-
microphoneSource.loop = true;
412-
microphoneSource.bypassEffects =
413-
microphoneSource.bypassListenerEffects = false;
414-
microphoneSource.clip = Microphone.Start(null, true, (int)MAX_RECORDING_TIME, (int)microphoneFrequency);
415-
while (Microphone.GetPosition(null) <= 0) { }
416-
microphoneSource.Play();
448+
if (!isVideoRecording || isFinishWriting)
449+
return;
450+
451+
if (cancellationTokenSource != null)
452+
cancellationTokenSource.Cancel(true);
417453
}
418454

419-
private async void StopRecording()
455+
private async Task FinishRecording()
420456
{
421-
if (!isVideoRecording)
457+
if (!isVideoRecording || isFinishWriting)
422458
return;
423459

424-
isVideoRecording = false;
425-
426-
Debug.Log("StopRecording ()");
427-
428-
StopCoroutine("Countdown");
429-
if (fpsMonitor != null)
430-
{
431-
fpsMonitor.consoleText = "";
432-
}
433-
434460
// Stop the microphone if we used it for recording
435461
if (recordMicrophoneAudio)
436462
{
437463
StopMicrophone();
438464
audioInput.Dispose();
439465
}
440466

467+
if (fpsMonitor != null) fpsMonitor.consoleText = "FinishWriting...";
468+
441469
// Stop recording
470+
isFinishWriting = true;
442471
try
443472
{
444473
var path = await videoRecorder.FinishWriting();
445474
videoPath = path;
446475
Debug.Log("Saved recording to: " + videoPath);
447476
savePathInputField.text = videoPath;
448477
}
449-
catch (Exception e)
478+
catch (ApplicationException e)
450479
{
451480
Debug.Log(e.Message);
452481
savePathInputField.text = e.Message;
453482
}
483+
isFinishWriting = false;
484+
485+
if (fpsMonitor != null) fpsMonitor.consoleText = "";
454486

455487
ShowAllVideoUI();
456488
recordVideoButton.GetComponentInChildren<UnityEngine.UI.Text>().color = Color.black;
489+
490+
isVideoRecording = false;
491+
}
492+
493+
private Task<bool> StartMicrophone()
494+
{
495+
var task = new TaskCompletionSource<bool>();
496+
StartCoroutine(CreateMicrophone(granted =>
497+
{
498+
microphoneSource.Play();
499+
task.SetResult(granted);
500+
}));
501+
502+
return task.Task;
503+
}
504+
505+
private IEnumerator CreateMicrophone(Action<bool> completionHandler)
506+
{
507+
// Create a microphone clip
508+
microphoneSource.loop = true;
509+
microphoneSource.bypassEffects =
510+
microphoneSource.bypassListenerEffects = false;
511+
microphoneSource.clip = Microphone.Start(null, true, MAX_RECORDING_TIME, (int)microphoneFrequency);
512+
yield return new WaitUntil(() => Microphone.GetPosition(null) > 0);
513+
completionHandler(true);
457514
}
458515

459516
private void StopMicrophone()
@@ -463,31 +520,22 @@ private void StopMicrophone()
463520
Microphone.End(null);
464521
}
465522

466-
private IEnumerator Countdown()
523+
private async Task CountdownAsync(Action<int> countdownHandler, int sec = 10, CancellationToken cancellationToken = default(CancellationToken))
467524
{
468-
float startTime = Time.time;
469-
while ((Time.time - startTime) < MAX_RECORDING_TIME)
525+
for (int i = sec; i > 0; i--)
470526
{
471-
472-
if (fpsMonitor != null)
473-
{
474-
string str = "Recording";
475-
for (int i = 0; i < (int)(MAX_RECORDING_TIME - (Time.time - startTime)); i++)
476-
{
477-
str += ".";
478-
}
479-
fpsMonitor.consoleText = str;
480-
}
481-
482-
yield return new WaitForSeconds(0.5f);
527+
cancellationToken.ThrowIfCancellationRequested();
528+
countdownHandler(i);
529+
await Task.Delay(1000, cancellationToken);
483530
}
484-
485-
StopRecording();
531+
cancellationToken.ThrowIfCancellationRequested();
532+
countdownHandler(0);
486533
}
487534

535+
488536
private void PlayVideo(string path)
489537
{
490-
if (isVideoPlaying || isVideoRecording || string.IsNullOrEmpty(path))
538+
if (isVideoPlaying || isVideoRecording || isFinishWriting || string.IsNullOrEmpty(path))
491539
return;
492540

493541
Debug.Log("PlayVideo ()");
@@ -517,7 +565,7 @@ private void PlayVideo(string path)
517565

518566
private void PrepareCompleted(VideoPlayer vp)
519567
{
520-
Debug.Log("PrepareCompleted");
568+
Debug.Log("PrepareCompleted ()");
521569

522570
vp.prepareCompleted -= PrepareCompleted;
523571

@@ -528,9 +576,7 @@ private void PrepareCompleted(VideoPlayer vp)
528576

529577
private void EndReached(VideoPlayer vp)
530578
{
531-
Debug.Log("EndReached");
532-
533-
videoPlayer.loopPointReached -= EndReached;
579+
Debug.Log("EndReached ()");
534580

535581
StopVideo();
536582
}
@@ -542,16 +588,19 @@ private void StopVideo()
542588

543589
Debug.Log("StopVideo ()");
544590

591+
videoPlayer.loopPointReached -= EndReached;
592+
545593
if (videoPlayer.isPlaying)
546594
videoPlayer.Stop();
547595

548-
gameObject.GetComponent<Renderer>().sharedMaterial.mainTexture = texture;
549-
550-
webCamTextureToMatHelper.Play();
551-
552596
isVideoPlaying = false;
553597

554-
ShowAllVideoUI();
598+
if (this != null && isActiveAndEnabled)
599+
{
600+
gameObject.GetComponent<Renderer>().sharedMaterial.mainTexture = texture;
601+
webCamTextureToMatHelper.Play();
602+
ShowAllVideoUI();
603+
}
555604
}
556605

557606
private void ShowAllVideoUI()
@@ -717,20 +766,20 @@ public void OnRecordMicrophoneAudioToggleValueChanged()
717766
/// <summary>
718767
/// Raises the record video button click event.
719768
/// </summary>
720-
public void OnRecordVideoButtonClick()
769+
public async void OnRecordVideoButtonClick()
721770
{
722771
Debug.Log("OnRecordVideoButtonClick ()");
723772

724773
if (isVideoPlaying)
725774
return;
726775

727-
if (isVideoRecording)
776+
if (!isVideoRecording && !isFinishWriting)
728777
{
729-
StopRecording();
778+
await StartRecording();
730779
}
731780
else
732781
{
733-
StartRecording();
782+
CancelRecording();
734783
}
735784
}
736785

@@ -741,7 +790,7 @@ public void OnPlayVideoButtonClick()
741790
{
742791
Debug.Log("OnPlayVideoButtonClick ()");
743792

744-
if (isVideoPlaying || isVideoRecording || string.IsNullOrEmpty(videoPath))
793+
if (isVideoPlaying || isVideoRecording || isFinishWriting || string.IsNullOrEmpty(videoPath))
745794
return;
746795

747796
if (System.IO.Path.GetExtension(videoPath) == ".gif")
@@ -767,7 +816,7 @@ public void OnPlayVideoFullScreenButtonClick()
767816
{
768817
Debug.Log("OnPlayVideoFullScreenButtonClick ()");
769818

770-
if (isVideoPlaying || isVideoRecording || string.IsNullOrEmpty(videoPath))
819+
if (isVideoPlaying || isVideoRecording || isFinishWriting || string.IsNullOrEmpty(videoPath))
771820
return;
772821

773822
// Playback the video
@@ -788,7 +837,7 @@ public void OnShareButtonClick()
788837
{
789838
Debug.Log("OnShareButtonClick ()");
790839

791-
if (isVideoPlaying || isVideoRecording || string.IsNullOrEmpty(videoPath))
840+
if (isVideoPlaying || isVideoRecording || isFinishWriting || string.IsNullOrEmpty(videoPath))
792841
return;
793842

794843
using (var payload = new SharePayload("NatCorderWithOpenCVForUnityExample",
@@ -810,7 +859,7 @@ public void OnSaveToCameraRollButtonClick()
810859
{
811860
Debug.Log("OnSaveToCameraRollButtonClick ()");
812861

813-
if (isVideoPlaying || isVideoRecording || string.IsNullOrEmpty(videoPath))
862+
if (isVideoPlaying || isVideoRecording || isFinishWriting || string.IsNullOrEmpty(videoPath))
814863
return;
815864

816865
using (var payload = new SavePayload("NatCorderWithOpenCVForUnityExample",

0 commit comments

Comments
 (0)