8
8
using OpenCVForUnity . UnityUtils . Helper ;
9
9
using System ;
10
10
using System . Collections ;
11
+ using System . Threading ;
12
+ using System . Threading . Tasks ;
11
13
using UnityEngine ;
12
14
using UnityEngine . SceneManagement ;
13
15
using UnityEngine . UI ;
@@ -128,8 +130,9 @@ public class VideoRecordingExample : MonoBehaviour
128
130
129
131
IClock recordingClock ;
130
132
131
- const float MAX_RECORDING_TIME = 10f ;
132
- // Seconds
133
+ CancellationTokenSource cancellationTokenSource ;
134
+
135
+ const int MAX_RECORDING_TIME = 10 ; // Seconds
133
136
134
137
string videoPath = "" ;
135
138
@@ -139,6 +142,8 @@ public class VideoRecordingExample : MonoBehaviour
139
142
140
143
bool isVideoRecording ;
141
144
145
+ bool isFinishWriting ;
146
+
142
147
int frameCount ;
143
148
144
149
int recordEveryNthFrame ;
@@ -253,7 +258,7 @@ public void OnWebCamTextureToMatHelperDisposed()
253
258
{
254
259
Debug . Log ( "OnWebCamTextureToMatHelperDisposed" ) ;
255
260
256
- StopRecording ( ) ;
261
+ CancelRecording ( ) ;
257
262
StopVideo ( ) ;
258
263
259
264
if ( texture != null )
@@ -283,7 +288,7 @@ void Update()
283
288
if ( applyComicFilter )
284
289
comicFilter . Process ( rgbaMat , rgbaMat ) ;
285
290
286
- if ( isVideoRecording )
291
+ if ( isVideoRecording && ! isFinishWriting )
287
292
{
288
293
textPos . x = 5 ;
289
294
textPos . y = rgbaMat . rows ( ) - 70 ;
@@ -313,7 +318,7 @@ void Update()
313
318
Utils . fastMatToTexture2D ( rgbaMat , texture ) ;
314
319
315
320
// Record frames
316
- if ( videoRecorder != null && isVideoRecording && frameCount ++ % recordEveryNthFrame == 0 )
321
+ if ( videoRecorder != null && ( isVideoRecording && ! isFinishWriting ) && frameCount ++ % recordEveryNthFrame == 0 )
317
322
{
318
323
videoRecorder . CommitFrame ( ( IntPtr ) rgbaMat . dataAddr ( ) , recordingClock . timestamp ) ;
319
324
}
@@ -325,9 +330,9 @@ void Update()
325
330
}
326
331
}
327
332
328
- private void StartRecording ( )
333
+ private async Task StartRecording ( )
329
334
{
330
- if ( isVideoPlaying || isVideoRecording )
335
+ if ( isVideoPlaying || isVideoRecording || isFinishWriting )
331
336
return ;
332
337
333
338
Debug . Log ( "StartRecording ()" ) ;
@@ -344,7 +349,7 @@ private void StartRecording()
344
349
videoBitrate = ( int ) ( 960 * 540 * 11.4f ) ;
345
350
frameDuration = 0.1f ;
346
351
347
- // Start recording
352
+ // Create video recorder
348
353
recordingClock = new RealtimeClock ( ) ;
349
354
if ( container == ContainerPreset . MP4 )
350
355
{
@@ -387,73 +392,125 @@ private void StartRecording()
387
392
}
388
393
frameCount = 0 ;
389
394
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
+
390
406
// Start microphone and create audio input
391
407
if ( recordMicrophoneAudio )
392
408
{
393
- StartMicrophone ( ) ;
409
+ await StartMicrophone ( ) ;
394
410
audioInput = new AudioInput ( videoRecorder , recordingClock , microphoneSource , true ) ;
395
411
}
396
412
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
+ }
398
426
399
- HideAllVideoUI ( ) ;
400
- recordVideoButton . interactable = true ;
401
- recordVideoButton . GetComponentInChildren < UnityEngine . UI . Text > ( ) . color = Color . red ;
427
+ if ( fpsMonitor != null ) fpsMonitor . consoleText = str ;
402
428
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 ;
404
441
405
- isVideoRecording = true ;
442
+ if ( this != null && isActiveAndEnabled )
443
+ await FinishRecording ( ) ;
406
444
}
407
445
408
- private void StartMicrophone ( )
446
+ private void CancelRecording ( )
409
447
{
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 ) ;
417
453
}
418
454
419
- private async void StopRecording ( )
455
+ private async Task FinishRecording ( )
420
456
{
421
- if ( ! isVideoRecording )
457
+ if ( ! isVideoRecording || isFinishWriting )
422
458
return ;
423
459
424
- isVideoRecording = false ;
425
-
426
- Debug . Log ( "StopRecording ()" ) ;
427
-
428
- StopCoroutine ( "Countdown" ) ;
429
- if ( fpsMonitor != null )
430
- {
431
- fpsMonitor . consoleText = "" ;
432
- }
433
-
434
460
// Stop the microphone if we used it for recording
435
461
if ( recordMicrophoneAudio )
436
462
{
437
463
StopMicrophone ( ) ;
438
464
audioInput . Dispose ( ) ;
439
465
}
440
466
467
+ if ( fpsMonitor != null ) fpsMonitor . consoleText = "FinishWriting..." ;
468
+
441
469
// Stop recording
470
+ isFinishWriting = true ;
442
471
try
443
472
{
444
473
var path = await videoRecorder . FinishWriting ( ) ;
445
474
videoPath = path ;
446
475
Debug . Log ( "Saved recording to: " + videoPath ) ;
447
476
savePathInputField . text = videoPath ;
448
477
}
449
- catch ( Exception e )
478
+ catch ( ApplicationException e )
450
479
{
451
480
Debug . Log ( e . Message ) ;
452
481
savePathInputField . text = e . Message ;
453
482
}
483
+ isFinishWriting = false ;
484
+
485
+ if ( fpsMonitor != null ) fpsMonitor . consoleText = "" ;
454
486
455
487
ShowAllVideoUI ( ) ;
456
488
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 ) ;
457
514
}
458
515
459
516
private void StopMicrophone ( )
@@ -463,31 +520,22 @@ private void StopMicrophone()
463
520
Microphone . End ( null ) ;
464
521
}
465
522
466
- private IEnumerator Countdown ( )
523
+ private async Task CountdownAsync ( Action < int > countdownHandler , int sec = 10 , CancellationToken cancellationToken = default ( CancellationToken ) )
467
524
{
468
- float startTime = Time . time ;
469
- while ( ( Time . time - startTime ) < MAX_RECORDING_TIME )
525
+ for ( int i = sec ; i > 0 ; i -- )
470
526
{
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 ) ;
483
530
}
484
-
485
- StopRecording ( ) ;
531
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
532
+ countdownHandler ( 0 ) ;
486
533
}
487
534
535
+
488
536
private void PlayVideo ( string path )
489
537
{
490
- if ( isVideoPlaying || isVideoRecording || string . IsNullOrEmpty ( path ) )
538
+ if ( isVideoPlaying || isVideoRecording || isFinishWriting || string . IsNullOrEmpty ( path ) )
491
539
return ;
492
540
493
541
Debug . Log ( "PlayVideo ()" ) ;
@@ -517,7 +565,7 @@ private void PlayVideo(string path)
517
565
518
566
private void PrepareCompleted ( VideoPlayer vp )
519
567
{
520
- Debug . Log ( "PrepareCompleted" ) ;
568
+ Debug . Log ( "PrepareCompleted () " ) ;
521
569
522
570
vp . prepareCompleted -= PrepareCompleted ;
523
571
@@ -528,9 +576,7 @@ private void PrepareCompleted(VideoPlayer vp)
528
576
529
577
private void EndReached ( VideoPlayer vp )
530
578
{
531
- Debug . Log ( "EndReached" ) ;
532
-
533
- videoPlayer . loopPointReached -= EndReached ;
579
+ Debug . Log ( "EndReached ()" ) ;
534
580
535
581
StopVideo ( ) ;
536
582
}
@@ -542,16 +588,19 @@ private void StopVideo()
542
588
543
589
Debug . Log ( "StopVideo ()" ) ;
544
590
591
+ videoPlayer . loopPointReached -= EndReached ;
592
+
545
593
if ( videoPlayer . isPlaying )
546
594
videoPlayer . Stop ( ) ;
547
595
548
- gameObject . GetComponent < Renderer > ( ) . sharedMaterial . mainTexture = texture ;
549
-
550
- webCamTextureToMatHelper . Play ( ) ;
551
-
552
596
isVideoPlaying = false ;
553
597
554
- ShowAllVideoUI ( ) ;
598
+ if ( this != null && isActiveAndEnabled )
599
+ {
600
+ gameObject . GetComponent < Renderer > ( ) . sharedMaterial . mainTexture = texture ;
601
+ webCamTextureToMatHelper . Play ( ) ;
602
+ ShowAllVideoUI ( ) ;
603
+ }
555
604
}
556
605
557
606
private void ShowAllVideoUI ( )
@@ -717,20 +766,20 @@ public void OnRecordMicrophoneAudioToggleValueChanged()
717
766
/// <summary>
718
767
/// Raises the record video button click event.
719
768
/// </summary>
720
- public void OnRecordVideoButtonClick ( )
769
+ public async void OnRecordVideoButtonClick ( )
721
770
{
722
771
Debug . Log ( "OnRecordVideoButtonClick ()" ) ;
723
772
724
773
if ( isVideoPlaying )
725
774
return ;
726
775
727
- if ( isVideoRecording )
776
+ if ( ! isVideoRecording && ! isFinishWriting )
728
777
{
729
- StopRecording ( ) ;
778
+ await StartRecording ( ) ;
730
779
}
731
780
else
732
781
{
733
- StartRecording ( ) ;
782
+ CancelRecording ( ) ;
734
783
}
735
784
}
736
785
@@ -741,7 +790,7 @@ public void OnPlayVideoButtonClick()
741
790
{
742
791
Debug . Log ( "OnPlayVideoButtonClick ()" ) ;
743
792
744
- if ( isVideoPlaying || isVideoRecording || string . IsNullOrEmpty ( videoPath ) )
793
+ if ( isVideoPlaying || isVideoRecording || isFinishWriting || string . IsNullOrEmpty ( videoPath ) )
745
794
return ;
746
795
747
796
if ( System . IO . Path . GetExtension ( videoPath ) == ".gif" )
@@ -767,7 +816,7 @@ public void OnPlayVideoFullScreenButtonClick()
767
816
{
768
817
Debug . Log ( "OnPlayVideoFullScreenButtonClick ()" ) ;
769
818
770
- if ( isVideoPlaying || isVideoRecording || string . IsNullOrEmpty ( videoPath ) )
819
+ if ( isVideoPlaying || isVideoRecording || isFinishWriting || string . IsNullOrEmpty ( videoPath ) )
771
820
return ;
772
821
773
822
// Playback the video
@@ -788,7 +837,7 @@ public void OnShareButtonClick()
788
837
{
789
838
Debug . Log ( "OnShareButtonClick ()" ) ;
790
839
791
- if ( isVideoPlaying || isVideoRecording || string . IsNullOrEmpty ( videoPath ) )
840
+ if ( isVideoPlaying || isVideoRecording || isFinishWriting || string . IsNullOrEmpty ( videoPath ) )
792
841
return ;
793
842
794
843
using ( var payload = new SharePayload ( "NatCorderWithOpenCVForUnityExample" ,
@@ -810,7 +859,7 @@ public void OnSaveToCameraRollButtonClick()
810
859
{
811
860
Debug . Log ( "OnSaveToCameraRollButtonClick ()" ) ;
812
861
813
- if ( isVideoPlaying || isVideoRecording || string . IsNullOrEmpty ( videoPath ) )
862
+ if ( isVideoPlaying || isVideoRecording || isFinishWriting || string . IsNullOrEmpty ( videoPath ) )
814
863
return ;
815
864
816
865
using ( var payload = new SavePayload ( "NatCorderWithOpenCVForUnityExample" ,
0 commit comments