Two SurfaceHolders in one Activity - android

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).

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: How to seek into just one of currently playing tracks?

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.

How to correct play RAW audio files with one Instance of MediaPlayer?

I don't think what is good but it's works.
I want know is it rigth what i do?
I have 2 files tick.wav and tock.wav wich must be played by timer tick or tock. setLooping not good because i need play by timer init.
So i try two methods:
First
I have variable MediaPlayer mp;
When i need play tick i call mp=MediaPlayer.create(context,tickID), when i need play tock i call mp=MediaPlayer.create(contenxt,tockID)
When i call mp.start();
Some time it's work good and i hear tick and tock, but then i start getting errors from mediaplayer. I think this because previous instance of MediaPlayer is still playing file.
Second
So i do next: i create two variables
tickPlayer=MediaPlayer.create(tickID);
and
tockplayer=MediaPlayer.create(tockID);
and then i need tock i call tockPlayer.start() when i need tick i call tickplayer.start()
I't works, but (always exists but) what me do if files will be more than 2, maybe 100?
Create array of mediaplayers like Vector<MediaPlayer> mpPlayers?
And call needed? I think it's eat my memory quickly.
So target is: i need correct playing files with shortime reaction of mediaplayer from RAW soruce, how ca i do what?
May be you don't need Vector to store media files, I think you can use java reflection to get information about "raw" resources as raw is static class from R.java.
And are you stopping media player. tickPlayer.stop().

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.

android -- wait for user input

I'm creating a spades app with 1 human player and 3 computer players.
The problem that I am having is, the play must happen sequentially (clockwise) and I need my program to wait on the player input. I can't use wait() and notify(). I have tried while loops to check whether the user has selected a card but those stop the program from running. I've tried recursive methods that won't return anything until the player has chosen a card. That too does not work. So what do I do? I'm stuck.
My method goes like this (leaving out the non-pertinent code)
private void game(){
while(there are more tricks to be played)
while(each player has not played){
if(human turn)
get input from player
else
computer plays
}
}
Maybe you should change a little bit your game controller. Instead of waiting for anything, have your program continuously paint the screen. If user inputs nothing, same screen is paint all the time.
Once he presses a key (or clicks a card or whatever events you have), simply modify the paint method's argument (the screen to be painted). Thus you will separate painting the screen and input handling. It's a common technique called MVC model.
Maybe this will help (it's my game creating blog, and the links inside it are also helpful):
http://m3ph1st0s.blogspot.ro/2012/12/create-games-with-libgdx-library-in.html
You don't need to adapt all your game to the game described there, only the technique of separating input from painting. As a general technique, you should NOT have input determine painting.
Hope it helps. Don't hesitate to request further help.
You can try to add Event Handlers. It will try triger a event every time the user selects a card.
Try this.
Create one thread and in that threat call sleep(1000);

Categories

Resources