Search Unity

Bug VideoPlayer (iOS): texture freeze after resume app suspended.

Discussion in 'Audio & Video' started by GHSmediaSrl, Dec 16, 2020.

  1. GHSmediaSrl

    GHSmediaSrl

    Joined:
    Dec 2, 2015
    Posts:
    12
    Unity 2020.1
    Platform: iOS (tested with iOS 14)

    Component: VideoPlayer https://docs.unity3d.com/2020.1/Documentation/ScriptReference/Video.VideoPlayer.html
    Render Mode: Material Override, Render Texture
    Audio Output: Audio Source

    My project use VideoPlayer to reproduce videos from streamingassets folder (via URL).

    I got problem when the App resumes after went to suspended state: video keep stuck but the audio come back to play.
    I tried to log the VideoPlayer state with OnApplicationPause and I found that the video "isPlaying" property was "true" when app resumed even tought video frame keep freezed.

    Here the code:
    Code (CSharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using UnityEngine;
    5. using UnityEngine.Video;
    6. [RequireComponent(typeof(VideoPlayer))]
    7. public class VideoManager : MonoBehaviour
    8. {
    9.     public event Action OnVideoEnd;
    10.     public void Dispatch_OnVideoEnd() { if (OnVideoEnd != null) OnVideoEnd(); }
    11.     #region Serialization
    12. #pragma warning disable 0649
    13.     [SerializeField] string m_filename;
    14.     [SerializeField] public bool Auto_Play;
    15.     [SerializeField] public bool Loop = true;
    16.     [SerializeField] public bool MultiTrackVideo = true;
    17. #pragma warning restore 0649
    18.     #endregion
    19.     Renderer _renderer;
    20.     VideoPlayer _mediaPlayer;
    21.     bool _isPlaying;
    22.     public bool isPlaying { get { return _mediaPlayer != null && _mediaPlayer.isPlaying; } }
    23.     public bool isPrepared { get { return _mediaPlayer != null && _mediaPlayer.isPrepared; } }
    24.     #region Unity + Init
    25.     // ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
    26.     // ■■■ UNITY + INITIALIZATION        
    27.     void Awake()
    28.     {
    29.         _renderer = this.GetComponent<Renderer>();
    30.         _mediaPlayer = this.GetComponent<VideoPlayer>();
    31.         _mediaPlayer.source = VideoSource.Url;
    32.         _mediaPlayer.playOnAwake = false;
    33.         _mediaPlayer.isLooping = Loop;
    34.         _mediaPlayer.loopPointReached += _mediaPlayer_loopPointReached;
    35.     }
    36.     void Start()
    37.     {
    38.         Activate(false);
    39.         if (Auto_Play)      
    40.             Play();      
    41.     }
    42.     void OnDestroy()
    43.     {
    44.         this.StopAllCoroutines();
    45.     }
    46. #if UNITY_IPHONE
    47.     bool _wasplaying = false;
    48.     void OnApplicationPause(bool pause)
    49.     {
    50.         Debug.LogFormat("OnApplication pause:{0} - _isPlaying:{1} - _wasPlaying:{2}", pause, _isPlaying, _wasplaying);
    51.         //going pause
    52.         if (pause)
    53.         {
    54.             _wasplaying = _isPlaying;
    55.             if (_wasplaying)
    56.                 _mediaPlayer.Pause();
    57.         }
    58.         else
    59.         {
    60.             if (_wasplaying)
    61.                 this.StartCoroutine(PlayCoroutine());
    62.             _wasplaying = false;
    63.         }
    64.     }
    65. #endif
    66.     #endregion
    67.     #region METHODS
    68.     // ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
    69.     // ■■■  METHODS
    70.     public void Activate(bool doActivate)
    71.     {
    72.         if (_renderer != null)
    73.             _renderer.enabled = doActivate;
    74.         _mediaPlayer.enabled = doActivate;
    75.     }
    76.     public void Play(string filename)
    77.     {
    78.         if (isPlaying)
    79.             return;
    80.         Activate(true);
    81.         this.StopAllCoroutines();
    82.         _mediaPlayer.url = System.IO.Path.Combine(Application.streamingAssetsPath, filename);
    83.         this.StartCoroutine(PlayCoroutine());
    84.     }
    85.     public void Play()
    86.     {
    87.         this.Play(m_filename);
    88.     }
    89.     private IEnumerator PlayCoroutine()
    90.     {
    91.         var audioSource = _mediaPlayer.GetComponent<AudioSource>();
    92.         if (audioSource == null) audioSource = _mediaPlayer.gameObject.AddComponent<AudioSource>();
    93.         _mediaPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;
    94.         _mediaPlayer.controlledAudioTrackCount = (ushort)(MultiTrackVideo ? 2 : 1);      
    95.         _mediaPlayer.Prepare();
    96.         // Wait until ready
    97.         while (!_mediaPlayer.isPrepared)
    98.             yield return null;
    99.         _mediaPlayer.Play();
    100.         _isPlaying = true;
    101.     }
    102.     public void Stop()
    103.     {
    104.         _mediaPlayer.Stop();
    105.         _isPlaying = false;
    106.     }
    107.     #endregion
    108.     #region Callbacks
    109.     // ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
    110.     // ■■■  Callbacks  
    111.     private void _mediaPlayer_loopPointReached(VideoPlayer source)
    112.     {
    113.         //this.Dispatch_OnVideoEnd();
    114.     }
    115.     #endregion
    116. }
    117.  
    118.  

    Any ideas?
     
  2. marvpaul

    marvpaul

    Joined:
    May 9, 2016
    Posts:
    32
    I'm facing the same problem for the VideoPlayer component with other settings on iOS. One thing you could do is stopping the video on suspend. This is not the exact solution but for me it is the best I can came up with.

    Code (CSharp):
    1. private void OnApplicationPause(bool pause) {
    2.             if(GameObject.Find("GameManager").GetComponent<ConfigManager>().settingsObj["sections"]["Background"]["Background"]["current"]["name"] == "Video"){
    3.                 if(pause){
    4.                     Camera.main.GetComponent<UnityEngine.Video.VideoPlayer>().Stop();
    5.                 } else {
    6.                     StartCoroutine("startVideo");
    7.                 }  
    8.             }
    9.     }
    10.  
    11.     IEnumerator startVideo(){
    12.         Debug.Log("Loading video");
    13.         UnityEngine.Video.VideoPlayer videoPlayer = Camera.main.GetComponent<UnityEngine.Video.VideoPlayer>();
    14.         videoPlayer.Prepare();
    15.         while (!videoPlayer.isPrepared && GameObject.Find("GameManager").GetComponent<ConfigManager>().settingsObj["sections"]["Background"]["Background"]["current"]["name"] == "Video") {
    16.             yield return new WaitForEndOfFrame();
    17.         }
    18.        
    19.         videoPlayer.Play();
    20.         PlayerPrefs.SetInt("videoLoaded", 1);
    21.         Resources.UnloadUnusedAssets();
    22.     }