13

Я пытаюсь залежных Truiton ScreenCapture пример для того, чтобы записать экран устройства с помощью MediaProjectionпоток андроида экран

При сохранении записи, локальной работает

mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); 
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 

    String localFilePath = getLocalFilePath(); 
    mMediaRecorder.setOutputFile(localFilePath); 

    mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT); 
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); 
    mMediaRecorder.setVideoFrameRate(30); 
    mMediaRecorder.prepare(); 

Как всегда при переходе на работу с FileDescriptor это не

mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); 
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 

    String hostname = "10.26.100.18"; 
    int port = 2007; 
    Socket socket = new Socket(InetAddress.getByName(hostname), port); 
    ParcelFileDescriptor fileDescriptor = ParcelFileDescriptor.fromSocket(socket); 
    LocalServerSocket localServerSocket = new LocalServerSocket(fileDescriptor.getFileDescriptor()); 

    mMediaRecorder.setOutputFile(localServerSocket.getFileDescriptor()); 

    mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT); 
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); 
    mMediaRecorder.setVideoFrameRate(30); 
    mMediaRecorder.prepare(); 

Если не используется LocalServerSocket, то mMediaRecorder.prepare() бросить исключение, теперь, когда я нас ING его, получить исключение в приведенном ниже методе в mMediaRecorder.getSurface()

private VirtualDisplay createVirtualDisplay() { 
    return mMediaProjection.createVirtualDisplay("MainActivity", 
      DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity, 
      DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, 
      mMediaRecorder.getSurface(), null /*Callbacks*/, null 
      /*Handler*/); 
} 

за исключением

Caused by: java.lang.IllegalStateException: failed to get surface 
    at android.media.MediaRecorder.getSurface(Native Method) 
    at com.truiton.screencapture.MainActivity$override.createVirtualDisplay(MainActivity.java:172) 
    at com.truiton.screencapture.MainActivity$override.onActivityResult(MainActivity.java:133) 
    at com.truiton.screencapture.MainActivity$override.access$dispatch(MainActivity.java) 
    at com.truiton.screencapture.MainActivity.onActivityResult(MainActivity.java:0) 
    at android.app.Activity.dispatchActivityResult(Activity.java:6456) 
    at android.app.ActivityThread.deliverResults(ActivityThread.java:3695) 
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)  
    at android.app.ActivityThread.-wrap16(ActivityThread.java)  
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)  
    at android.os.Handler.dispatchMessage(Handler.java:102)  
    at android.os.Looper.loop(Looper.java:148)  
    at android.app.ActivityThread.main(ActivityThread.java:5417)  
    at java.lang.reflect.Method.invoke(Native Method)  
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)  
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)  

Это мой Java-сервер, я получаю сокет после mMediaRecorder.prepare() называется и он застрял на inputStream.read в eccpected. Исключение в Android happands, когда я звоню mMediaRecorder.start()

final byte[] buffer = new byte[1024]; 
    try { 
     ServerSocket serverSocket = new ServerSocket(2007); 
     while (!serverSocket.isClosed()) { 
      Socket socket = serverSocket.accept(); 
      File videoFile = createEmptyVideoFile(); 
      FileOutputStream outputStream = new FileOutputStream(videoFile); 
      InputStream inputStream = socket.getInputStream(); 
      int length = inputStream.read(buffer); 
      while (length != -1) { 
       outputStream.write(buffer, 0, length); 
       length = inputStream.read(buffer); 
      } 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

ответ

7

Вы должны использовать LocalServerSocket, ниже, что частично работал для меня, у меня есть MediaStreamer класс, который расширяет MediaRecorder.

public class MediaStreamer extends MediaRecorder { 

    private LocalServerSocket localServerSocket = null; 
    private LocalSocket receiver, sender = null; 

    public void prepare() throws IllegalStateException,IOException { 

     receiver = new LocalSocket(); 
     try { 
      localServerSocket = new LocalServerSocket("<your_socket_addr>"); 
      receiver.connect(new LocalSocketAddress("<your_socket_addr>")); 
      receiver.setReceiveBufferSize(4096); 
      receiver.setSendBufferSize(4096); 
      sender = localServerSocket.accept(); 
      sender.setReceiveBufferSize(4096); 
      sender.setSendBufferSize(4096); 
     } catch (IOException e1) { 
      throw new IOException("Can't create local socket !"); 
     } 

     setOutputFile(sender.getFileDescriptor()); 

     try { 
      super.prepare(); 
     } catch (Exception e) { 
      closeSockets(); 
      throw e; 
     }   
    } 

    public InputStream getInputStream() { 

     InputStream out = null; 

     try { 
      out = receiver.getInputStream(); 
     } catch (IOException e) { 
     } 

     return out; 

    } 


    public void stop() { 
     closeSockets(); 
     super.stop(); 
    } 

    private void closeSockets() { 
     if (localServerSocket !=null) { 
      try { 
       localServerSocket.close(); 
       sender.close(); 
       receiver.close(); 
      } 
      catch (IOException e) { 

      } 
      localServerSocket = null; 
      sender = null; 
      receiver = null; 
     } 
    } 
} 

Для записи

video = new MediaStreamer(); 
video.reset(); 

video.setVideoSource(MediaRecorder.VideoSource.DEFAULT); 
video.setPreviewDisplay(holder.getSurface()); 
video.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
video.setVideoFrameRate(VideoConstants.frameRate); 
video.setVideoEncodingBitRate(VideoConstants.bitRate*1000); 
video.setVideoSize(VideoConstants.resolationX, VideoConstants.resolationY); 
video.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); 

try { 
    video.prepare(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 
video.start(); 


Но основная проблема заключается в mp4 не очень легко течь. Основная проблема заключается в том, что MP4 не является живым, потоковым форматом, поэтому, несмотря на то, что данные захватываются через сокет, важные заголовки файлов, которые обычно записываются в конце аудио- или видеозахвата, отсутствуют (поскольку сокеты не видны, как локальные файлы) - следовательно, неиграбельные данные (и поэтому, почему он отлично работает при сохранении в виде локальных файлов, понятно).

Нет простого способа выполнить пост-обработку данных, чтобы вручную добавить заголовки файлов. Таким образом, решение либо не использует MP4 в качестве формата записи, либо пишет пакетик, аналогичный тому, что используется в проекте Spydroid.

Надеюсь, это поможет!

+0

Является ли мой ответ недостаточным или более необходимым, plz сообщите мне? –

+0

Как найти 'your_socket_addr' в nodejs - easyRTC-архитектуре? –

Смежные вопросы