{"action":"opened","issue":{"url":"https://api.github.com/repos/google/ExoPlayer/issues/1520","repository_url":"https://api.github.com/repos/google/ExoPlayer","labels_url":"https://api.github.com/repos/google/ExoPlayer/issues/1520/labels{/name}","comments_url":"https://api.github.com/repos/google/ExoPlayer/issues/1520/comments","events_url":"https://api.github.com/repos/google/ExoPlayer/issues/1520/events","html_url":"https://github.com/google/ExoPlayer/issues/1520","id":154116540,"number":1520,"title":"MediaCodecVideoTrackRenderer inconsistently reporting isEnded so onPlaybackStateChange STATE_ENDED does not occur","user":{"login":"moagrius","id":701344,"avatar_url":"https://avatars.githubusercontent.com/u/701344?v=3","gravatar_id":"","url":"https://api.github.com/users/moagrius","html_url":"https://github.com/moagrius","followers_url":"https://api.github.com/users/moagrius/followers","following_url":"https://api.github.com/users/moagrius/following{/other_user}","gists_url":"https://api.github.com/users/moagrius/gists{/gist_id}","starred_url":"https://api.github.com/users/moagrius/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/moagrius/subscriptions","organizations_url":"https://api.github.com/users/moagrius/orgs","repos_url":"https://api.github.com/users/moagrius/repos","events_url":"https://api.github.com/users/moagrius/events{/privacy}","received_events_url":"https://api.github.com/users/moagrius/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2016-05-10T21:58:43Z","updated_at":"2016-05-10T21:58:43Z","closed_at":null,"body":"Great work, great library, thanks for all your hard work.\r\n\r\n**A description of the issue itself.**\r\n\r\nThis was first discovered when using `ExoPlayer` and backgrounded cideo (audio continues to play in a `Service` while the `Activity` is paused).  We found that on most devices, the `onPlaybackStateChange` callback for `STATE_ENDED` was not called when the `Activity` was paused, but would fire as soon as the `Activity` resumed.  On some devices (e.g., HTC One X 4.1.1), `STATE_ENDED` happened as expected, even with the `Activity` backgrounded/paused.\r\n\r\nFor example:\r\n\r\n1.  Create an `Activity` that has a `TextureView`.\r\n2.  Create a `Service` that creates an `ExoPlayer` instance.\r\n3.  Start the `Service` from the `Activity`, setting the surface of the `ExoPlayer` to the `TextureView`.  Attach a `Listener` to the `ExoPlayer` that logs out state changes.\r\n4.  Play any video.\r\n5.  Allow the video to get near the end, then hit the HOME button.\r\n6.  The audio continues, but the `onPlaybackStateChange` callback for `STATE_ENDED` does not fire (on most devices).\r\n7.  Resume the `Activity` (select it from the multi-task / app switcher).\r\n8.  The `onPlaybackStateChange` callback for `STATE_ENDED` will now fire as the `Activity` resumes.\r\n\r\nThe cause is:\r\n\r\n1.  `ExoPlayerImplInternal` calls `doSomeWork`, where it checks if each renderer is \"done\" by calling `isEnded` on each renderer.  If all renderers report that they're ended (and meet some other conditions), it fires `onPlaybackStateChange` with `STATE_ENDED`.\r\n2.  `MediaCodecTrackRenderer`'s `isEnded` method returns `outputStreamEnded`, which is apparently not set to `true` in most devices, for `MediaCodeVideoTrackRenderer` instances, if there is not a surface to send to.  When the surface is replaced, it correctly (and immediately) reports `outputStreamEnded`/`isEnded` to be true, so `doSomeWork` does indeed call `onPlaybackStateChange` to `STATE_ENDED`.\r\n\r\n**Steps describing how the issue can be reproduced, ideally in the ExoPlayer demo app.**\r\n\r\n1.  Create an app using a VideoPlaybackActivity https://gist.github.com/moagrius/4732021bf4ca5c8957b9e8a15429e2a5\r\n and a BackgroundAudioService https://gist.github.com/moagrius/f2ca1d2d5c451d8b862304e46caf69f1\r\n2.  Add a video to assets.  Update the path in VideoPlaybackActivity to that video.\r\n3.  Run the VideoPlaybackActivity.\r\n4.  Allow the video to get near the end, then hit the HOME button.\r\n5.  The audio continues, but the onPlaybackStateChange callback for STATE_ENDED does not fire (on most devices).\r\n6.  Resume the Activity (select it from the multi-task / app switcher).\r\n7.  The onPlaybackStateChange callback for STATE_ENDED will now fire as the Activity resumes.\r\n8.  Comment out or remove the line that set the surface to `null` in `VideoPlaybackActivity.onSurfaceTextureDestroyed`\r\n9.  Repeat steps 3 and 4.  Now, since the surface was not made unavailable to the video renderer, the `onPlaybackStateChange` will fire for `STATE_ENDED` _while the Activity is paused_.\r\n\r\n**If the issue only reproduces with certain content, a link to some content that we can use to reproduce. If you don’t wish to post a link publicly, please send the link by email to dev.exoplayer@gmail.com, including the issue number in the subject line.**\r\n\r\nn/a\r\n\r\n**The version of ExoPlayer being used.**\r\n\r\n1.5.7\r\n\r\n**The device(s) and version(s) of Android on which the issue can be reproduced, and how easily it reproduces. Does it happen every time, or only occassionally? If possible, please test on multiple devices and Android versions. If the issue does not reproduce on some combinations, that’s useful information!**\r\n\r\nWe've tested on multiple devices, including Nexus 5, Nexus 6, Nexus 7, Samsung Galaxy 6, and HTC One X.  So far, only the HTC One X on 4.1.1 did _not_ exhibit the behavior (the video track renderer ended with or without a surface to draw too).  It is predictable and reproducible (it _never_ happens on the HTC One X, and _always_ happens on the other devices).\r\n\r\n**A full bug report taken from the device just after the issue occurs, attached to the issue as a file. A bug report can be captured from the command line using adb bugreport > bugreport.txt. Note that the output from adb logcat or a log snippet is typically not sufficient.**\r\n\r\nn/a\r\n\r\n**Anything else you think might be relevant!**\r\n\r\nThe proper way to get around this is to re-use the `SurfaceTexture`, so that it's always available to the `MediaCodeVideoTrackRenderer`, even if it's not onscreen, and `return false` from `onSurfaceTextureDestroyed` so that it is not released.  That said, the behavior described above does seem like it could be corrected to behave like I think most users would expect (the audio renderer correctly reported when it had ended, which is when the \"media item\" as a single entity had concluded - I believe it should have reported `STATE_ENDED` at that time).\r\n\r\nThanks, and let me know if you need any more information."}}