android - Using an arbitrary stream as a source for MediaPlayer -
android - Using an arbitrary stream as a source for MediaPlayer -
i utilize arbitrary inputstream info source mediaplayer object.
the reason inputstream using in fact authorized https connection media resource on remote server. passing url in case not work authentication required. can authentication separately , inputstream resource - problem do 1 time have it?
i thought alternative of using named pipe , passing filedescriptor setdataresource method of mediaplayer. there way create named pipes in android (without using ndk)?
any other suggestion welcome.
i think have found solution. appreciate if others interested seek on own , study results device models , sdk version.
i have seen similar posts direct thought post anyway since newer , seems work on newer versions of sdk - far works on nexus 1 running android 2.3.6.
the solution relies on bufferring input stream local file (i have file on external storage possible place on intenal storage well) , providing file's descriptor mediaplayer instance.
the next runs in doinbackground method of asynctask audioplayback:
@override protected void doinbackground(libraryitem... params) { ... mediaplayer player = new mediaplayer(); setlisteners(player); seek { _remotestream = getmyinputstreamsomehow(); file tempfile = file.createtempfile(...); tempfile.deleteonexit(); _localinstream = new fileinputstream(tempfile); _localoutstream = new fileoutputstream(tempfile); int buffered = buffermedia( _remotestream, _localoutstream, buffer_target_size // = 128kb instance ); player.setaudiostreamtype(audiomanager.stream_music); player.setdatasource(_localinstream.getfd()); player.prepareasync(); int streamed = 0; while (buffered >= 0) { buffered = buffermedia( _remotestream, _localoutstream, buffer_target_size ); } } grab (exception exception) { // handle errors see fit } homecoming null; }
the buffermedia method buffers nbytes bytes or until end of input reached:
private int buffermedia(inputstream instream, outputstream outstream, int nbytes) throws ioexception { final int buffer_size = 8 * (1 << 10); byte[] buffer = new byte[buffer_size]; // todo: static allocation instead int buffered = 0, read = -1; while (buffered < nbytes) { read = instream.read(buffer); if (read == -1) { break; } outstream.write(buffer, 0, read); outstream.flush(); buffered += read; } if (read == -1 && buffered == 0) { homecoming -1; } homecoming buffered; }
the setlisteners method sets handlers various mediaplayer events. of import 1 oncompletionlistener invoked when playback complete. in cases of buffer underrun (due to, say, temporary slow network connection) player reach end of local file , transit playbackcompleted state. identify situations comparing position of _localinstream against size of input stream. if position smaller, playback completed , reset mediaplayer:
private void setlisteners(mediaplayer player) { // set other listeners player.setonseekcompletelistener( new mediaplayer.onseekcompletelistener() { @override public void onseekcomplete(mediaplayer mp) { mp.start(); } } ); player.setoncompletionlistener( new mediaplayer.oncompletionlistener() { @override public void oncompletion(mediaplayer mp) { seek { long byteposition = _localinstream.getchannel().position(); int timeposition = mp.getcurrentposition(); int duration = mp.getduration(); if (byteposition < _track.size) { mp.reset(); mp.setdatasource(_localinstream.getfd()); mp.prepare(); mp.seekto(timeposition); } else { mp.release(); } } grab (ioexception exception) { // handle errors see fit } } } ); }
android pipe android-mediaplayer
Comments
Post a Comment