Я действительно застрял при получении видеопотока для воспроизведения в проекте java fx.
- Короткая версия:
Я транслирую видеофрагмент h264 / avcc с Androidтелефон к настольному компьютеру.Однако у javafx нет простого решения для отображения потока.Я пытаюсь использовать javacv / ffmpeg в попытке сделать эту работу.Однако я получаю ошибки от ffmpeg.
1) Есть ли лучший способ отображать потоковое видео на javafx?
2) У вас есть пример проекта или хороший учебник для javacv ffmpegframegrabber?
3) Я думаю, что я могу упустить некоторые мелкие детали в моем коде, но я не уверен, что я буду.
- Более длинная версия:
1) На конце AndroidЯ получаю видео, используя медиа-рекордер.Чтобы получить информацию о sps / pps, я записываю и сохраняю небольшой фильм на устройстве, а затем анализирую данные sps и pps.
2) Затем на андроиде я разделил налус, чтобы встретить MTUпотребуйте и отправьте их через соединение udp на мой рабочий стол
3) На своем рабочем столе я повторно собираю nalus (или удаляю их, если они теряют данные) и подаю их во входной поток, который я дал конструктору framegreabber.
- Код и журналы:
Ошибки длинные и многочисленные, в зависимости от того, какой вкус я им подаю.Вот два отдельных примера, которые обычно повторяются с большой длиной
[h264 @ 0000020225907a40] non-existing PPS 0 referenced
[h264 @ 0000020225907a40] decode_slice_header error
[h264 @ 0000020225907a40] no frame!
[h264 @ 00000163d8637a40] illegal aspect ratio
[h264 @ 00000163d8637a40] pps_id 3412 out of range
[AVBSFContext @ 00000163e28a0e00] Invalid NAL unit 0, skipping.
!!Одно важное замечание, которое я знаю, это то, что я не реализовал метки времени, которые я создал на устройстве Android при подаче ffmpeg.Я думаю, что это все равно должно показывать искаженные изображения без этого
Поскольку я потратил весь день на то, чтобы угадать и попробовать у меня есть несколько «разновидностей» данных, которые я просмотрел.Я показываю только первый раздел каждого nal, который, по моему мнению, в случае правильного отображения, по крайней мере, покажет изображение мусора, если мои sps и pps правильны
sps: 67 80 80 1E E9 01 68 22 FD C0 36 85 09 A8
pps: 68 06 06 E2
Ниже приведен стиль приложения B.У каждого из них был префикс 00 00 01 и 00 00 00 01
Debug transfer 65 B8 40 0B E5 B8 7B 80 5B 85
Debug transfer 41 E2 20 7A 74 34 3B D6 BE FA
Debug transfer 41 E4 40 2F 01 E0 0C 06 EE 91
Debug transfer 41 E6 60 3E A1 20 5A 02 3C 6D
Debug transfer 41 E8 80 13 B0 B9 82 C3 03 F4
Debug transfer 41 EC C0 1B A3 0C 28 F1 B0 C8
Debug transfer 41 EE E0 1F CE 07 30 EE 05 06
Debug transfer 41 F1 00 08 ED 80 9C 20 09 73
Debug transfer 41 F3 20 09 E9 00 86 60 21 C3
VideoDecoderaddPacket type: 24
Debug transfer 67 80 80 1E E9 01 68 22 FD C0
Debug transfer 68 06 06 E2
Debug transfer 65 B8 20 00 9F 80 78 00 12 8A
Debug transfer 41 E2 20 09 F0 1E 40 7B 0C E0
Debug transfer 41 E4 40 09 F0 29 30 D6 00 AE
Debug transfer 41 E6 60 09 F1 48 31 80 99 40
[h264 @ 000001c771617a40] non-existing PPS 0 referenced
Здесь я попробовал стиль Avcc.Вы можете видеть, что первая строка представляет собой комбинацию sps pps, за которой следует idr, а затем повторяется non idr
Debug transfer 18 00 0E 67 80 80 1E E9 01 68
Debug transfer 00 02 4A 8F 65 B8 20 00 9F C5
Debug transfer 00 02 2F DA 41 E2 20 09 E8 0F
Debug transfer 00 02 2C 34 41 E4 40 09 F4 20
Debug transfer 00 02 4D 92 41 E6 60 09 FC 2B
Debug transfer 00 02 47 02 41 E8 80 09 F0 72
Debug transfer 00 02 52 50 41 EA A0 09 EC 0F
Debug transfer 00 02 58 8A 41 EC C0 09 FC 6F
Debug transfer 00 02 55 F9 41 EE E0 09 FC 6E
Debug transfer 00 02 4D 79 41 F1 00 09 F0 3E
Debug transfer 00 02 4D B6 41 F3 20 09 E8 64
В следующем классе я пытаюсь получить javacv / ffmpeg для показа видео.Я не думаю, что это идеальное решение, и я исследую canvasfram как замену представлению изображения.
public class ImageDecoder {
private final static String TAG = "ImageDecoder ";
private ImageDecoder(){
}
public static void streamImageToImageView(
final ImageView view,
final InputStream inputStream,
final String format,
final int frameRate,
final int bitrate,
final String preset,
final int numBuffers
)
{
System.out.println("Image Decoder Starting...");
try( final FrameGrabber grabber = new
FFmpegFrameGrabber(inputStream))
{
final Java2DFrameConverter converter = new Java2DFrameConverter();
grabber.setFrameNumber(frameRate);
grabber.setFormat(format);
grabber.setVideoBitrate(bitrate);
grabber.setVideoOption("preset", preset);
grabber.setNumBuffers(numBuffers);
System.out.println("Image Decoder waiting on grabber.start...");
grabber.start(); //---- this call is blocking the loop
System.out.println("Image Decoder Looping---------------------------
-------- hit stop");
while(!Thread.interrupted()){
//System.out.println("Image Decoder Looping");
final Frame frame = grabber.grab();
if (frame != null){
final BufferedImage bufferedImage =
converter.convert(frame);
if (bufferedImage != null){
Platform.runLater(() ->
view.setImage(SwingFXUtils.toFXImage(bufferedImage, null)));
}else{
System.out.println("no buf im");
}
}else{
System.out.println("no fr");
Thread.currentThread().interrupt();
}
}
}catch (Exception e){
System.out.print(TAG + e);
}
}
}
Любая помощь очень ценится.