Чтение BufferedInputStream из именованного канала Linux работает только один раз

Я в отчаянии,... Я много пробовал и искал, не повезло. Пожалуйста помоги

Немного фона: используя Raspberry Pi 3, я разрабатываю сервер потоковой передачи веб-камеры, так как не хочу, чтобы он был доступен. При raspistill частота кадров в секунду очень низкая (4 кадра в секунду), поэтому я рассматриваю вариант v4l2 для потоковой передачи веб-камеры. Для этого я вывожу видео mjpeg в трубу.

При чтении из этого канала показывается первое изображение в формате JPEG, но последовательные чтения возвращают ноль.

Чтобы исследовать это дальше, я сделал небольшую демонстрационную программу - тот же результат.

Вот код, который я использую:

Итерация 20 раз чтения из bufferedinputstream

private void standardRead()
    {
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(new File(image_path)));           


        } catch (FileNotFoundException e) {         
            e.printStackTrace();
        }

        System.out.println("Is mark supported? "+bis.markSupported());

        try {
            for(int i=0;i<20;i++)
            {
                readingImage(bis,i);
                TimeUnit.MILLISECONDS.sleep(250);
            }

        } catch (IOException | InterruptedException e) {            
            e.printStackTrace();
        }
    }

Метод чтения (улучшен некоторым System.out)

private void readingImage(BufferedInputStream bis,int iteration) throws IOException
    {
        System.out.println("Available bytes to read:"+bis.available());
        System.out.println("Reading image"+iteration);

        BufferedImage read = ImageIO.read(bis);

        if(read!=null){
            System.out.println(read.getRGB(25, 25)+" h:"+read.getHeight());System.out.println();
        }else
        {
            System.out.println("image is null");
        }
        read = null;
    }

То, что я уже пробовал: - Создание нового BufferedInputStream для каждой итерации - Закрытие и создание нового BufferedInputStream - Попытка с использованием метки и сброса (не повезло) - Чтение из потока с использованием чтения вместо ImageIO (чтение всегда с частотой примерно 20 кадров в секунду)

Когда я выполняю программу, v4l2 сообщает, что фреймы использованы, поэтому канал освобождается / читается программой java, поэтому в нее можно вводить новые фреймы. Только первое изображение и только во время первого выполнения программы возвращает мне одно изображение. Второе выполнение программы дает нулевое значение и для первого изображения.

Вот пример вывода:

Is mark supported? true
Available bytes to read:65536
Reading image0
image is null
Available bytes to read:73720
Reading image1
image is null
Available bytes to read:73712
Reading image2
image is null
Available bytes to read:73704
Reading image3
image is null
Available bytes to read:73696
Reading image4
image is null
Available bytes to read:73688
Reading image5
image is null

Одно примечание, если это будет полезно. Для функции ImageIO.read (InputStream) Java-документ утверждает нечто странное, чего я не могу понять:

(...) InputStream заключен в ImageInputStream. Если ни один зарегистрированный ImageReader не утверждает, что может прочитать результирующий поток, возвращается значение null (...)

Заранее спасибо за вашу помощь и совет.

1 ответ

Однажды бессонной ночью я получил кое-что работающее.

Эврика: Я передаю 1000 кадров с помощью библиотеки v4l2 в канал Linux и могу читать все 1000 кадров. Сохранение каждого файла в каталоге занимает около 103 секунд или 10 кадров в секунду. Ни один кадр не пропущен.

Вот как:

private void ReadImages(File path)
    {
        BufferedInputStream bis = null;
        int index = 0;

        ImageReader reader = null;

            try {
                bis = new BufferedInputStream(new FileInputStream(path));
                ImageInputStream stream = ImageIO.createImageInputStream(bis);

                while(bis.available()>0)
                {
                    if(gotReader(stream))
                    {
                        reader = ImageIO.getImageReaders(stream).next();
                        reader.setInput(stream);
                        BufferedImage read = reader.read(index);
                        System.out.println("Image height"+read.getHeight() +" image width:"+read.getWidth()) ;

                        stream.flush();                 
                    index = 0;
                    }

                }
            } catch (IOException e) {
                System.err.println(e.getMessage());
                //e.printStackTrace();
            }
    }

Совет: часто очищайте поток и сбрасывайте индекс. Без очистки растущая память резко снижает производительность.

Совет: Стандартный ImageIO не читает BGR3, RGB3,YU12,YUYV,YV12,YVYU, но H264 и MJPEG

Совет: Считыватель протестирован с

if(ImageIO.getImageReaders(stream).hasNext())
Другие вопросы по тегам