package com.dronecontrol.droneapi; import com.google.inject.Inject; import com.dronecontrol.droneapi.components.AddressComponent; import com.dronecontrol.droneapi.components.ErrorListenerComponent; import com.dronecontrol.droneapi.components.ReadyStateListenerComponent; import com.dronecontrol.droneapi.components.ThreadComponent; import com.dronecontrol.droneapi.components.UdpComponent; import com.dronecontrol.droneapi.listeners.VideoDataListener; import com.dronecontrol.droneapi.video.P264ImageDecoder; import org.apache.log4j.Logger; import java.awt.image.BufferedImage; import java.net.DatagramPacket; import static com.dronecontrol.droneapi.helpers.ThreadHelper.sleep; public class VideoRetrieverP264 extends VideoRetrieverAbstract { private final Logger logger = Logger.getLogger(VideoRetrieverP264.class); public static final int RECEIVING_BUFFER_SIZE = 1024000; private final UdpComponent udpComponent; private final P264ImageDecoder imageDecoder; private byte[] receivingBuffer; private DatagramPacket incomingDataPacket; @Inject public VideoRetrieverP264(ThreadComponent threadComponent, AddressComponent addressComponent, UdpComponent udpComponent, ReadyStateListenerComponent readyStateListenerComponent, ErrorListenerComponent errorListenerComponent, P264ImageDecoder imageDecoder) { super(threadComponent, addressComponent, readyStateListenerComponent, errorListenerComponent); this.udpComponent = udpComponent; this.imageDecoder = imageDecoder; determineDatagramPackets(); } private void determineDatagramPackets() { receivingBuffer = new byte[RECEIVING_BUFFER_SIZE]; incomingDataPacket = new DatagramPacket(receivingBuffer, receivingBuffer.length, getDroneAddress(), getVideoDataPort()); } @Override protected void doRun() { connectToVideoDataPort(); initializeCommunication(); setReady(); while (!isStopped()) { try { udpComponent.receive(incomingDataPacket); processData(); udpComponent.sendKeepAlivePacket(); } catch (RuntimeException e) { // This happens sometimes, but does not hinder the video data from being displayed } } disconnectFromVideoDataPort(); } private void connectToVideoDataPort() { logger.info(String.format("Connecting to video data port %d", getVideoDataPort())); udpComponent.connect(getDroneAddress(), getVideoDataPort()); } private void initializeCommunication() { udpComponent.sendKeepAlivePacket(); sleep(1000); } private void processData() { BufferedImage image = getImage(); logger.trace(String.format("Received video data - width: %d, height: %d", image.getWidth(), image.getHeight())); for (VideoDataListener listener : getVideoDataListeners()) { listener.onVideoData(image); } } public BufferedImage getImage() { imageDecoder.determineImageFromStream(receivingBuffer, incomingDataPacket.getLength()); int width = imageDecoder.getWidth(); int height = imageDecoder.getHeight(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); image.setRGB(0, 0, width, height, imageDecoder.getJavaPixelData(), 0, width); return image; } private void disconnectFromVideoDataPort() { logger.info(String.format("Disconnecting from video data port %d", getVideoDataPort())); udpComponent.disconnect(); } }