Exoplayer View not able to find player.prepare() function - android

Currently I am facing a problem with the new version of Exoplayer. Below is the code used for player start. In getPlayerStart() I am passing url link. In initExoPlayer() I am initializing my Exoplayer but in earlier version of Exoplayer I am facing this problem:
mExoPlayerView!!.player.prepare(mVideoSource):
Above function is showing not available
private fun getPlayerStart(urlLink: String) {
if (playerMode) {
val userAgent = Util.getUserAgent(context, context!!.getApplicationInfo().packageName)
val httpDataSourceFactory = DefaultHttpDataSourceFactory(userAgent, null, DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, true)
val dataSourceFactory = DefaultDataSourceFactory(context, null, httpDataSourceFactory)
Log.i("Video",urlLink)
val daUri = Uri.parse(urlLink)
val extractorsFactory = DefaultExtractorsFactory()
mVideoSource = ExtractorMediaSource(daUri, dataSourceFactory,
extractorsFactory, null, null) as MediaSource?
}
initExoPlayer()
}
private fun initExoPlayer() {
val bandwidthMeter = DefaultBandwidthMeter()
val videoTrackSelectionFactory = AdaptiveTrackSelection.Factory(bandwidthMeter)
val trackSelector = DefaultTrackSelector(videoTrackSelectionFactory)
val loadControl = DefaultLoadControl()
player = ExoPlayerFactory.newSimpleInstance(DefaultRenderersFactory(context), trackSelector, loadControl)
mExoPlayerView!!.player= this.player
player!!.addListener(this)
mExoPlayerView!!.player.prepare(mVideoSource)
mExoPlayerView!!.getPlayer().playWhenReady = true
}

The prepare() method is part of the ExoPlayer interface which extends the Player interface.
The PlayerView only exposes the Player interface which does not have the prepare method. That's why you can't do mExoPlayerView!!.player.prepare(mVideoSource).
However, the ExoPlayerFactory, which you are using, does return a SimpleExoPlayer instance which does implement the ExoPlayer interface:
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(context), trackSelector, loadControl);
player.prepare(mediaSource);
Here are the class references of the ExoPlayer and Player interface, as well as the SimpleExoPlayer:
https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/Player.html
https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/ExoPlayer.html
https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/SimpleExoPlayer.html

Related

using ExoPlayer with kotlin

I want to use ExoPlayer using kotlin, I saw code for that but my compiler can't recognize 'buildRenderersFactory' reference.
Can someone help?
I'm using android studio
and implement:
def exoPlayerVersion = "2.9.0"
implementation "com.google.android.exoplayer:exoplayer:$exoPlayerVersion"
private val defaultBandwidthMeter = DefaultBandwidthMeter.Builder(context).build()
private val dataSourceFactory: DefaultDataSourceFactory
private val extractorsFactory = DefaultExtractorsFactory()
private val renderersFactory = buildRenderersFactory(useExtensionRenderers = true, preferExtensionRenderer = true)
val exoPlayer :SimpleExoPlayer = ExoPlayerFactory.newSimpleInstance(context, renderersFactory, DefaultTrackSelector(), DefaultLoadControl())
val dataSourceFactory = DefaultDataSourceFactory(context, defaultBandwidthMeter, DefaultHttpDataSourceFactory(Util.getUserAgent(context, "MKDPlayer"), defaultBandwidthMeter))
val mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory,extractorsFactory)
.setCustomCacheKey("ExoPlayerAdapter")
.createMediaSource(uri)
exoPlayer.prepare(mediaSource)
As Usama Altaf send me a link. The solution is using DefaultRenderersFactory constuctor.
so now it looks that way:
val renderersFactory = DefaultRenderersFactory(context)

ExoPlayer initialize player deprecated

