13
私は記録を保存するとき MediaProjection

ストリームは、Androidの画面

使用して、デバイスの画面を記録するために、Truiton ScreenCapture例を休閑地しようとしています

とlocalYそれが動作のFileDescriptorで動作するように変更するとき、それはだどのようにこれまで

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

ない

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の、これは私のJavaサーバです

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)  

例外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*/); 
} 

に以下の方法で例外を取得し、私はmMediaRecorder.prepare()後にソケットが呼び出されるとeccpectedとして、それはinputStream.readに貼り付ける取得します。 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を使用する必要がありますが、私はMediaRecorderを拡張MediaStreamerクラスを持って、部分的に私のために働いていたものです。

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

nodejs - easyRTCアーキテクチャで 'your_socket_addr'を探すには? –