ipcam-view icon indicating copy to clipboard operation
ipcam-view copied to clipboard

Resetting to invalid mark&java.lang.NegativeArraySizeException: -1

Open ghost opened this issue 8 years ago • 11 comments

Hi i am new at android and i have to stream ip cam. I am getting these errors after i entered my credentials.

java.io.IOException: Resetting to invalid mark
                                                                             at java.io.BufferedInputStream.reset(BufferedInputStream.java:437)
                                                                             at java.io.FilterInputStream.reset(FilterInputStream.java:226)
                                                                             at com.github.niqdev.mjpeg.MjpegInputStreamDefault.readMjpegFrame(MjpegInputStreamDefault.java:76)
                                                                             at com.github.niqdev.mjpeg.MjpegViewDefault$MjpegViewThread.run(MjpegViewDefault.java:129)

and this

java.lang.NegativeArraySizeException: -1
                                                                           at com.github.niqdev.mjpeg.MjpegInputStreamDefault.readMjpegFrame(MjpegInputStreamDefault.java:69)
                                                                           at com.github.niqdev.mjpeg.MjpegViewDefault$MjpegViewThread.run(MjpegViewDefault.java:129)

If you want i can write my credentials. Thanks in advance.

ghost avatar May 04 '17 11:05 ghost

Hi, are you using the code in the sample app? Did you try with the app on the Play Store? Thanks

niqdev avatar May 05 '17 08:05 niqdev

I did both. I did try sample in Android Studio and i got those errors. The camera what i use is Mobotix IP Camera and the url is http://plazacam.studentaffairs.duke.edu/mjpg/video.mjpg, it is type MJPEG and i entered credentials. I did debug and i ve seen in MjpegInputStreamDefault.class, when the headerLen variable equals -1, these errors appear.

ghost avatar May 05 '17 08:05 ghost

Interesting, so could you please checkout old tags of the app and test the sample code or just downgrade the library with old versions, I wouldn't that with the latest changes we have introduced some regressions. Let me know if you find a version that work, thanks.

niqdev avatar May 05 '17 08:05 niqdev

@erdemnayir Do you still have the problem? Did you try with older versions?

niqdev avatar May 07 '17 21:05 niqdev

Unfortunately, I tried all versions, but I got the same errors.

ghost avatar May 07 '17 21:05 ghost

Can you give me please more details of how reproduce the error?

niqdev avatar May 07 '17 21:05 niqdev

Hi, so for sure you should open the stream in this way

.credential("deneme1", "deneme0002")
.open("http://85.99.109.4:5005/control/faststream.jpg?stream=full", TIMEOUT)

but apparently I have another error with that URL then

com.github.niqdev.ipcam E/MjpegViewDefault: encountered exception during render
  java.io.IOException: Mark has been invalidated.
  at java.io.BufferedInputStream.reset(BufferedInputStream.java:336)
  at java.io.FilterInputStream.reset(FilterInputStream.java:134)
  at com.github.niqdev.mjpeg.MjpegInputStreamDefault.readMjpegFrame(MjpegInputStreamDefault.java:76)
  at com.github.niqdev.mjpeg.MjpegViewDefault$MjpegViewThread.run(MjpegViewDefault.java:129)

com.github.niqdev.ipcam E/AndroidRuntime: FATAL EXCEPTION: Thread-217
  Process: com.github.niqdev.ipcam, PID: 18311
  java.lang.NegativeArraySizeException: -1
  at com.github.niqdev.mjpeg.MjpegInputStreamDefault.readMjpegFrame(MjpegInputStreamDefault.java:69)
  at com.github.niqdev.mjpeg.MjpegViewDefault$MjpegViewThread.run(MjpegViewDefault.java:129)

so maybe there is another parameter to add in the URL or a different path to retrieve the stream in the proper format

niqdev avatar May 11 '17 08:05 niqdev

Yes, i did like that. I did try so many times and with different types.

ghost avatar May 11 '17 08:05 ghost

I used this then it worked and i think you can fix with this;

package com.nagikho.ipcammjpegsample;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

public class MjpegInputStream extends DataInputStream {
    private static final String TAG = "MjpegInputStream";

