【问题标题】:Read fixed size of bytes of inputSream [duplicate]读取输入流的固定大小的字节[重复]
【发布时间】:2018-07-14 07:44:54
【问题描述】:

我们正在开发一个视频流应用程序, 目前我们能够捕获视频并逐帧处理,然后在两个设备之间发送/接收数据。

问题出在接收端,因为我们正在发送固定大小的帧,所以接收端也应该以固定大小处理它们,否则他将无法获得帧。

希望这张图能说明问题。

传输过程:

代码:

public void process(@NonNull Frame frame) {
            byte[] data = frame.getData();           
            frameWidth = frame.getSize().getWidth();
            frameHieght = frame.getSize().getHeight();
            YuvImage yuv = new YuvImage(data, frame.getFormat(), frameWidth, frameHieght, null);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            yuv.compressToJpeg(new Rect(0, 0, frameWidth, frameHieght), 25, out);
            final byte[] bytes = out.toByteArray();
            frameByteSize = bytes.length;

            OutputStream outputStream = StreamHandler.getOutputStream();
            if (out != null) {
             try {
                   outputStream.write(bytes, 0, frameByteSize);
                   } catch (IOException e) {
                     e.printStackTrace();
                   }
    }

复活过程:

代码:

public void run() {
        int read = 0;
        int hold = 0;
        int frameSize = StreamHandler.getFrameByteSize();
        try {
            Thread.sleep(10000);
            if (SrtreamHandler != null) {
                InputStream inputStream = StreamHandler.getInputStream();
                if (inputStream != null) {
                    BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
                    while (microPhoneActive) {
                        byte[] frame = new byte[frameSize];
                        read = bufferedInputStream.read(frame, 0, frame.length);
                        Bitmap bitmap = BitmapFactory.decodeByteArray(frame, 0, frame.length);
                        if (bitmap != null) {
                            final Bitmap rotatedBitmap = rotateBitmap(bitmap, -90);
                            frameEvent.onNewFrame(rotatedBitmap);
                        }

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


    }

当前缓冲区读取器正在读取不同大小的数据块,因此构建的位图如下:

图像的黑色部分还没有被接收到,因为缓冲的阅读器没有阻塞并等待所有缓冲的都被填满。

【问题讨论】:

  • 你应该收集块直到你有一个完整的框架。使用 tcp/ip 以大块形式输入的字节是很正常的。
  • 您对read 整数无能为力。开始检查实际读取了多少字节。
  • @greenapps 当我继续阅读直到有完整的帧时,在大多数情况下,我最终会得到一个完整的帧,并且下一帧的某些字节会破坏下一帧和之后的所有帧,是否有处理框架的数据结构?至于读取值,我已经读取了数据,它小于我损坏流的帧
  • 当然,您不应该已经读取下一帧的字节。您应该只先读取一帧的字节。收集块直到你有一个框架。使用 Oleg 提供的链接。
  • @greenapps 这正是我现在的问题,我知道使用 inputStream.available() 是没用的,并且 read 是阻塞的,但不是固定长度

标签: java android sockets bitmap inputstream


【解决方案1】:

所以问题是帧大小是固定的错误假设,

逻辑是获取相机提供的第一个帧大小,然后将其发送到另一个控制 Chanel 上的另一端,然后继续传输该信息的其余流, 如果我不对图像进行有损压缩,这将起作用

yuv.compressToJpeg(new Rect(0, 0, frameWidth, frameHieght), 25, out);

witch 结果到不同的帧大小,在@Oleg 对此评论的帮助下 发帖 How to read all of Inputstream in Server Socket JAVA

代码如下所示, 发送:

public void process(@NonNull Frame frame) {
            byte[] data = frame.getData();
                frameWidth = frame.getSize().getWidth();
                frameHieght = frame.getSize().getHeight();

                YuvImage yuv = new YuvImage(data, frame.getFormat(), frameWidth, frameHieght, null);
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                yuv.compressToJpeg(new Rect(0, 0, frameWidth, frameHieght), 25, out);
                final byte[] bytes = out.toByteArray();
                frameByteSize = bytes.length;

                if (StreamHandler != null) {
                    OutputStream outputStream = StreamHandler.getOutputStream();
                    if (out != null) {
                        try {
                            byte firstByte = (byte) ((bytes.length & 0xff00) >> 8);
                            byte secondByte = (byte) (bytes.length & 0xFF);
                            outputStream.write(firstByte);
                            outputStream.write(secondByte);
                            outputStream.write(bytes, 0, frameByteSize);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }

                }

            }
        }

接收:

public void run() {
        int read = 0;
        int hold = 0;
        int frameSize = StreamHandler.getFrameByteSize();
        try {
            if (StreamHandler != null) {
                InputStream inputStream = SrtreamHandler.getInputStream();
                if (inputStream != null) {
                    DataInputStream dataInputStream = new DataInputStream(inputStream);
                    byte[] frameInfo = new byte[2];
                    while (microPhoneActive) {
                        frameInfo[0] = dataInputStream.readByte();
                        frameInfo[1] = dataInputStream.readByte();
                        ByteBuffer byteBuffer = ByteBuffer.wrap(frameInfo, 0, 2);
                        int bytesToRead = byteBuffer.getShort();
                        byte[] frame = new byte[bytesToRead];
                        dataInputStream.readFully(frame, 0, bytesToRead);
                        Bitmap bitmap = BitmapFactory.decodeByteArray(frame, 0, frame.length);
                        if (bitmap != null) {
                            final Bitmap rotatedBitmap = rotateBitmap(bitmap, -90);
                            frameEvent.onNewFrame(rotatedBitmap);
                        }

                    }
                }
            }

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


    }

【讨论】:

    【解决方案2】:

    当前缓冲区读取器正在读取不同大小的数据块

    好的,那有什么问题?

    read 并不总是读取您要求的所有数据,原因有很多。你需要继续阅读,直到你读完所有你想读的数据。

    【讨论】:

      猜你喜欢
      • 2013-12-24
      • 2012-04-14
      • 2019-05-10
      • 1970-01-01
      • 1970-01-01
      • 2020-04-26
      • 1970-01-01
      • 1970-01-01
      • 2014-11-23
      相关资源
      最近更新 更多