I'm currently working with the latest ExoPlayer update and I'm getting calls that it is deprecated, could someone help me?
private fun initializePlayer () {
if (simpleExoPlayer == null) {
val trackSelector = DefaultTrackSelector(this)
val loadControl = DefaultLoadControl()
simpleExoPlayer = E̶x̶o̶P̶l̶a̶y̶e̶r̶F̶a̶c̶t̶o̶r̶y̶.̶n̶e̶w̶S̶i̶m̶p̶l̶e̶I̶n̶s̶t̶a̶n̶c̶e̶(this, trackSelector, loadControl)
}
}
Setting Up Exoplayer version(2.11.8) :
Sep 2020 Update:
//Setting Up Exoplayer
private void SetupPlayer(){
SimpleExoPlayer simpleExoPlayer;
// Create a data source factory.
dataSourceFactory =
new DefaultHttpDataSourceFactory(Util.getUserAgent(this
, getApplicationInfo().loadLabel(getPackageManager()).toString()));
// Passing Load Control
loadControl = new DefaultLoadControl.Builder()
.setBufferDurationsMs(25000, 50000, 1500, 2000).createDefaultLoadControl();
#DefaultRenderersFactory.ExtensionRendererMode int extensionRendererMode = DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER;
renderersFactory = new DefaultRenderersFactory(this) .setExtensionRendererMode(extensionRendererMode);
// Create a progressive media source pointing to a stream uri.
mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(url_to_stream));
// Create a player instance.
simpleExoPlayer = new SimpleExoPlayer.Builder(this,renderersFactory).setLoadControl(loadControl).build();
// Prepare the player with the media source.
simpleExoPlayer.prepare(mediaSource, true, true);
}
It's worked. You should use this version:
implementation 'com.google.android.exoplayer:exoplayer:2.18.2'
exoPlayer = ExoPlayer.Builder(this).build()
exoPlayer?.playWhenReady = true
binding.playerView.player = exoPlayer
val defaultHttpDataSourceFactory = DefaultHttpDataSource.Factory()
val mediaItem =
MediaItem.fromUri(URL)
val mediaSource =
HlsMediaSource.Factory(defaultHttpDataSourceFactory).createMediaSource(mediaItem)
exoPlayer?.setMediaSource(mediaSource)
exoPlayer?.seekTo(playbackPosition)
exoPlayer?.playWhenReady = playWhenReady
exoPlayer?.prepare()

How to play encrypted video in exoplayer (android app) coming from HLS streamer?

I am right now using FFMPEG to stream mp4 file using HLS.
I am using this link to enable encryption: https://hlsbook.net/how-to-encrypt-hls-video-with-ffmpeg/
To play video in my android app, I am using exoplayer, below is my source code to play video:
Player player;
private MediaSource buildMediaSource(Uri uri) {
TrackSelection.Factory adaptiveTrackSelection = new AdaptiveTrackSelection.Factory(new DefaultBandwidthMeter());
player = ExoPlayerFactory.newSimpleInstance(
this,
new DefaultTrackSelector(adaptiveTrackSelection));
playerView.setPlayer(player);
// These factories are used to construct two media sources.
DefaultBandwidthMeter defaultBandwidthMeter = DefaultBandwidthMeter.getSingletonInstance(this);
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(mContext,
Util.getUserAgent(mContext, "cookvid"), defaultBandwidthMeter);
//DataSource.Factory dataSourceFactory =
// new DefaultDataSourceFactory(this, "exoplayer-codelab");
HlsMediaSource.Factory mediaSourceFactory = new HlsMediaSource.Factory(dataSourceFactory);
return mediaSourceFactory.createMediaSource(uri);
//return new ProgressiveMediaSource.Factory(dataSourceFactory)
// .createMediaSource(uri);
}
private void initializePlayer() {
Uri uri = Uri.parse(getString(R.string.media_url_hls));
MediaSource mediaSource = buildMediaSource(uri);
player.setPlayWhenReady(playWhenReady);
player.seekTo(currentWindow, playbackPosition);
player.addListener(playbackStateListener);
player.prepare(mediaSource, false, false);
}
But with this code, I can not play video in app, If I am not using this encryption ,then exoplayer can play video without any issue.
Please help me on this, I am newbie on exoplayer side.
I created for you an example in Kotlin to make it work:
class MainActivity : AppCompatActivity() {
private var exoPlayer: SimpleExoPlayer? = null
private var trackSelector: DefaultTrackSelector? = null
var drmSessionManager: DefaultDrmSessionManager? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
trackSelector = DefaultTrackSelector(this)
exoPlayer = SimpleExoPlayer.Builder(this)
.setTrackSelector(trackSelector!!)
.build()
player_view.player = exoPlayer
var uri = Uri.fromFile( File("//android_asset/legend_enc.mp4"))
playVideo(uri, "zX65/4jzTK6wYYWwACTkwg", "Y8tfcYTdS2iaXF/xHuajKA")
}
private fun playVideo(url: Uri, id: String, value: String){
try {
drmSessionManager =
Util.getDrmUuid(C.CLEARKEY_UUID.toString())?.let { buildDrmSessionManager(
it,
true,
id,
value
) }
} catch (e: UnsupportedDrmException) {
e.printStackTrace()
}
exoPlayer?.setMediaSource(buildDashMediaSource(url))
exoPlayer?.prepare()
exoPlayer?.playWhenReady = true
}
private fun buildDashMediaSource(uri: Uri): MediaSource {
val dashChunkSourceFactory = DefaultDataSourceFactory(this, "agent")
return ProgressiveMediaSource.Factory(dashChunkSourceFactory)
.setDrmSessionManager(drmSessionManager ?: DrmSessionManager.DUMMY)
.createMediaSource(uri)
}
#Throws(UnsupportedDrmException::class)
private fun buildDrmSessionManager(uuid: UUID, multiSession: Boolean, id: String, value: String): DefaultDrmSessionManager {
val drmCallback = LocalMediaDrmCallback("{\"keys\":[{\"kty\":\"oct\",\"k\":\"${value}\",\"kid\":\"${id}\"}],\"type\":\"temporary\"}".toByteArray())
val mediaDrm = FrameworkMediaDrm.newInstance(uuid)
return DefaultDrmSessionManager(uuid, mediaDrm, drmCallback, null, multiSession)
}
}

