2014-11-18 6 views
19

Ich teste libstreaming auf neue Android Lollipop, und dieser Code, der auf früheren Release arbeitete, scheint Ausnahme zu starten.MediaRecorder Problem auf Android Lollipop

try { 
     mMediaRecorder = new MediaRecorder(); 
     mMediaRecorder.setCamera(mCamera); 

     mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
     mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
     mMediaRecorder.setVideoEncoder(mVideoEncoder); 
     mMediaRecorder.setPreviewDisplay(mSurfaceView.getHolder().getSurface()); 
     mMediaRecorder.setVideoSize(mRequestedQuality.resX,mRequestedQuality.resY); 


     mMediaRecorder.setVideoFrameRate(mRequestedQuality.framerate); 

     // The bandwidth actually consumed is often above what was requested 

     mMediaRecorder.setVideoEncodingBitRate((int)(mRequestedQuality.bitrate*0.8)); 

     // We write the ouput of the camera in a local socket instead of a file !   
     // This one little trick makes streaming feasible quiet simply: data from the camera 
     // can then be manipulated at the other end of the socket 

     mMediaRecorder.setOutputFile(mSender.getFileDescriptor()); 

     mMediaRecorder.prepare(); 
     mMediaRecorder.start(); 

    } catch (Exception e) { 
     throw new ConfNotSupportedException(e.getMessage()); 
    } 

gestartet Ausnahme ist:

MediaRecorder: Start fehlgeschlagen -38

11-18 09:50:21.028: W/System.err(15783): net.majorkernelpanic.streaming.exceptions.ConfNotSupportedException 
11-18 09:50:21.028: W/System.err(15783): at net.majorkernelpanic.streaming.video.VideoStream.encodeWithMediaRecorder(VideoStream.java:442) 
11-18 09:50:21.028: W/System.err(15783): at net.majorkernelpanic.streaming.MediaStream.start(MediaStream.java:250) 

Ich habe versucht zu kommentieren:

mMediaRecorder.setOutputFile(mSender.getFileDescriptor()); 

keine Ausnahme gestartet, aber wenn ich starten Streaming eines Dialogs sag mir, dass eine Ausgabedatei benötigt wird.

Hilfe geschätzt.

+0

Ich denke, ich bekomme einen ähnlichen Fehler. Ich versuche, in einen lokalen Socket zu schreiben, um auch Audio/Video zu streamen, bekomme aber nach dem -38 Fehler E/StagefrightRecorder: Der Ausgabedateideskriptor ist ungültig. Laut https://android.googlesource.com/platform/frameworks/av/+/master/media/libmediaplayerservice/StagefrightRecorder.cpp der Fehler Ausgaben in Zeile 752. Wenn der Dateideskriptor kleiner als 0 ist, bedeutet -1 der Standard-Sentinel-Wert Außer dass ich verifiziere, dass ich den Deskriptor als 136 setze, bevor ich die Ausgabedatei setze. – sbaar

+0

welche Android Version verwenden Sie? – andreasperelli

+0

Dieses Problem betrifft nur Lollipop. Derselbe Code auf demselben Nexus 5 und demselben Nexus 7 Gerät funktionierte, als sie auf Kitkat waren. Ich bin mir jetzt ziemlich sicher, dass das Problem etwas mit Sockets zu tun hat, aber ich versuche immer noch herauszufinden, was sich geändert haben könnte. – sbaar

Antwort

22

Ich habe einen Fehlerbericht über AOSP eingereicht. https://code.google.com/p/android/issues/detail?id=80715

„Die aktuellen SELinux-Richtlinien erlauben keine Medienserver App generierte abstrakte Unix Domain Sockets behandelt.

Stattdessen würde ich empfehlen Sie ein Rohr-Paar (http://developer.android.com/reference/android/os/ParcelFileDescriptor.html#createPipe()) zu schaffen, die durch die erlaubt ist Android 5.0 Richtlinie. " Ich weiß nicht, warum sie das getan haben oder wie wir wissen sollten.

Ich benutze eine sehr alte/modifizierte (kann nicht sagen) Version von libstreaming, wo mediastream noch von mediarecorder erweitert wird, aber mit Blick auf die aktuelle Version, in MediaStream werden Sie wahrscheinlich createSockets zu etwas einschließlich ändern die folgenden:

 ParcelFileDescriptor[] parcelFileDescriptors =ParcelFileDescriptor.createPipe(); 
     parcelRead = new ParcelFileDescriptor(parcelFileDescriptors[0]); 
     parcelWrite = new ParcelFileDescriptor(parcelFileDescriptors[1]); 

dann in Ihrem Video/Audio-Stream

setOutputFile(parcelWrite.getFileDescriptor()); 

und in derselben Datei Änderung

// The packetizer encapsulates the bit stream in an RTP stream and send it over the network 
    mPacketizer.setInputStream(mReceiver.getInputStream()); 
    mPacketizer.start(); 

zu

  InputStream is = null; 
      try{ is = new ParcelFileDescriptor.AutoCloseInputStream(parcelRead); 
      } 
      catch (Exception e){} 
      mPacketizer.setInputStream(is); 

Wie andreasperelli im Kommentar darauf hingewiesen, stellen Sie sicher, dass die ParcelFileDescriptors in closeSockets(), oder in Abhängigkeit von der jeweiligen Implementierung und Version zu schließen, bevor closeSockets() und bevor Sie anrufen MediaRecorder.stop().

+0

können Sie bitte fügen Sie mir den MediaStream.java Code, um zu sehen, wie haben Sie die createSockets() -Methode geändert? – andreasperelli

+0

Es tut mir leid, ich war nicht klar. Sie können createSockets() und closeSockets() alleine lassen und nur den Code in ihnen ignorieren. Sie werden die LocalSockets nicht verwenden. Erstellen Sie stattdessen die geschützten ParcelRead- und ParcelWrite-Vars in Mediastream, initialisieren Sie sie in createSockets, wie oben gezeigt, und verwenden Sie sie an der Stelle, an der die lokalen Sockets verwendet wurden, und ersetzen Sie den obigen Code beim Festlegen des Ausgabefiles und Paketizer-Eingabestreams – sbaar

+1

streaming, auf stop it Ich sehe MediaCodecInputStream - Kein Puffer verfügbar ... in logcat und onSessionStopped scheint nicht aufgerufen zu werden. Übrigens, super fix! – andreasperelli

0

bei Android 6.0 ich dieses Problem mit dem Code beheben

new Thread(new Runnable() { 
    @Override public void run() { 
    FileInputStream inputStream = null; 
    try { 
     inputStream = new FileInputStream(path); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } 
    while (true) { 
     byte[] buffer = new byte[0]; 
     try { 
     buffer = new byte[inputStream.available()]; 
     } catch (IOException e) { 
     e.printStackTrace(); 
     } 
     try { 
     inputStream.read(buffer); 
     } catch (IOException e) { 
     e.printStackTrace(); 
     } 
     try { 
     mSender.getOutputStream().write(buffer); 
     mSender.getOutputStream().flush(); 
     } catch (IOException e) { 
     e.printStackTrace(); 
     } 
    } 
    } 
}).start(); 

Ich verwende eine Datei als Puffer und Schreiben Bytes an einer anderen Gewinde MediaRecorder Ausgabe in die Datei.

+0

Hallo, bitte erläutern Sie, wie Sie diesen Code ausführlicher verwenden können. –