Я работаю над приложением, которое записывает экран моего устройства Android и передает его поверх rtsp другому клиенту. Для этого я использую VirtualDisplay и MediaCodec.Android-потоковая передача с MediaCodec и VirtualDisplay, клиент отключается
У меня проблема, я не знаю, как ее решить. Когда я запускаю потоковое вещание, клиент ничего не получает до тех пор, пока экран не изменится. Я думаю, это имеет смысл, буфер не содержит ничего, поэтому ничего не отправляется клиенту. Код для этого:
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 и пытаться «заставить» рендеринг?
Спасибо.
Вы когда-нибудь выясняли, как это решить? –
Нет, я как-то взломал его. Я показываю значок в строке состояния. Этот значок анимирован. У меня есть возможность рисования с двумя изображениями, эти два изображения одинаковы, поэтому пользователь ничего не видит. Но для Android он должен «перекрасить» эту часть, поэтому он продолжает генерировать фреймы. –
haha clever :) спасибо! –