2012-10-15 27 views
22

我正在嘗試制定一個記錄音頻的例子,數據存儲由應用程序處理,而不是MediaRecorder。使用情況包括將記錄存儲在內部存儲器上或加密記錄。任何人都有MediaRecorder使用ParcelFileDescriptor和createPipe()?

原則上,這應該使用createPipe()ParcelFileDescriptor上創建的管道工作,但我得到格式錯誤的輸出。

首先,here is a sample project使用MediaRecorder記錄「自然」,而MediaRecorder直接寫入外部存儲器上的輸出文件。這個應用程序工作得很好,輸出可以通過Android設備錄製,也可以通過我的Linux機器上的VLC播放。

Here is my createPipe() variation of this project。從通用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都不能播放它。

如果我不得不猜測,我會假設我搞砸了一些從管道中讀取的東西,但我不確定具體哪裏出錯。

有什麼建議嗎?

在此先感謝!

+0

FWIW,我有一個關於在'MediaPlayer'中使用'createPipe()'的相關問題:http://stackoverflow.com/questions/12920429/anyone-have-mediaplayer-working-with-parcelfiledescriptor-and-createpipe – CommonsWare

+0

你解決了這個問題嗎? – Teocci

+0

@Teocci:不,Android O的'ProxyFileDescriptorCallback' *可能會在這裏有所幫助,但僅限於Android O及更高版本。基本上,管道不會產生可尋求的流。 – CommonsWare

回答

13

我想這與我對你的其他問題的回答有關。 Anyone Have MediaPlayer Working with ParcelFileDescriptor and createPipe()?

可能在MediaRecorder試圖寫入Header信息時,管道關閉。

如果你使用:

recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR); 
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 

記錄工作正常,因爲它不會有一個頭信息,只有原始音頻。

+1

啊哈!這確實有效,你的解釋是有道理的。非常感謝! – CommonsWare

+0

我試圖用這個來創建一個videorecording應用程序的輸入流,但我不知道你的輸入流來自哪裏,你爲輸入流準確傳遞了什麼?任何幫助都會帶來很大的幫助 –

相關問題