Exoplayer error in Recyclerview, Source error None of the available extractors

I am using ExoPlayer to stream videos in a RecyclerView.
I am implementing the ExoPlayer inside my RecyclerView Adapter's bind method inside my ViewHolder.
The video format I am using is m3u8 and the URL I am using works in a browser.
So I know that the video link is valid. I've also testing a youtube link in there.
Here is the code from the Recyclerview adapter's ViewHolder ->
class ViewHolder private constructor(val binding: FeedRowBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(context: Activity){
if (entity.content.videolink != null) {
setupVideoPlayer(entity.content.videolink, context)
}
}
}
private fun setupVideoPlayer(url: String, context: Activity) {
val videoExoPlayer = SimpleExoPlayer.Builder(binding.videoView.context).build()
videoExoPlayer.prepare(createUrlMediaSource(url, context))
binding.play.setOnClickListener {
videoExoPlayer.playWhenReady = true
}
binding.pause.setOnClickListener {
videoExoPlayer.playWhenReady = false
}
}
private fun createUrlMediaSource(url: String, context: Activity): MediaSource {
val userAgent = Util.getUserAgent(context, context.getString(R.string.about))
return ProgressiveMediaSource
.Factory(DefaultDataSourceFactory(context, userAgent), DefaultExtractorsFactory())
.createMediaSource(Uri.parse(url))
}
When loading my recyclerview and get to the row with the video I get the following error:
ExoPlayerImplInternal: Source error.
com.google.android.exoplayer2.source.UnrecognizedInputFormatException:
None of the available extractors (MatroskaExtractor,
FragmentedMp4Extractor, Mp4Extractor, Mp3Extractor, AdtsExtractor,
Ac3Extractor, TsExtractor, FlvExtractor, OggExtractor, PsExtractor,
WavExtractor, AmrExtractor, Ac4Extractor, FlacExtractor) could read
the stream.
at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractorHolder.selectExtractor(ProgressiveMediaPeriod.java:1090)
at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:969)
at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:391)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
I'm not sure what am I doing wrong, any ideas on how to fix this issue?
You need to modify your createUrlMediaSource
private fun createUrlMediaSource(url: String, context: Activity): MediaSource {
val userAgent = Util.getUserAgent(context, context.getString(R.string.about))
return ProgressiveMediaSource
.Factory(DefaultDataSourceFactory(context, userAgent), DefaultExtractorsFactory())
.createMediaSource(Uri.parse(url))
}
as stated in https://exoplayer.dev
DashMediaSource for DASH.
SsMediaSource for SmoothStreaming.
HlsMediaSource for HLS (this is your format => .m3u8).
ProgressiveMediaSource for regular media files.
So you need to replace your function to this:
private fun createUrlMediaSource(url: String, context: Activity): MediaSource {
val userAgent = Util.getUserAgent(context, context.getString(R.string.about))
return HlsMediaSource
.Factory(DefaultDataSourceFactory(context, userAgent), DefaultExtractorsFactory())
.createMediaSource(Uri.parse(url))
}
I don't think m3u8 is a video format but rather a playlist format. I think Exoplayer is lower level than handling playlists; probably you need to read the m3u8 file yourself and then pass in the links in the playlist yourself.
Luckily the file format isn't complicated and it shouldn't be too difficult to parse. It seems it's pretty well documented. There's even some examples on Wikipedia: https://en.wikipedia.org/wiki/M3U
On Android 4.1+, you can use this library https://github.com/brianwernick/ExoMedia/ . The example mentioned on the Read-me page should be sufficient to get you started. I have reproduced that code snippet with a few additions/modifications.
private void setupVideoView() {
EMVideoView emVideoView = (EMVideoView)findViewById(R.id.video_play_activity_video_view);
emVideoView.setOnPreparedListener(this);
//Enter your m3u8 URL below
emVideoView.setVideoURI(Uri.parse("http://SOMESERVER/playlist.m3u8"));
}
#Override
public void onPrepared(MediaPlayer mp) {
//Starts the video playback as soon as it is ready
emVideoView.start();
}
#Override
public void onPause() {
super.onPause();
//Pause Video Playback
emVideoView.pause();
}
For streaming .m3u8 file use below code while initializing Exoplayer:-
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
videoPlayer = ExoPlayerFactory.newSimpleInstance(context,trackSelector);
Handler mHandler = new Handler();
String userAgent = Util.getUserAgent(context, "Exo Player");
DataSource.Factory dataSourceFactory = new DefaultHttpDataSourceFactory(
userAgent, null,
DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
1800000,
true);
HlsMediaSource mediaSource = new HlsMediaSource(Uri.parse(mediaUrl),dataSourceFactory, 1800000,mHandler, null);
if (mediaUrl != null) {
videoPlayer.prepare(mediaSource);
videoPlayer.setPlayWhenReady(true);
}

