我正在开发一款应用程序,用于记录我的Android设备的屏幕并将其通过rtsp传输到另一个客户端。我正在使用VirtualDisplay和MediaCodec。
我有一个我不知道如何解决的问题。当我开始流式传输时,客户端在屏幕更改之前不会收到任何内容。我想这是有道理的,缓冲区什么都没有,所以没有任何东西发送给客户端。代码是这样的:
MediaCodec buildMediaCodec() throws IOException {
MediaFormat format = MediaFormat.createVideoFormat(VIDEO_MIME_TYPE, VIDEO_WIDTH, VIDEO_HEIGHT);
// Set some required properties. The media codec may fail if these aren't defined.
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); // 1 seconds between I-frames
// Create a MediaCodec encoder and configure it. Get a Surface we can use for recording into.
MediaCodec mediaCodec = MediaCodec.createEncoderByType(VIDEO_MIME_TYPE);
mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
return mediaCodec;
}
// This is passed to buildVirtualDisplay(), and I get it from calling buildMediaCodec()
Surface mediaCodecSurface = mMediaCodec.createInputSurface();
VirtualDisplay buildVirtualDisplay(MediaProjection mediaProjection, Surface mediaCodecSurface, DisplayMetrics displayMetrics) {
if (mediaProjection == null || mediaCodecSurface == null || displayMetrics == null) {
throw new InvalidParameterException("MediaProjection, Surface and DisplayMetrics are mandatory");
}
return mediaProjection.createVirtualDisplay("Recording Display", VIDEO_WIDTH, VIDEO_HEIGHT, SCREEN_DPI, 0 /* flags */, mediaCodecSurface, null /* callback */, null /* handler */);
}
...
mIndex = mMediaCodec.dequeueOutputBuffer(mBufferInfo, 500000);
if (mIndex >= 0) {
mBuffer = mMediaCodec.getOutputBuffer(mIndex);
if (mBuffer == null) {
throw new RuntimeException("couldn't fetch buffer at index " + mIndex);
}
mBuffer.position(0);
break;
} else if (mIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
mMediaFormat = mMediaCodec.getOutputFormat();
Log.i(TAG, mMediaFormat.toString());
} else if (mIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
Log.v(TAG, "No buffer available...");
} else {
Log.e(TAG, "Message: " + mIndex);
}
在日志中,我可以看到无缓冲区......一个接一个。在屏幕改变的那一刻它停止。
问题是当我停止与手机交互时。屏幕没有刷新,因为没有任何变化,所以我不断获得MediaCodec.INFO_TRY_AGAIN_LATER。大约10秒钟后,客户端断开连接。我猜它没有收到任何东西所以它只是关闭连接。
我还观察到,我在开始时等待的时间越长,服务器和客户端设备之间的延迟就越大。
如果我放一个进度条,一切正常,似乎屏幕重新渲染,因此缓冲区包含要发送的数据。
我已经找到了有关此问题的信息。有什么建议我可以做些什么来防止这种情况发生?我应该在MediaCodec和VirtualDisplay之间使用另一个Surface并尝试“强制”渲染吗?
感谢。
答案 0 :(得分:1)
我发现客户端在未接收数据至少10秒后断开连接。我从MediaFormat尝试KEY_REPEAT_PREVIOUS_FRAME_AFTER来防止这种情况,但到目前为止还没有运气。