web-dev-qa-db-fra.com

Problème MediaRecorder sur Android Lollipop

Je teste libstreaming sur le nouvel Android Lollipop, et ce code qui fonctionnait sur la version précédente semble lancer une exception.

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

L'exception lancée est:

MediaRecorder: le démarrage a échoué -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)

J'ai essayé de commenter:

mMediaRecorder.setOutputFile(mSender.getFileDescriptor());

aucune exception n'a été lancée, mais lorsque je lance la transmission en continu d'une boîte de dialogue, indiquez que vous avez besoin d'un fichier de sortie.

Aide appréciée.

20
andreasperelli

J'ai déposé un rapport de bogue sur AOSP . https://code.google.com/p/Android/issues/detail?id=80715

"Les règles actuelles de SELinux ne permettent pas à mediaserver de gérer les sockets de domaine Unix abstraits générés par les applications.

Au lieu de cela, je vous recommande de créer une paire de tubes ( http://developer.Android.com/reference/Android/os/ParcelFileDescriptor.html#createPipe () ) qui est autorisée par la stratégie Android 5.0. " Je ne sais pas pourquoi ils ont fait cela ou comment nous étions censés le savoir.

J'utilise une version très ancienne/modifiée (je ne le sais pas) de libstreaming où mediastream est toujours étendu à partir de mediarecorder, mais si vous regardez la version actuelle, dans MediaStream, vous voudrez probablement remplacer createSockets par un élément comprenant les éléments suivants:

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

puis dans votre flux vidéo/audio

setOutputFile(parcelWrite.getFileDescriptor());

et dans ce même fichier change

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

à

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

Comme l'a souligné andreasperelli dans le commentaire, assurez-vous de fermer les ParcelFileDescriptors dans closeSockets () ou, selon votre implémentation et votre version, avant closeSockets () et avant d'appeler MediaRecorder.stop ().

25
sbaar

sur Android 6.0, je résous ce problème avec le code 

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

J'utilise un fichier comme tampon et j'écris des octets sur un autre thread. La sortie de MediaRecorder dans le fichier.

1
xiaose