2012-10-15 12 views
22

Próbuję opracować przykład nagrywania dźwięku, a pamięć danych jest obsługiwana przez aplikację, a nie MediaRecorder. Przypadki użycia obejmują przechowywanie nagrania w pamięci wewnętrznej lub szyfrowanie nagrania.Ktoś ma MediaRecorder Praca z ParcelFileDescriptor i createPipe()?

W zasadzie to powinno działać przy użyciu rury utworzonej przez createPipe() na ParcelFileDescriptor, ale jestem coraz wyjście nieprawidłowy.

Najpierw here is a sample project który rejestruje „naturalnie” za pomocą MediaRecorder z MediaRecorder pisząc bezpośrednio do pliku wyjściowego na pamięci zewnętrznej. Ta aplikacja działa dobrze, a dane wyjściowe mogą być odtwarzane przez urządzenie z Androidem, które je nagrało lub VLC na moim komputerze z systemem Linux.

Here is my createPipe() variation of this project. Z punktu widzenia ogólnej konfiguracji MediaRecorder (np. setOutputFormat()), jest taka sama jak pierwsza, więc kod jest prawdopodobnie poprawny.

Jestem jednak dostarczanie wyjście poprzez:

recorder.setOutputFile(getStreamFd()); 

Gdzie getStreamFd() wykorzystuje createPipe(), spawns wątek tła do czytania z rury, i zwraca się do końca pisania dla wykorzystania przez 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 to klasyczna procedura kopiowania strumieniowego do strumienia, wzbogacona o sprytne elementy do wypróżniania i synchronizowania pliku wyjściowego:

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); 
     } 
    } 
    } 

Po uruchomieniu drugiej aplikacji otrzymuję plik wyjściowy, który w wyniku surowej inspekcji za pomocą edytora szesnastkowego wydaje się być w zasadzie prawidłowy. IOW, to nie jest plik zero-bajtowy lub jest wypełniony nierozpoznawalnym bełkotem. Jest wypełniony podobnym bełkotem, podobnie jak wyjście z pierwszej aplikacji. Jednak ani Android, ani VLC nie mogą go odtworzyć.

Gdybym miał zgadywać, to przypuszczam, że jestem przekręcane coś w czytaniu z rury, ale nie jestem pewien, gdzie specjalnie jadę źle.

Wszelkie sugestie?

Z góry dziękuję!

+0

FWIW mam powiązane pytanie na temat używania 'createPipe()' 'MediaPlayer' z: http://stackoverflow.com/questions/12920429/anyone-have-mediaplayer-working-with-parcelfiledescriptor-and-createpipe – CommonsWare

+0

Czy rozwiązałeś ten problem? – Teocci

+0

@Teocci: Nie. "ProxyFileDescriptorCallback" Androida O * może * pomóc tutaj, ale tylko na Androidzie O i wyższym. Zasadniczo, rury nie dają widocznych strumieni. – CommonsWare

Odpowiedz

13

Przypuszczam, że jest to związane z moją odpowiedzią na inne pytanie. Anyone Have MediaPlayer Working with ParcelFileDescriptor and createPipe()?

Prawdopodobnie, gdy MediaRecorder będzie próbował zapisać informacje w nagłówku, rura zostanie zamknięta.

Jeśli używasz:

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

Rekord działa dobrze, bo nie będzie miał informacje nagłówka, tylko surowy dźwięk.

+1

Aha! To rzeczywiście działa, a twoje wyjaśnienie ma sens. Wielkie dzięki! – CommonsWare

+0

Próbuję użyć tego do stworzenia strumienia wejściowego dla aplikacji do nagrywania wideorejestracji, ale nie jestem pewien, skąd pochodzi twój strumień wejściowy, co dokładnie przekazałeś dla swojego strumienia wejściowego? jakakolwiek pomoc byłaby długa –