当前位置: 首页 > 知识库问答 >
问题:

从命名Linux管道读取BufferedInputStream只能工作一次

益英逸
2023-03-14

我绝望了,。。。我已经试了很多次了,没有运气。请帮忙

背景知识:我使用raspberry Pi 3开发了一个网络摄像头流媒体服务器,因为我不想要可用的服务器。使用raspistill时,fps非常低(4fps),这就是为什么我考虑使用v4l2选项来流式传输网络摄像机。为此,我将mjpeg视频输出到管道中。

从该管道读取时,将显示第一个jpeg图像,但连续读取返回null。

为了进一步调查这一点,我做了一个小演示程序——同样的结果。

这里是我使用的代码:

从bufferedinputstream迭代20次读取

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-尝试使用标记和重置(运气不好)-使用read而不是ImageIO从流中读取(以20fps的速度读取)

当我执行程序时,v4l2通知帧被消耗,因此java程序正在清空/读取管道,以便可以将新帧输入其中。只有第一个图像并且只有在程序的第一次执行期间才会返回一个图像。程序的第二次执行也会为第一个图像返回null。

这里是一个示例输出:

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 doc声明了一些奇怪的事情,我无法理解:

(...) InputStream被包装在ImageInputStream中。如果没有注册的ImageReader声称能够读取结果流,则返回null(…)

提前感谢您的帮助和建议。

共有1个答案

裴存
2023-03-14

一个不眠之夜后,我得到了一些工作。

尤里卡:我使用v4l2库将1000帧流式传输到linux管道中,并且可以读取所有1000帧。将每个文件保存到目录中大约需要103秒,即10fps。没有跳过任何一帧。

以下是操作方法:

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())
 类似资料:
  • 问题内容: 如何从C ++ / Qt Linux应用程序逐行读取FIFO /命名管道? 今天,我可以从Qt程序的fifo中打开和读取数据,但是我无法使该程序逐行读取数据。Qt读取整个文件,这意味着他要等到“发送方”关闭其会话。 让我们以一些shell命令为例,展示我希望应用程序执行的操作。 首先创建一个fifo 然后我们可以用猫从fifo中读取 然后我们与另一只猫一起发送一些数据 然后开始输入内容

  • 主要内容:使用命名管道双向通信管道是用于相关过程之间的通信。 我们是否可以使用管道进行不相关的进程通信,比方说,我们要从一个终端执行客户端程序,从另一个终端执行服务器程序? 答案是否定的。那么怎样才能实现不相关的进程通信,简单的答案就是使用 命名管道。 即使这适用于相关的进程,但是使用命名管道进行相关的进程通信没有任何意义。 我们使用一个管道进行单向通信,两个管道进行双向通信。 命名管道是否适用相同的条件。 答案是否定的,我们

  • 我目前在PHP中使用proc_open()与命令行工具进行通信。它会自动为STDIN、STDOUT和STDERR创建多达3个文件描述符,因为超过3个管道会破坏Windows兼容性。它适用于Windows XP和我的Mac 10.7。 然而,我希望能够创建我自己的命名管道,以便更好地控制。如果我不能这样做,那么我必须维护进程资源及其流资源之间的引用,这使我的代码过于复杂。我不能使用文件,因为它们会填

  • 我在bitbucket上有一个私有的存储库,其中有一些python代码,是我用git从命令行提取的。然后我将该项目导入Pycharm 2016.3。从命令行我可以推拉,但Pycharm中的git似乎不起作用。我会遇到以下错误:我正在使用ssh身份验证,并且我已将我的.ssh/config设置为使用正确的私钥解析Bitbucket.org。我还将Pycharm配置为使用本机ssh,而不是内置ssh。

  • 我知道将BufferedInpurStream包装在FileInputStream周围会使读取操作更快,但我想知道如何做到这一点。我看了BufferedInpurStream的源代码,得到了一些东西。这是我的理解 当我做了这件事。read(),在内部,它将首先在缓冲区中一次读取字节块,然后从缓冲区中逐个读取每个字节,而不是从文件中读取(成本更高)。一旦缓冲区为空,它将再次用字节块填充它 而使用Fi

  • 这是take II,前几周我发了帖子,我的问题被搁置,我调整了我的文本,但无法得到评论,系统关闭了原来的帖子。 服务器端:只读-服务器打开管道,然后定期检查是否有内容(即不在流末尾)并读取信息。此检查必须以轮询为基础,因为只有在轮询期间,才有有效的上下文来传递数据。。 客户端:仅写-打开管道、写入管道、关闭(Client.exe多次调用,生命周期短,下面的代码是测试代码),例如,其他一些脚本将“使