Stream android screen



我正在尝试使用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()抛出异常,现在我正在使用它,在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上卡住了。当我调用mMediaRecorder.start()

时,Android中的异常发生了。
    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();
    }

你必须使用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项目中使用的打包程序

相关内容

  • 没有找到相关文章

最新更新