Exoplayer2 Streaming HLS Videos , Sometimes plays video with sound only(video not played)

I implement exoplayer2 in my app for playing HLS Videos, but sometimes it plays just sound, and doesn't work correctly. What am I supposed to do? I couldn't find why this happens sometimes.
this is the code for initializing player :
fun initPalyer(){
val mainHandler = Handler()
val bandwidthMeter: BandwidthMeter = DefaultBandwidthMeter.Builder(context).build()
bandwidthMeter.addEventListener(mainHandler!!, this)
val trackSelectionFactory: TrackSelection.Factory = AdaptiveTrackSelection.Factory()
trackSelector = DefaultTrackSelector(context, trackSelectionFactory)
val builder = ParametersBuilder(context)
trackSelectorParameters = builder.build()
trackSelector!!.parameters = trackSelectorParameters
var rendersFactory: RenderersFactory = app.buildRenderersFactory(false)
player = SimpleExoPlayer.Builder(
context, renderersFactory
)
.setTrackSelector(trackSelector!!)
.setBandwidthMeter(bandwidthMeter)
//.setLoadControl(loadControl)
.build()
player!!.addListener(this)
loadState()
playerView.player = player!!
}
the code for preparing player :
private fun preparePlayer(uri: Uri) {
val mediaSource = MediaSourceBuilder().build(uri)
durationSet = false
player?.prepare(mediaSource, true, false)
}
and the code for creating mediaSources :
class MediaSourceBuilder {
//Build various MediaSource depending upon the type of Media for a given video/audio uri
fun build(uri: Uri): MediaSource {
val userAgent = PlayerConstants.USER_AGENT
val lastPath = uri.lastPathSegment?:""
val defaultHttpDataSourceFactory = DefaultHttpDataSourceFactory(userAgent)
if(lastPath.contains(PlayerConstants.FORMAT_MP3) || lastPath.contains(PlayerConstants.FORMAT_MP4)){
return ExtractorMediaSource.Factory(defaultHttpDataSourceFactory)
.createMediaSource(uri)
}else if(lastPath.contains(PlayerConstants.FORMAT_M3U8)){
return HlsMediaSource.Factory(defaultHttpDataSourceFactory)
.setAllowChunklessPreparation(true)
.createMediaSource(uri)
}else{
val dashChunkSourceFactory = DefaultDashChunkSource.Factory(defaultHttpDataSourceFactory)
return DashMediaSource.Factory(dashChunkSourceFactory, defaultHttpDataSourceFactory)
.createMediaSource(uri)
}
}
You might wanna change your DataSourceFactory, in case your URL are in HTTPS you might end up with an error, try using DefaultDataSourceFactory instead of DefaultHttpDataSourceFactory

Categories

Resources