I'm using an android MediaPlayer class right now for progressive audio streaming like this:
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(audioUrl);
mp.prepare();
mp.start();
But MediaPlayer class doesn't provide any caching, and I always need to do this routine: unnecessary network and battery waste
So, can someone help me find some library that will provide caching, because I couldn't find any. Thanks
There are not currently any libraries (that I am aware of) that do caching for you. You'll basically need to create a proxy that reads in the data and writes it back out to the media player. In the proxy you can write your own caching layer. It's not simple but it's currently the only way to cache data. You can see an example of a proxy (although it doesnt cache) from NPR here.
Looking my projects:
https://github.com/master255/ImmortalPlayer One thread to read, send and save to cache data. Most simplest way and most fastest work. Complex logic - best way!
https://github.com/master255/VideoViewCache Simple Videoview with cache. Two threads for play and save data. Bad logic, but if you need then use this.
Related
I guess small audio clips are necessary for many applications, thus I would expect QT have support playing mp3 in memory slices. Maybe decode mp3 data to wav data in memory may be one solution, but that needs time to decode all data first. For real time application, it is not a good idea. It also doesn't make sense to store mp3_data in a file and ask QMediaPlayer to play that, the performance is unacceptable.
This is my code after many searches by google, including stackoverflow:
m_buffer.setBuffer(&mp3_data_in_memory);
m_player.setMedia(QMediaContent(), &m_buffer);
m_player.play();
where m_buffer is a QBuffer instance, and mp3_data_in_memory is a QByteArray one; m_player is a QMediaPlayer instance.
I got some information that the code here doesn't work in MacOS and iOS, but I am running on Android now.
Does anyone have a solution for Android system? Thanks a lot.
Your code won't work because the media property requires a valid QMediaContent instance:
Setting this property to a null QMediaContent will cause the player to
discard all information relating to the current media source and to
cease all I/O operations related to that media.
There's also no way of telling the QMediaPlayer what format the data is in, you're just dumping raw data on it. In principle QMediaResource can hold this information, but it requires a url and is regarded as null without it.
As you may have guessed, QMediaPlayer and the related classes are high-level constructs not designed for this sort of thing. You need to use a QAudioDecoder to actually decode the raw data, and pipe the output to a QAudioOutput to hear it.
I have a video file that is encoded. For example the first bit of each byte is reversed. I want to read this video file, change the first bits and send the decoded result to Mediaplayer.
How can I do that? How can I create and pass this stream to media player without saving the decoded data on storage?
It is important that I do not want to save a decoded copy of my video and play it on media player. I want to play encoded video directly on mediaplayer using streams or other possible ways.
Short answer: NO, there is no way to do that (obviously by my point of view)
You cannot reproduce from a "custom" stream by manipulating the data just before passing it the MediaPlayer.
Why?
The official MediaPlayer API which is closest to the one needed to achieve your goal is the following:
MediaPlayer mp = new MediaPlayer();
FileInputStream fis = new FileInputStream(yourFile);
mp.setDataSource(fis.getFD());
//...
This snippet allows to play a file starting from a FileInputStream, but more precisely from the underlying FileDescriptor. The FileDescriptor is a class which is marked as final (and it is reasonable because it has to deal with the underlying OS), so you cannot override anything.
Possible workarounds?
As you already pointed out, you can try to modify the real file "in-place" while reproducing the video with the standard MediaPlayer (without creating a deep/separate copy of it): it's very tricky but plausible.
Try to use another player object: ExoPlayer (which is a new standard Android API) or Vitamio
Try a pure native solution (NDK + Android source), which I will not recommend ;)
UPDATE: detail about the 1st workaround
Assuming that "the first bit of each byte is reversed" you can use a FileChannel to manipulate the whole file "in-place" while reading it. You should use a FileChannels created from a RandomAccessFile created in mode "rw" in order to be able to read/write simultaneously.
This pre-elabaration task can run on a separated thread (or inside an IntentService, which is more fashion and reliable); you can wait for few seconds after the elaboration begins and then starting the playback by passing the File reference to the standard MediaPlayer (you need to tune this waiting period considering how fast is the elaboration, like a streaming buffering but easier because performance are almost stable).
In this way you don't need to wait the end of the pre-elaboration before starting the playback.
When the playback stops or you close the app, you need to undo your work by calling the same pre-elaboration task on the played file in order to restore it to its original state.
I hope that this hint can be useful.
Comments and precisations about my answer are welcome, I will update my post if I'll find more information.
Hello sages of the Overflowing Stack, Android noob here..
I'm using CSipSimple and want to stream the call audio to another app, in chunks of 1 second audio data so that it can process the raw pcm data.
The code that handles the audio in CSipSimple is native, so I prefer using native approaches and not callback Java.
I thought of a few ways of doing so:
Use audio streaming and let the other app get it.
Writing the data to a file and let the other app read it.
Calling a service in the other application (AIDL)
Using intents.
These are the considerations leading to my dillema:
Streaming looks like the natural choice, but I couldn't find Android support for retrieving raw pcm data from an an audio stream. The intent mechanism is flexible and convenient, but I don't think that that's what they're meant for. Using a file seems cumbersome, although it's well supported. Finally, using a service seems like a good option but it seems less flexible and probably needs more error handling and thread management.
Can you guys point out the best alternative?
If you have another one you're welcome to share it..
I do not know about the streaming audio API support so I'll not touch this case.
As for writing data to a file and let other application to read it - this is a possible case how to solve your problem.
As for calling service through AIDL and using intents, I do not think that this is a good solution. The problem is that Binder has a limitation over the size of the data (1MB) that can be passed in a transaction.
To my point of view, the best solution (especially if you're working in native) is to use AshMem. This is a shared memory driver developed specifically for Android. Thus, in your service you create a shared memory region and pass the reference to it into your client app that reads information from the this memory.
I have XOR'ed media files.
I want to play them with MediaPlayer class. Is it possible to decrypt media flow on the fly (and be able to rewind them)?
Shortly, I want to have all functionality of MediaPlayer class for XOR'ed media files.
Thanks in advance!
MediaPlayer may be too high level to accomplish this. I would suggest taking a look at AudioTrack. If you read your file in using an InputStream then you could XOR the data before feeding it to an AudioTrack instance. The only downfall to this approach is you will need to implement your own seek mechanism.
I'm attempting to stream from a URL using Android's built in MediaPlayer class. However, I also need to send a special header along with the URL. Is this possible without having to rewrite the whole steaming process?
If it's not possible to send a header, I would need to stream the file manually. However, it appears that the MediaPlayer class locks the file you are writing to when it begins reading the file. This means you cant just simply continue writing to the file while reading from it. I've seen the 'double buffer' method however that results in choppy playback. Any suggestions?
I asked a question recently about alternatives to the double buffer method you mentioned:
is-there-a-better-way-to-save-streamed-files-with-mediaplayer
I guess you could act as a proxy in a thread, handle your header and forward the rest to the media player? Or if you control the server pass the extra data in a different request...