ExoPlayer: How to seek into just one of currently playing tracks? - android

I have an ExoPlayer instance initialized with 4 tracks. 2 of them are MediaCodecVideoTrackRenderer instances, each with its own ExtractorSampleSource.
I'd like to start the playback of one of those track from the middle.
I'm waiting until I get the MSG_PLAYER_STATE_READY message to be able to get the duration of the tracks and then calling seektoUs on the sample-source (also tried calling seekTo on the renderer), but both give unpredictable results.
What's the proper way to seek into a single track while the rest of the tracks play from the beginning?

Managed to solve the issue by overriding my custom TrackRenderer's doSomeWork method and calling super.doSomeWork with a custom positionUs based on the logic I needed.

Related

Is there a correct way to dispose/release the MediaStream object after displaying it in a RecyclerView?

I am attempting to display a list of MediaStream objects in a RecyclerView. Currently, my peer is giving me all of the MediaStream objects upon our initial handshake, and I am able to display them in a list view item that has a custom TextureView. The problem arises when I am given a large number of streams to scroll through. I eventually crash after scrolling through enough list items.
I have tried to use the MediaStream#dispose() function when my list item is being recycled. This seems to avoid the issue of using too many decoder resources, but it also makes the stream unable to be viewed again. If the user wants to scroll to a stream that has been disposed of, my app crashes with the exception MediaStreamTrack has been disposed. when trying to enable the MediaStream's VideoTrack.
I expected the combination of removing the sink from the video track videoTrack?.removeSink(cameraStreamView) as well as invoking the release() function on the EglRenderer within my TextureView would be enough to clean up the MediaStream in onViewRecycled().
private fun destroyCameraStream() {
videoTrack?.removeSink(cameraStreamView)
cameraStreamView.release()
}
fun release() {
eglRenderer.release()
}
However, after scrolling down the list far enough, I get the error:
Unable to instantiate codec 'OMX.qcom.video.decoder.avc' with err 0xfffffff4. I think this is due to the fact that I am not fully cleaning up and releasing my Codecs as I spin them up along the way, and I run out of resources.
Does anyone know if there is a certain function to call in order to correctly clean up MediaStream resources/the codecs used to decode them? Is there any documentation that talks about this type of situation?
Thanks!

ExoPlayer - get total duration with ConcatenatingMediaSource

I am trying to put together a seamless player using the ExoPlayer and ConcatenatingMediaSource. The general idea is:
I have a set of X short tracks (~15s each), kept in Assets
I load each of them into a ExtractorMediaSource
I put all of them into one ConcatenatingMediaSource
The solution works perfectly, but there is one flaw - ConcatenatingMediaSource seems to be loading media sources dynamically, not all at once.
This created a problem, because iterating Period objects from the Timeline to accumulate the total duration does not work. It will add up to X, but when the playback reaches a certain point, it will jump to X+15.
Any tips on how to get the total duration in this scenario?
i met the same problem before and here comes my solution:
extend a LoadControl
override a shouldContinueLoading returning true to make sure the ExoPlayerImplInternal keeps updating periods,so that the playlist would loaded at once.
i hope it helps

How can I set the seek point in a VideoView or otherwise quickly end playback?

Is there a way to set a video in a VideoView to the final second of its duration? Or trigger the onCompletionListener by code?
VideoView.seekTo(int milisec)
Attention, the unit of the parameter is in millisecond.
myVideoView.seekTo(myVideoView.getDuration())
If you have access to the instance of the class who implement the onCompletionListener, you can just manually call the function.
But I think it's quiet a bad idea; a callback should never be fired manually.
Having a quick view of the VideoView api there is a VideoView.seekTo(int msec) method. I would use that but then you will need to know the video length. That may be depending on your code, i'm not familiar with that. You might look it up or open a new question.

Seeker For Media Player

I would assume that someone would have found an easy solution to this but I haven't found a straight-forward method. I want to build a seeker bar for playing back audio through the MediaPlayer. I haven't been able to find something like an onSeekChanged listener in the MediaPlayer object so I've built an AsyncTask that just keeps refreshing through a while(playing) loop and updates the duration and bar. This doesn't seem to be the best way, however, since this while loop causes the app to run very slowly (the audio doesn't lag, but buttons like pause are delayed). So I want to know what the best implementation is for building a seeker that is efficient. This isn't a difficult question since so many apps use it, I just want to know what the proper way of doing this should be. Thanks!
First of all you need put sleep at least 1 millisecond in your cycle whit:
Thread.sleep(1);
Second you can calculate needed time for next recheck:
Thread.sleep(1000 - currentPos % 1000);
This algorithm is used in standard MediaController.

Two SurfaceHolders in one Activity

I want to play one RTSP stream in a surfaceView while I prepare the other in a separate thread. However, the MediaPlayer does give an error when instantiating two SurfaceHolders:
Command PLAYER_PREPARE completed with an error or info PVMFErrResource
Despite this, the video gets buffered, but when I switch to it, only audio is played. In the Android docs it is stated that this is a consequence of not calling setDisplay(SurfaceHolder) but this is what causes the error.
Does anyone have any idea how I can make the video part of the stream show and how to avoid the error when calling setDisplay? Is this a platform limitation?
Thanks.
Maybe you could put two separate SurfaceViews inside (for example) FrameLayout. Use these with two separate MediaPlayers and show/hide (in parallel to stoping/starting video) SurfaceView you desire at given moment (using android:visibility set to GONE for example).

Categories

Resources