任何人都有MediaRecorder使用ParcelFileDescriptor和createPipe()?

Com*_*are 22 android android-mediarecorder

我试图找出一个录制音频的例子,数据存储由应用程序处理,而不是MediaRecorder.用例包括将记录存储在内部存储器或加密记录.

原则上,这应该使用createPipe()on 创建的管道ParcelFileDescriptor,但我得到输出格式错误.

首先,这是一个示例项目,使用"自然"记录MediaRecorder,MediaRecorder直接写入外部存储上的输出文件.这个应用程序工作得很好,输出可以由记录它的Android设备或我的Linux机器上的VLC播放.

这是我createPipe()对这个项目的变化.从一般MediaRecorder配置(例如setOutputFormat())的角度来看,它与第一个相同,因此代码可能是正确的.

但是,我通过以下方式提供输出:

  recorder.setOutputFile(getStreamFd());
Run Code Online (Sandbox Code Playgroud)

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());
  }
Run Code Online (Sandbox Code Playgroud)

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);
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

当我运行第二个应用程序时,我得到一个输出文件,通过十六进制编辑器的粗略检查,似乎基本上没问题.IOW,它不像是一个零字节文件,或者充满了无法识别的乱码.它充满了与第一个应用程序的输出类似的乱码.但是,Android和VLC都无法播放它.

如果我不得不猜测,我会认为我从管道中读取了一些东西,但我不知道具体到哪里我出错了.

有什么建议?

提前致谢!

luc*_*ofm 13

我猜这与我对你的另一个问题的答案有关. 任何人都有MediaPlayer使用ParcelFileDescriptor和createPipe()?

可能当MediaRecorder试图写入标题信息时,管道将关闭.

如果您使用:

recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
Run Code Online (Sandbox Code Playgroud)

该记录工作正常,因为它不会有标题信息,只有原始音频.