    private final byte[] SOI_MARKER = {(byte) 0xFF, (byte) 0xD8};
    private final byte[] EOF_MARKER = {(byte) 0xFF, (byte) 0xD9};
    private int mContentLength = -1;

    byte[] CONTENT_LENGTH_BYTES;
    byte[] CONTENT_END_BYTES;


    private final static int HEADER_MAX_LENGTH = 100;
    private final static int FRAME_MAX_LENGTH = 200000 + HEADER_MAX_LENGTH;
    private final String CONTENT_LENGTH = "Content-length:";
    private final String CONTENT_END = "\r\n";
    private final static byte[] gFrameData = new byte[FRAME_MAX_LENGTH];
    private final static byte[] gHeader = new byte[HEADER_MAX_LENGTH];
    BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();

    public MjpegInputStream(InputStream in) {
        super(new BufferedInputStream(in, FRAME_MAX_LENGTH));

        bitmapOptions.inSampleSize = 1;
        bitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
        bitmapOptions.inPreferQualityOverSpeed = false;
        bitmapOptions.inPurgeable = true;
        try {
            CONTENT_LENGTH_BYTES = CONTENT_LENGTH.getBytes("UTF-8");
            CONTENT_END_BYTES = CONTENT_END.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    private int getEndOfSeqeunce(DataInputStream in, byte[] sequence) throws IOException {
        int seqIndex = 0;
        byte c;
        for (int i = 0; i < FRAME_MAX_LENGTH; i++) {
            c = (byte) in.readUnsignedByte();
            if (c == sequence[seqIndex]) {
                seqIndex++;
                if (seqIndex == sequence.length) {
                    return i + 1;
                }
            } else {
                seqIndex = 0;
            }
        }
        return -1;
    }

    private int getStartOfSequence(DataInputStream in, byte[] sequence) throws IOException {
        int end = getEndOfSeqeunce(in, sequence);
        return (end < 0) ? (-1) : (end - sequence.length);
    }

    private int parseContentLength(byte[] headerBytes, int length) throws IOException, NumberFormatException {
        int begin = findPattern(headerBytes, length, CONTENT_LENGTH_BYTES, 0);

        int end = findPattern(headerBytes, length, CONTENT_END_BYTES, begin) - CONTENT_END_BYTES.length;

        // converting string to int
        int number = 0;
        int radix = 1;
        for (int i = end - 1; i >= begin; --i) {
            if (headerBytes[i] > 47 && headerBytes[i] < 58) {
                number += (headerBytes[i] - 48) * radix;
                radix *= 10;
            }
        }

        return number;
    }

    private int findPattern(byte[] buffer, int bufferLen, byte[] pattern, int offset) {
        int seqIndex = 0;
        for (int i = offset; i < bufferLen; ++i) {
            if (buffer[i] == pattern[seqIndex]) {
                ++seqIndex;
                if (seqIndex == pattern.length) {
                    return i + 1;
                }
            } else {
                seqIndex = 0;
            }
        }

        return -1;
    }

    public Bitmap readMjpegFrame() throws IOException {
        mark(FRAME_MAX_LENGTH);
        int headerLen = getStartOfSequence(this, SOI_MARKER);


        if (headerLen < 0)
            return null;

        reset();

        readFully(gHeader, 0, headerLen);

        try {
            mContentLength = parseContentLength(gHeader, headerLen);
        } catch (NumberFormatException nfe) {
            nfe.getStackTrace();
            mContentLength = getEndOfSeqeunce(this, EOF_MARKER);
        }
        readFully(gFrameData, 0, mContentLength);
        Bitmap bm = BitmapFactory.decodeByteArray(gFrameData, 0, mContentLength, bitmapOptions);
        bitmapOptions.inBitmap = bm;

        return bm;
    }
}

ghost avatar May 11 '17 08:05 ghost

@erdemnayir if it works and probably could help also someone else, would be nice if you can make a pull request with your changes. If you think it make more sense you could create another stream type with your solution since this library is just a wrapper and could be used with

stream:type="stream_default OR stream_native OR YOUR_STREAM_NAME"

niqdev avatar May 11 '17 08:05 niqdev

If your frame size is larger than ~40,000 you will have this problem.

mdeneen avatar Nov 21 '22 19:11 mdeneen