How to I create mediaplayer instance with inputstream?
I see only 4 function for setDataSource. And there is no function getting inputstream ?
is it a must to use FileDescriptor to mediaplayer ? It seems so basic. but, I couldnot find a way. In j2me, there is a function that Manager.createPlayer(InputStream). And you can use inputstream to create a media player. Is there a way to create a mediaplayer like j2me ?
How about making a HTTP server on the recieveing side (a thread on the phone) that outputs the data from the InputStream on any HTTP request to the OutputStream of the Socket and provide MediPlayer with URI http 127.0.0.1 : a port? THAT IS UGLY (but it should work)
it is also possible to play PCM uncompressed audio from an InputStream in android. goole it. if you can do decoding in software with JLayer or something and output it as PCMto the audio interface that should do the trick too but without hardware acceleration.
Pick your poison I guess. I chose option B.
One approach can be to write your stream to a File and then give it to the MediaPlayer for playback.
I'm looking into this right now (in order to send encrypted movie files to the MediaPlayer). Am I wrong in assuming the FileInputStream.getFD() is the solution to this? If you can get a FileDescriptor from a FileInputStream (unless you specifically need InputStream and not FileInputStream) then it seems like that can be passed right on to the MediaPlayer.
EDIT: Okay, so FileInputStream is created using a path or URL, making it useless.
You are correct, MediaPlayer will not take a stream parameter directly as its data source. The four overloaded versions of setDataSource() allow the data to come from a file (using the file path OR a FileDescriptor) or a Uri (web location or local content:// uri).
In addition, to static create() method can create a media player from a raw resource (R.raw.something) or the same style Uri as above.
Where are you sourcing the audio/video from other than either a file location or the web?
for now, I copy the InputStream to a temp file and give it to mediaplayer. but, you know, it s not good solution. because, it s slow solution. if data is big, player must wait too much.
my source is changing. for example, it s come from database. if I will not find solution, I convert my code to getting file. but, for now I desing the system to getting inputstream and play it. like, j2me function of MediaPlayer.createPlayer(InputStream,String)
I think you can get the file descriptor from your input stream and feed that to your setDataSource.
Related
I'd like to build something a little like the LiveEffect sample in the Google/Oboe library.
However, I want to affect the audio selected from a file chosen by the user rather than the microphone input. I do not need the input.
There's no example in the Google/Oboe repo of how to operate on a file.
Does anyone have an example or guidance so I can let the user choose a file from their local storage, then (and this is the bit I'm missing) pass the audio across the JNI bridge to my oboe app?
I do the need low-latency capability of Oboe as I'm going to affect the audio in response to motion data.
Any guidance gratefully recieved.
For anyone passing by in search of a similar solution, here's how I solved this
On the Java/Kotlin side pick up the audio file (i used a WAV in this
case) with an intent
Use a contentResolver on the audio file to create an inputStream
read the data from the inputStream into a byteArray
pass the byteArray over the JNI bridge to the native code
wrap the byteArray in a MemInputStream from the PARSELIB example
wrap the MemInputStream in a WavStreamReader, also from the PARSELIB example
create a SampleBuffer, from the IOLIB example, and load the WavStreamReader into it
create SampleSource, from the IOLIB example, and give it the SampleBuffer
give the SampleSource and SampleBuffer to the SimplePlayer from the IOLIB example
do the processing in the SampleSource's mixAudio() method bearing in mind all the rules for real-time processing in Oboe.
I also needed to do this on the block because I have a fixed window operation. to do this, I adapted the SampleBuffer class to add a method that would pull block data into mixAudio(), but that's only specific to some cases.
I hope that helps someone in the future.
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 need to implement a video DASH client for Android.
At this time I haven't find any solution except write the InputStream in a temp file and then read the file. Of course this solution is not efficient at all. I thought to use an OutputStream to use its FileDescriptor as the data source. But I'm not able to use a valid FileDescriptor without creating an existing file...
Because of the DASH protocol, the client has the charge of getting all the (little) segments, so I really need to find a way to read the media directly from the memory. Maybe the only solution is to use the JNI but I don't really know how.
To resume I'm open to every suggestions. The only constraints are :
At first I have an InputStream
Here it can be any intermediate operations but the more efficient as possible
Get a valid input to feed a MediaPlayer
That seems pretty basic but I can't found any way to achieve that. Thanks.
Derzu is correct that a local proxy can do this. See my answer here. Feel free to ask any questions.
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...