Поток h264 в javafx возможно используя javacv / ffmpeg - PullRequest
0 голосов
/ 21 сентября 2018

Я действительно застрял при получении видеопотока для воспроизведения в проекте 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);
        }


    }






    }

Любая помощь очень ценится.

1 Ответ

0 голосов
/ 04 октября 2018

Итак, у меня было две проблемы.

Первая - ошибка моего метода синтаксического анализа sps pps.Обратите внимание, что 2-й и 3-й байты одинаковы

Вторым было то, что я случайно увеличил размер буфера и создал большие области с полями 0x00, которые эмулировали стартовые коды.

Это был большой проект для меня, и я хочупомогать другим.Пожалуйста, посетите мой сайт, где я написал длинную дискуссию о потоковой передаче h264

...