2

I'm trying to pipe some ByteBuffer in a thread (IO1) to another (IO2).

http://tutorials.jenkov.com/java-nio/pipe.html

private int bufferSize;
private boolean isRecording;

private Thread IO1;
private Thread IO2;

private ByteBuffer byteBuffer1;
private ByteBuffer byteBuffer2;

private Pipe pipe;
private Pipe.SinkChannel skChannel;
private Pipe.SourceChannel sourceChannel;

            byteBuffer1 = ByteBuffer.allocateDirect(bufferSize);
            byteBuffer2 = ByteBuffer.allocateDirect(bufferSize);

            //An instance of Pipe is created
            try
            {
                pipe = Pipe.open();
                skChannel = pipe.sink();
                sourceChannel = pipe.source();

                IO1.start();
                IO2.start();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }

--

IO1 = new Thread(new Runnable()
{
    public void run()
    {
        isRecording = true;
        recorder.startRecording();
        try
        {
            int read;
            while (isRecording)
            {
               // byteBuffer1.clear();
                read = recorder.read(byteBuffer1, bufferSize);
                if (AudioRecord.ERROR_INVALID_OPERATION != read)
                {
                       skChannel.write(byteBuffer1);
                       Log.v("========IO1 ", String.valueOf(read));
                       //This triggered almost 20 times/second
                }
            }
            recorder.stop();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
});

skChannel.write(byteBuffer1); and Log.v("========IO1 ", String.valueOf(read)); is triggered almost 20 times/second, and this is the expected behavior, so far so good.

IO2 = new Thread(new Runnable()
{
    public void run()
    { 
        try
        {
            int read;
            while (  (read =sourceChannel.read(byteBuffer2)) >0)
            {
                Log.v("========IO2 ", String.valueOf(read));
                //this triggered only once

                // To do Codec etc.
                //............
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        } 
        Log.v("========IO2 ", "END!!!!!"); //never triggered(this is fine)
    }
});

However, Log.v("========IO2 ", String.valueOf(read)); is triggered only once, and I don't know why.

Can someone tell me how can I obtain the update of Thread IO1 in IO2?

Thanks.

1 Answers1

1

You need to flip() the buffer before writing, and compact() it afterwards.

BUT: In a word, don't. Pipes between threads are basically pointless. Use a queue, or have the receiving thread read the sending thread's input directly.

If you must do this, the basic NIO copy loop goes like this:

while (in.read(buffer) > 0 || buffer.position() > 0) // or whatever your read API needs
{
    buffer.flip();
    out.write(buffer);
    buffer.compact();
}
user207421
  • 305,947
  • 44
  • 307
  • 483
  • Thanks EJP, the reason I prepare another thread is I need to have MediaCodec loop. As you can see here http://developer.android.com/reference/android/media/MediaCodec.html it needs a specific (while) loop. In fact, I'm very confused how to implement this along with the AudioRecord loop thread. Do you still think Pipes between threads are pointless in this scenario? again, I am confused on this, so. –  Feb 17 '14 at 10:02
  • thank you. I quit to use bi-threads approach as you suggested, and getting closer to what I needed. I placed a new question for this: http://stackoverflow.com/questions/21804390/android-mediacodec-pcm-aac-encoder-pcmdecoder-in-real-time-with-correc and if you are interested in, please join. It's a +400 reputation bounty question. –  Feb 18 '14 at 03:25