使用MediaCodec和VirtualDisplay,客户端断开连接的Android流媒体



我正在使用一个应用程序,该应用程序记录了我的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中进行预防,但到目前为止还没有运气。

最新更新