9

I know it is possible to use TextureView in ExoPlayer. But I cannot find any sample on how to implement this functionality in a proper way. Could you please help me on this issue?

Elnur Hajiyev
  • 464
  • 1
  • 4
  • 14

3 Answers3

18

The PlayerView has an xml attribute surface_type which let's you choose whether you want to use a SurfaceView or a TextureView.

(Note: SimpleExoPlayerView has been renamed to PlayerView in recent versions since it only depends on the Player interface and not on SimpelExoPlayerView anymore.)

You can choose texture_view, surface_view (default) or none. See the main section of the JavaDoc of PlayerView for details.

<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/player_view"
     app:surface_type="texture_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"/>
marcbaechinger
  • 2,759
  • 18
  • 21
6

From the documentation:

If you require fine-grained control over the player controls and the Surface onto which video is rendered, you can set the player’s target SurfaceView, TextureView, SurfaceHolder or Surface directly using SimpleExoPlayer’s setVideoSurfaceView, setVideoTextureView, setVideoSurfaceHolder and setVideoSurface methods respectively.

So the relevant part here would be the setVideoTextureView(). Something like:

SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
TexturView textureView = findViewById(texture_view);
player.setVideoTextureView(textureView);

You can also create a Surface from a SurfaceTexture which you can get through TextureView's setSurfaceTextureViewListener(). See TextureView's documentation and this post. And then you could call setSurface(...) on the player.

But you shouldn't really need to do this anymore now that SimpleExoPlayer has the TextureView setter (we didn't always have this in old ExoPlayer). Also as another reference, here's the issue on ExoPlayer about supporting this.

As a side note, you can see the differences between SurfaceView and TextureView here. The general recommendation is to use a SurfaceView, but there are nuances.

[EDIT]

If you want to do it on the fly, you can instantiate the SimpleExoPlayer (not SimpleExoPlayerView) like I've written above, and then call setPlayer(...) on your PlayerView (which you could have defined in XML or dynamically).

If you don't need to set the surface/texture view on the fly, then you can just set it on the PlayerView in the layout XML via app:surface_type="texture_view".

Kyle Venn
  • 4,597
  • 27
  • 41
  • Kyle Venn, thank you for your answer. I tried it, but if I use raw TextureView instead of SimpleExoPlayer, I can't benefit from ExoPlayer's advantages, such as playback controls, fixed aspect ratio etc. Should I code those features myself if I choose to use TextureView? Btw, I have to use TextureView, because user should be able to drag player view like on Youtube, and SurfaceView does not give smooth result below Nougat. – Elnur Hajiyev Mar 25 '18 at 18:14
  • You should be able to use `SimpleExoPlayer` _with_ `TextureView` like in my example. Do you mean `SimpleExoPlayerView`? If you're using that, you can call `setPlayer()` on the `PlayerView` and ensure that the player already has the `TextureView` set on it. Does that make sense? – Kyle Venn Mar 25 '18 at 18:21
  • Kyle Venn, yes, I meant SimpleExoPlayerView. I have just tried your solution. Video is shown in SimpleExoPlayerView. But when I start to drag it, the video get replaced by black screen and does not return to normal until I restart the player fragment. – Elnur Hajiyev Mar 25 '18 at 18:33
  • I placed TextureView before SimpleExoPlayerView and there is no more black screen issue. Unfortunately, there is still rendering lag while drag animation is performing as when using SurfaceView. So, there is no use of TextureView in this case. Do we do it wrong? – Elnur Hajiyev Mar 25 '18 at 18:40
  • 1
    Actually, when reading the question, Kyle's answer is more accurate then mine. :) Not sure whether it would make sense to change the question to "with PlayerView of ExoPlayer" which apparently was the intended question. Thanks both. – marcbaechinger Mar 25 '18 at 22:18
  • 1
    Yes, this would be a more accurate title for the question. Changed it. – Elnur Hajiyev Mar 26 '18 at 14:43
  • If SimpleExoPlayerView is being deprecated, can we use PlayerView type of the activity manifest layout file? And if that is the case how would I go about setting SurfaceView or TextureView on the fly before i play the video? I currently do the following just to accommodate: playerView = findViewById((shouldUseWorkaround() ? R.id.surface_view : R.id.texture_view)); playerView.setPlayer(player); My playerView is a SimpleExoPlayerView and now I want to change it to PlayerView. Update: it seems I cannot set the surface type on the fly, unless I set in the activity layout `app:surface_type=""`? – petrosmm May 11 '18 at 02:19
  • @petersmm I just edited my answer to include how to set it on the fly still using `PlayerView`. – Kyle Venn May 11 '18 at 20:17
  • @KyleVenn I have updated my code and it complains that `com.google.android.exoplayer2.ui.PlayerView cannot be cast to android.view.TextureView` pastebin.com/rnB7DANr has the code. – petrosmm May 11 '18 at 22:29
  • @KyleVenn it seems after a short time, this worked... https://pastebin.com/pGcGf5Ep. Not only did it work but I no longer require using a workaround for certain known boards when using `PlayerView` instead of `SimpleExoPlayerView`. It worked straight out of the box which I was not able to do with the simpleview. Any thoughts? – petrosmm May 11 '18 at 22:49
  • 1
    `PlayerView` defaults to using a `SurfaceView` which, generally, shouldn't require a work around. So if it works, then you should be good to go just using the `SurfaceView`. – Kyle Venn May 14 '18 at 20:35
3

Note, TextureView can only be used in a hardware accelerated window. When rendered in software, TextureView will draw nothing. so after set surface type

<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/player_view"
 app:surface_type="texture_view"
 android:layout_width="match_parent"
 android:layout_height="match_parent"/>

you need to make sure that hardware acceleration is enabled, go to manifest file and ad this line

  • At application level: <application android:hardwareAccelerated="true" ...>
Mostafa Anter
  • 3,445
  • 24
  • 26