2017-02-22 33 views
0

Я работаю над приложением, которое записывает экран моего устройства 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 и пытаться «заставить» рендеринг?

Спасибо.

ответ

1

Я выяснил, что клиент отключается после приема данных не менее 10 секунд. Я пытаюсь KEY_REPEAT_PREVIOUS_FRAME_AFTER из MediaFormat, чтобы предотвратить это, но пока не повезло.

+0

Вы когда-нибудь выясняли, как это решить? –

+1

Нет, я как-то взломал его. Я показываю значок в строке состояния. Этот значок анимирован. У меня есть возможность рисования с двумя изображениями, эти два изображения одинаковы, поэтому пользователь ничего не видит. Но для Android он должен «перекрасить» эту часть, поэтому он продолжает генерировать фреймы. –

+0

haha ​​clever :) спасибо! –