user1028880
user1028880

Reputation:

Android Media Player Fails With Local Socket, and what is the workaround to play streaming data for VoiceChat?

I made a simple test to make MediaPlayer play some live streaming data via localSocket.

    class IOLoop extends Thread
    {
        @Override
        public void run()
        {
            try
            {
                MediaPlayer mPlayer = new MediaPlayer();
                mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                System.out.println("----======MediaPlayer()============-- ");
                LocalSocket receiver = new LocalSocket();
                System.out.println("----======new LocalSocket()============-- ");
                FileDescriptor fd = receiver.getFileDescriptor();
                System.out.println("----fd============-- ");

                    mPlayer.setDataSource(fd);  //<-- error
                    mPlayer.prepare();

                System.out.println("----=========mPlayer set===============-- ");

            }
            catch (IOException e)
            {//
            }
        }
    }

    IOLoop io00 = new IOLoop();
    io00.start();

This code fails, with IllegalArgumentException

02-14 05:16:46.418  20424-20436/com.example.app I/System.out﹕ ----fd============--
02-14 05:16:46.426  20424-20436/com.example.app W/dalvikvm﹕ threadid=10: thread exiting with uncaught exception (group=0xa61ea908)
02-14 05:16:46.426  20424-20436/com.example.app E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-197
    java.lang.IllegalArgumentException
            at android.media.MediaPlayer.setDataSource(Native Method)
            at android.media.MediaPlayer.setDataSource(MediaPlayer.java:976)
            at com.example.app.MainActivity$1IOLoop.run(MainActivity.java:51)

so googled.

Basically, they say LocalSocket FileDescriptor is not seekable so not adequate for the data source.

However, according to AndroidDeveloper-Media Playback

http://developer.android.com/guide/topics/media/mediaplayer.html

It clearly stated:

The Android multimedia framework includes support for playing variety of common media types, so that you can easily integrate audio, video and images into your applications. You can play audio or video from media files stored in your application's resources (raw resources), from standalone files in the filesystem, or from a data stream arriving over a network connection, all using MediaPlayer APIs.

So, it's a strange situation.

Also, there is voice chat apps like LINE etc. What is the workaround?

Any thought? Thank you.


EDIT:

found a similar topic:

Can I use MediaPlayer play video from stream line

How do you play Android InputStream on MediaPlayer?

Play AAC buffer on Android

https://code.google.com/p/aacdecoder-android/

What a mess..


EDIT2

This is a real good project to illustrate these area.

https://github.com/fyhertz/libstreaming

I think MediaCodec is the way to go instead of MediaRecorder etc.

Upvotes: 3

Views: 3114

Answers (2)

marcone
marcone

Reputation: 329

When using the version of MediaPlayer.setDataSource() that takes a FileDescriptor, MediaPlayer expects that file descriptor to be a regular seekable file. A socket is not seekable.

The "data stream arriving over a network connection" bit you quoted from the documentation refers to http/rtsp streaming, so you can either point it at a remote server URL, or implement a local server and then do something like mPlayer.setDataSource("http://localhost:12345")

Upvotes: 0

sam
sam

Reputation: 83

Don't use media player. Just take in the microphone input and send it to the client who is at the receiver end of the voice chat. For example to send the voice:

protected String doInBackground() throws Exception {
AudioFormat af = new AudioFormat(8000.0f,8,1,true,false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, af);
TargetDataLine microphone = (TargetDataLine)AudioSystem.getLine(info);
microphone.open(af);
Socket conn = new Socket(SERVER,3000);
microphone.start();
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
int bytesRead = 0;
byte[] soundData = new byte[1];
Thread inThread = new Thread(new SoundReceiver(conn));
inThread.start();
while(bytesRead != -1)
{
    bytesRead = microphone.read(soundData, 0, soundData.length);
    if(bytesRead >= 0)
    {
        dos.write(soundData, 0, bytesRead);
    }
}
    // TODO Auto-generated method stub
    return null;
}

}

To receive the voice:

   public SoundReceiver(Socket conn) throws Exception
      {
    connection = conn;
    soundIn = new DataInputStream(connection.getInputStream());
    AudioFormat af = new AudioFormat(8000.0f,8,1,true,false);
    DataLine.Info info = new DataLine.Info(SourceDataLine.class, af);
    inSpeaker = (SourceDataLine)AudioSystem.getLine(info);
    inSpeaker.open(af);
}

public void run()
{
    int bytesRead = 0;
    byte[] inSound = new byte[1];
    inSpeaker.start();
    while(bytesRead != -1)
    {
        try{bytesRead = soundIn.read(inSound, 0, inSound.length);} catch (Exception e){}
        if(bytesRead >= 0)
        {
            inSpeaker.write(inSound, 0, bytesRead);
        }
    }
}

Upvotes: 1

Related Questions