我正在尝试暂停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
被认为是eccpected。当我打电话给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();
}
答案 0 :(得分:8)
你必须使用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项目中使用的分组器
希望这有帮助!