读取inputSream的固定字节大小

时间:2018-02-04 07:39:25

标签: java android sockets bitmap inputstream

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

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

希望这张图能够澄清问题。

传输过程: enter image description here

代码:

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();
                   }
    }

复兴过程: enter image description here

代码:

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();
        }


    }

目前缓冲读取器正在读取不同大小的数据块,因此构建的位图将如下所示: enter image description here

尚未收到图像的黑色边,因为缓冲的阅读器没有阻塞并等待所有缓冲区都被填满。

2 个答案:

答案 0 :(得分:0)

  

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

好吧,那有什么不对?

由于各种原因,

read并不会始终阅读您要求的所有数据。在您阅读了想要阅读的所有数据之前,您需要继续阅读。

答案 1 :(得分:0)

所以问题是框架尺寸固定的错误假设,

逻辑是获取摄像头提供的第一个帧大小,然后将其发送到另一个控制Chanel的另一侧,然后继续传输该信息的其余流, 如果我没有对图像进行有损压缩,那将会奏效

yuv.compressToJpeg(new Rect(0, 0, frameWidth, frameHieght), 25, out);
由于@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();
        }


    }