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.
Related
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.
I am trying to stream incoming AMR_NB. I can't use MediaPlayer directly because it requires a seekable file. I would like to use MediaCodec, but to use MediaCodec I need (I think... please correct me!) MediaExtractor to give me things like the presentationTime. Is that true? Can I use MediaCodec without MediaExtractor?
MediaExtractor seems to require seekable files. The documentation only specifically says so for one of the setDataSource operations but when I tried to use any of the others it failed due to failed seek attempts.
So, what can I do to get my incoming AMR stream to play? I am aware of a scheme where by you save incoming data to a file and periodically make a copy of that file to feed to MediaPlayer but I'd really prefer to find a real honest streaming solution.
Is it possible to use MediaCodec without using MediaExtractor? If so how do I find presentation time and the string to pass to MediaCodec.createDecoderByType? The documentation SAYS that "audio/3gpp" is what I want but when I attempt to use that I get the following error:
codec = MediaCodec.createDecoderByType("audio/3gpp");
01-02 03:59:36.980: E/OMXMaster(21605): A component of name 'OMX.qcom.audio.decoder.aac' already exists, ignoring this one.
So I'm not sure how to get at MediaCodec either.
"I can't use MediaPlayer directly because it requires a seekable file" This is not generally true. I would like you to try it on your stream and report exactly what happens.
"Can I use MediaCodec without MediaExtractor?" I doubt it: I believe they are designed to be used together.
I have used these components to play streams. However, the MediaExtractor has limitations that are not documented ( as far as I know ). So use a little proxy server to feed it things it can digest. And I have 1 thread to run the MediaExtractor and another to take output from the the MediaCodec. Then i have to avoid deadlocks and cope with snchronization. But it is not that bad provided you just want to play forwards only. Then you have only the problem of how to stop!
I advise that you try MediaPlayer first. Otherwise, if you are keen enough to try the MediaExtractor, we could share our discoveries about what it will and wont digest. Don't take anything for granted. For example it seems it will play my MP3 files, but cannot discover their duration, or seek on them!
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.
I am making a game which will be using questions stored on a mp3, so for each question there will be a mp3 file.
The user will then press play to hear the mp3 and then add an answer for the mp3 in an edittext field. Which would then show correct or incorrect answer.
When the user clicks confirm answer the mp3 will move to the next question. So when the user presses play it will be question 2. Is it possible to do this and if so how would I go about implementing this. I would highly appreciate any advice on this.
Thanks.
It is recommended to use WAV or OGG format for sounds on Android, but in any case, you can play back your MP3s with the MediaPlayer class. For example:
MediaPlayer mp = MediaPlayer.create(YourActivityClass.this, R.raw.your_mp3_resource);
if(mp != null) {
mp.start();
}
Read the documentation regarding state and calling release() on finished MediaPlayer objects. Alternatively use one MediaPlayer object with the setDataSource() and prepare() methods.
Right now, you can use SoundPool or MediaPlayer
Both support mp3, but based on my experience, SoundPool will not always play Mp3 of more than 100kb. For those files you will have to use MediaPlayer.
One link comparing both.
Is it possible to get track name while playing radio stream via MediaPlayer?
I would say pretty much with certainty - no, it isn't possible.
I can't see any MediaPlayer methods which suggest it's possible plus the way that metadata such as track name etc is presented in streaming media, will depend on the source, e.g, Shoutcast or otherwise.
If it can be done I'd be interested to know but I'd suspect you'd need to write something like a Shoutcast client (or other client depending on source). You'd still use MediaPlayer for streaming but would need extra code for accessing the metadata.