Я разрабатываю своего рода приложение для удаленного рабочего стола, в котором клиент Android может отображать экран рабочего стола (и управлять им).
Проблема заключается в потоковой передаче видео. Моим решением было сделать снимки экрана с помощью класса Java Robot, изменить их размер в соответствии с разрешением целевого устройства и отправить их через DatagramPackets клиенту Android. Затем я обнаружил, что необработанные изображения должны были быть слишком большими для отправки по одному пакету UDP (потому что он занимал более 62 КБ), и поэтому я получил один из них.
IOException: Message too long
Поэтому я сжал изображения вJPEG с настройкой качества 0,25, пока я наконец не смог получить размер кадров разумно ниже 62 КБ. Но даже размер изображения иногда становится слишком большим, что приводит к тому, что кадр не отправляется. Код для этого в настоящее время:
@Override
public void run() {
while (running) {
try {
BufferedImage screenshot = robot.createScreenCapture(
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
BufferedImage resizedSS = Scalr.resize(screenshot,
Scalr.Method.BALANCED, screenSizeX, screenSizeY);
byte[] imageBuff = compressToJPEG(resizedSS, 0.25f);
DatagramPacket packet = new DatagramPacket(imageBuff, imageBuff.length, address, port);
socket.send(packet);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "LiveScreenSender.run: error while sending screenshot");
e.printStackTrace();
break;
}
}
}
Код для сжатия JPEG (примечание: это модифицированная версия кода, которую я нашел где-то на SO, и не до конца понимаю, как он работает)
private static byte[] compressToJPEG(BufferedImage image, float quality) throws IOException {
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(out);
writer.setOutput(ios);
ImageWriteParam param = writer.getDefaultWriteParam();
// compress to a given quality
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(quality);
writer.write(null, new IIOImage(image, null, null), param);
ios.close();
writer.dispose();
return out.toByteArray();
}
Клиентская часть (Android) также довольно похожа
@Override
public void run() {
while (running) {
try {
socket.receive(dataBuffPacket);
if (dataBuffPacket.getLength() == 0) break;
Bitmap bitmap = BitmapFactory.decodeByteArray(dataBuffPacket.getData(), 0, dataBuffPacket.getLength());
onFrameReceive(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Теперь, если длины пакетов UDP ограничены, каков обычный способ потоковой передачи живого видео с использованием UDP. Мне нужно несколько предложений, в каком направлении идти, для решения этого. Любые рекомендации библиотеки будут наиболее цениться. Насколько я видел в Интернете, большинство вопросов и блогов относятся к потоковому контенту, хранящемуся на сервере, а не к видео, генерируемому в режиме реального времени по кадрам.
Мои знания о работе в сети и воспроизведении аудио / видео довольно ограничены, поэтому я был бы признателен за хорошие уроки или ссылки на то, где я мог бы их изучить.