diff options
Diffstat (limited to 'emulator')
-rw-r--r-- | emulator/src/com/android/tools/idea/device/DeviceView.kt | 21 | ||||
-rw-r--r-- | emulator/src/com/android/tools/idea/device/VideoDecoder.kt | 16 |
2 files changed, 28 insertions, 9 deletions
diff --git a/emulator/src/com/android/tools/idea/device/DeviceView.kt b/emulator/src/com/android/tools/idea/device/DeviceView.kt index 8279a2a1d74..7065517f142 100644 --- a/emulator/src/com/android/tools/idea/device/DeviceView.kt +++ b/emulator/src/com/android/tools/idea/device/DeviceView.kt @@ -156,6 +156,7 @@ class DeviceView( } } decoder.addFrameListener(object : VideoDecoder.FrameListener { + override fun onNewFrameAvailable() { EventQueue.invokeLater { if (frameNumber == 0) { @@ -167,6 +168,10 @@ class DeviceView( } } } + + override fun onEndOfVideoStream() { + showDisconnectedMessage("Lost connection to the device. See the error log.") + } }) deviceClient.startVideoDecoding(decoder) } @@ -175,11 +180,17 @@ class DeviceView( } catch (e: Throwable) { thisLogger().error("Failed to initialize the screen sharing agent", e) - EventQueue.invokeLater { - hideLongRunningOperationIndicatorInstantly() - disconnectedStateLabel.text = "Failed to initialize the device agent. See the error log." - add(disconnectedStateLabel) - } + showDisconnectedMessage("Failed to initialize the device agent. See the error log.") + } + } + + private fun showDisconnectedMessage(message: String) { + EventQueue.invokeLater { + decoder = null + hideLongRunningOperationIndicatorInstantly() + disconnectedStateLabel.text = message + add(disconnectedStateLabel) + revalidate() } } diff --git a/emulator/src/com/android/tools/idea/device/VideoDecoder.kt b/emulator/src/com/android/tools/idea/device/VideoDecoder.kt index 77fd1420fc6..3ee786d03c9 100644 --- a/emulator/src/com/android/tools/idea/device/VideoDecoder.kt +++ b/emulator/src/com/android/tools/idea/device/VideoDecoder.kt @@ -118,18 +118,26 @@ internal class VideoDecoder(private val videoChannel: SuspendingSocketChannel, @ } finally { decodingContext.close() + onEndOfVideoStream() } } } - private fun notifyFrameListeners() { + private fun onNewFrameAvailable() { for (listener in frameListeners) { listener.onNewFrameAvailable() } } + private fun onEndOfVideoStream() { + for (listener in frameListeners) { + listener.onEndOfVideoStream() + } + } + interface FrameListener { fun onNewFrameAvailable() + fun onEndOfVideoStream() } internal class VideoFrame( @@ -139,7 +147,7 @@ internal class VideoDecoder(private val videoChannel: SuspendingSocketChannel, @ val frameNumber: Long, val originationTime: Long) - private inner class DecodingContext { + private inner class DecodingContext : AutoCloseable { private val codec: AVCodec private val codecContext: AVCodecContext @@ -211,7 +219,7 @@ internal class VideoDecoder(private val videoChannel: SuspendingSocketChannel, @ } } - fun close() { + override fun close() { avcodec_close(codecContext) avcodec_free_context(codecContext) av_frame_free(decodingFrame) @@ -332,7 +340,7 @@ internal class VideoDecoder(private val videoChannel: SuspendingSocketChannel, @ header.originationTimestampUs / 1000) } - notifyFrameListeners() + onNewFrameAvailable() } private fun createSwsContext(renderingFrame: AVFrame): SwsContext { |