4
votes

I am developing a low data rate VoIP kind of project . I need to capture audio at low data rates and store it in an internal buffer or FIFO (NOT in a file).

I would like to use low data rate .AMR encoders, which means AudioRecord is out. MediaRecorder looks like it does exactly what I want except that it seems to write to a file.

MediaRecorder takes a FileDescriptor... is there any way I can write a class that implements the FileDescriptor interface... acting as a sync for bytes... but instead of sending them to a file they are stored in a buffer? The documentation on FileDescriptor specifically says that Applications shouldn't write their own but why not and is it possible anyway?

http://docs.oracle.com/javase/1.4.2/docs/api/java/io/FileDescriptor.html

In short, I'd like to develop my own stream, and trick MediaRecorder to send data to it. Perhaps doing something tricky with opening both ends of a socket within the same APK and giving MediaRecorder the socket to write to? Using the socket as my FIFO? I'm somewhat new to this so any help/suggestions greatly appreciated.

I have a related question on the RX side. I'd like to have a buffer/fifo that feeds MediaPlayer. Can I trick MediaPlayer to accept data from a buffer fed by my own proprietary stream?

1

1 Answers

4
votes

I know its a bit late to answer this question now... ...But if it helps here's the solution.

Android MediaRecorder's method setOutputFile() accepts FileDescriptor as a parameter. As for your need a unix data pipe could be created and its FD could be passed as an argument in the following manner...

mediaRecorder.setOutputFile(getPipeFD());

FileDescriptor getPipeFD()
{
    final String FUNCTION = "getPipeFD";
    FileDescriptor outputPipe = null;

    try
    {
        ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
        outputPipe = pipe[1].getFileDescriptor();
    }
    catch(Exception e)
    {
        Log.e(TAG, FUNCTION + " : " + e.getMessage());
    }

    return outputPipe;
}

The ParcelFileDescriptor.createPipe() creates a Unix Data Pipe and returns an array of ParcelFileDescriptors. The first object refers to the read channel (Source Channel) and the second one refers to the write channel (Sink Channel) of the pipe. Use MediaRecorder object to write the recorded data to the write channel...

As far as MediaPlayer is concerned the same technique could be used by passing the FileDescriptor object related to the created pipe's read channel to the setDataSource() method...