RenderHeads / UnityPlugin-AVProVideo

AVPro Video is a multi-platform Unity plugin for advanced video playback
https://www.renderheads.com/products/avpro-video/
235 stars 28 forks source link

Android Behavioral Differences in v3 #1809

Closed yasirkula closed 3 months ago

yasirkula commented 6 months ago

Describe the issue After having major issues with v3 on Android, I've downgraded to v2.9.3 and can confirm that the following issues arrived with v3.0.0:

  1. Calling MediaPlayer.OpenMedia with autoPlay=false option doesn't trigger FirstFrameReady event on v3 but it does on v2.9.3. I've tried calling Seek, Play followed by Pause, ExtractFrame in ReadyToPlay event to trigger that event to no avail in v3. It seems impossible to display the initial frame of the video after opening it on v3.
  2. I handle loops manually by calling Seek(0) inside FinishedPlaying event (i.e. MediaPlayer's Loop option is disabled). This works flawlessly in v2.9.3 but on v3, this event is triggered shortly after the ReadyToPlay event (even though the video hasn't been started yet and hasn't even rendered yet, i.e. FirstFrameReady event not triggered). When I call Play and the video actually starts playing, FinishedPlaying event is no longer triggered.

PS. Using ExoPlayer.

Your Setup (please complete the following information):

To Reproduce

  1. On both v2.9.3 and v3.0.0, call OpenMedia with autoPlay=false and observe that FirstFrameReady isn't invoked in v3.0.0
  2. On v3.0.0, observe that FinishedPlaying is invoked after ReadyToPlay event even though FirstFrameReady hasn't been triggered. Then, call Play. FinishedPlaying event won't trigger after the video actually finishes playing
Last8Exile commented 5 months ago

I got weird problem after upgrading to v3. On Android after I call Seek() to any position I receive FinishedPlaying event almost immediatly and app closes video. In v2 this in not happenning and seek working as expected.

Chris-RH commented 5 months ago

I'm not seeing this. Can you reproduce this in a fresh project using only AVPro Video mediaplayer demo scene?

Last8Exile commented 5 months ago

I emailed reproduction project to unitysupport@renderheads.com

Chris-RH commented 5 months ago

I'm getting a FinishedSeeking event. It continues to play fine though.

Last8Exile commented 5 months ago

Yes. Player is working after seek.

But we getting FinishedPlaying event and MediaPlayer.Control.IsFinished() returns true after Seek is completed. Video is nowhere near it completion. So event is missfired and MediaPlayer.Control.IsFinished() should return false.

Described behaviour visible on reproduction video. Last GUI button with "Finished" text represents _mediaPlayer.Control.IsFinished() in your demo.

We tested this on devices: Quset 2, Quest 3 (Android 12), Redmagic 9 Pro, Pixel 6a (Android 14) It is happening both with remote (https://) and local (/storage) videos.

I attached debugger and Finished comes from Native.AVPPlayerGetState(_player, ref _state); in PlatformMediaPlayer. I can't debug deeper because it ends up in precompiled C plugin.

Last8Exile commented 5 months ago

I managed to workaround this issue by ignoring FinishedPlaying event and MediaPlayer.Control.IsFinished() method and implementing custom completion detection using MediaPlayer.Control.HasMetaData(), MediaPlayer.Control.GetCurrentTime() and MediaPlayer.Info.GetDuration()

Chris-RH commented 5 months ago

It works fine in Android mediaplayer, so it must be something to do with the switch over from Exoplayer to AndroidXMedia3

yasirkula commented 5 months ago

I'm not seeing this. Can you reproduce this in a fresh project using only AVPro Video mediaplayer demo scene?

I've set Auto Open, Auto Play and Loop to false in the Demo_MediaPlayer scene and added _mediaPlayer.OpenMedia(false); to MediaPlayerUI.Start function. Then built the scene to my Android device.

  1. FirstFrameReady event wasn't called in the following scenarios until I clicked the play button: a) doing nothing, b) calling Seek(0) in ReadyToPlay event, c) calling ExtractFrame(null, 0) in ReadyToPlay event. Calling Play followed by Pause worked in the example scene but the video didn't actually pause, it continued playing.
  2. Apparently Seek was the key factor here as @Last8Exile said. If I call Seek, FinishedPlaying is invoked immediately and won't be called at the end of the video.
aracid commented 5 months ago

I've been encountering a recurring issue that seems tied to specific software versions. Previously, everything was functioning perfectly on version 2.#.# of the software. However, after upgrading to version 3.0.0, I've noticed that seeking within a video triggers the FinishedPlaying event prematurely. This issue only surfaced after the transition to version 3.0.0.

I am currently using AVPro Video v3.0.0 with the native plugin also updated to v3.0.0-ultra. The platform specifics include an Adreno (TM) 740 GPU running Vulkan 1.1.0 [512.767.0], with multithreading enabled, on an Android system. My development environment is Unity 2022.3.20f1, and I'm streaming an MP4 file directly from AWS.

What's also interesting is that once the video has concluded that it "FinishedPlaying" from seeking, it wont trigger that event until a new video has played.

This can be validated by attaching this to a generic scene, connect the mediaplayer to the component MediaEvents.zip

With the seek active, mediaPlayer.Control.Seek(position); this event doesn't run at the end of the video MediaPlayerEvent.EventType.FinishedPlaying

With the seek INactive, MediaPlayerEvent.EventType.FinishedPlaying works as expected.

Interestingly, this problem seems to be isolated to the Android platform, specifically on the Quest 3 headset. I do not encounter this issue when running the same setup on a Windows system.

I hope this helps

WikkidEdd commented 4 months ago

I attached debugger and Finished comes from Native.AVPPlayerGetState(_player, ref _state); in PlatformMediaPlayer. I can't debug deeper because it ends up in precompiled C plugin.

@Last8Exile this goes through to the AVProVideo.jar as you observed in #1811. Digging through the Player_Base.PlayerRenderUpdate there is a bit where it's setting the flags for the state the player is in. Note that the bit being set for m_bFinishedSeeking is the same as for IsFinished so finishing seeking sets the IsFinished flag. Hence the false positive when seeking finishes.

    if (IsPlaying())
      i = bool | 0x2; 
    if (IsPaused())
      i |= 0x4; 
    if (IsFinished())
      i |= 0x8; 
    if (IsSeeking())
      i |= 0x10; 
    if (IsBuffering())
      i |= 0x20; 
    if (this.m_bFinishedSeeking)
      i |= 0x8; 
    if (GetVideoTracksDirty() || GetAudioTracksDirty() || GetTextTracksDirty())
      i |= 0x10000;
Ste-RH commented 3 months ago

This should be fixed in v3.0.2 (penciled in for release by the end of the week)

Chris-RH commented 3 months ago

AVPro Video version 3.0.2 has been released. Please let us know if it has not fixed your issue.