我正在使用一个应用程序,该应用程序记录了我的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之间使用另一个表面,然后尝试"强制"渲染?
谢谢。
我发现客户端在至少10秒内未接收数据后断开连接。我尝试key_repeat_previous_frame_frame_fter从MediaFormat中进行预防,但到目前为止还没有运气。