I am trying to work out an example of recording audio, with the data storage being handled by the app, not MediaRecorder
. Use cases include storing the recording on internal storage or encrypting the recording.
In principle, this should work using a pipe created by createPipe()
on ParcelFileDescriptor
, but I am getting malformed output.
First, here is a sample project that records "naturally" using MediaRecorder
, with MediaRecorder
writing directly to an output file on external storage. This app works just fine, and the output can be played either by the Android device the recorded it or VLC on my Linux box.
Here is my createPipe()
variation of this project. From the standpoint of general MediaRecorder
configuration (e.g., setOutputFormat()
), it is the same as the first, so that code is presumably correct.
However, I am supplying the output via:
recorder.setOutputFile(getStreamFd());
Where getStreamFd()
uses createPipe()
, spawns a background thread to read from the pipe, and returns the writing end for use by MediaRecorder
:
private FileDescriptor getStreamFd() {
ParcelFileDescriptor[] pipe=null;
try {
pipe=ParcelFileDescriptor.createPipe();
new TransferThread(new AutoCloseInputStream(pipe[0]),
new FileOutputStream(getOutputFile())).start();
}
catch (IOException e) {
Log.e(getClass().getSimpleName(), "Exception opening pipe", e);
}
return(pipe[1].getFileDescriptor());
}
TransferThread
is a classic java.io
stream-to-stream copy routine, augmented with smarts to flush and sync the output file:
static class TransferThread extends Thread {
InputStream in;
FileOutputStream out;
TransferThread(InputStream in, FileOutputStream out) {
this.in=in;
this.out=out;
}
@Override
public void run() {
byte[] buf=new byte[8192];
int len;
try {
while ((len=in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.flush();
out.getFD().sync();
out.close();
}
catch (IOException e) {
Log.e(getClass().getSimpleName(),
"Exception transferring file", e);
}
}
}
When I run the second app, I get an output file that, by crude inspection via a hex editor, seems basically OK. IOW, it's not like it's a zero-byte file, or is filled with unrecognizable gibberish. It is filled with a similar sort of gibberish as is the output from the first app. However, neither Android nor VLC can play it.
If I had to guess, I would presume that I am screwing up something in reading from the pipe, but I am not sure where specifically I am going wrong.
Any suggestions?
Thanks in advance!
See Question&Answers more detail:
os