У кого-нибудь есть MediaRecorder, работающий с ParcelFileDescriptor и createPipe()?
Я пытаюсь разработать пример записи звука, с приложением, а не с хранилищем данных. MediaRecorder
, Варианты использования включают хранение записи во внутреннем хранилище или шифрование записи.
В принципе, это должно работать с использованием трубы, созданной createPipe()
на ParcelFileDescriptor
, но я получаю искаженный вывод.
Во-первых, вот пример проекта, который записывает "естественно", используя MediaRecorder
, с MediaRecorder
запись непосредственно в выходной файл на внешнем хранилище. Это приложение работает просто отлично, и вывод может быть воспроизведен либо устройством Android, записавшим его, либо VLC на моем компьютере с Linux.
Вот мой createPipe()
Вариация этого проекта. С точки зрения общего MediaRecorder
конфигурация (например, setOutputFormat()
), он такой же, как и первый, так что код предположительно правильный.
Тем не менее, я поставляю вывод через:
recorder.setOutputFile(getStreamFd());
куда getStreamFd()
использования createPipe()
, порождает фоновый поток для чтения из канала и возвращает конец записи для использования 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
это классика java.io
подпрограмма копирования из потока в поток, дополненная смарт-кодами для очистки и синхронизации выходного файла:
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);
}
}
}
Когда я запускаю второе приложение, я получаю выходной файл, который, по грубой проверке через шестнадцатеричный редактор, кажется в принципе нормальным. IOW, это не похоже на файл с нулевым байтом или заполнен неузнаваемым бредом. Он наполнен подобным тарабарством, как в первом приложении. Тем не менее, ни Android, ни VLC не могут играть в нее.
Если бы мне пришлось угадывать, я бы предположил, что я что-то напутал в чтении с канала, но я не уверен, где конкретно я ошибаюсь.
Какие-либо предложения?
Заранее спасибо!
1 ответ
Я предполагаю, что это связано с моим ответом на ваш другой вопрос. У кого-нибудь есть MediaPlayer, работающий с ParcelFileDescriptor и createPipe()?
Возможно, когда MediaRecorder попытается записать информацию заголовка, канал будет закрыт.
Если вы используете:
recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
Запись работает нормально, потому что она не будет иметь информацию заголовка, только сырой звук.