MJpegInputStream.java
3.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package com.theta.view;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* Input stream for motion JPEG data
*/
public class MJpegInputStream extends DataInputStream {
private final byte[] SOI_MARKER = {(byte) 0xFF, (byte) 0xD8};
private final byte[] EOF_MARKER = {(byte) 0xFF, (byte) 0xD9};
private final static String CONTENT_LENGTH = "Content-Length";
private final static int HEADER_MAX_LENGTH = 100;
private final static int FRAME_MAX_LENGTH = 40000 + HEADER_MAX_LENGTH;
/**
* Constructor
* @param inputStream Input stream for receiving data
*/
public MJpegInputStream(InputStream inputStream) {
super(new BufferedInputStream(inputStream, FRAME_MAX_LENGTH));
}
/**
* Acquire end position of specified character string
* @param dataInputStream Input stream for receiving data
* @param sequence Specified character string
* @return End position of specified character string
* @throws IOException
*/
private int getEndOfSequence(DataInputStream dataInputStream, byte[] sequence) throws IOException {
int sequenceIndex = 0;
byte readByteData;
for(int index = 0; index < FRAME_MAX_LENGTH; index++) {
readByteData = (byte) dataInputStream.readUnsignedByte();
if(readByteData == sequence[sequenceIndex]) {
sequenceIndex++;
if(sequenceIndex == sequence.length) {
return index + 1;
}
} else {
sequenceIndex = 0;
}
}
return -1;
}
/**
* Acquire start position of specified character string
* @param dataInputStream Input stream for receiving data
* @param sequence Specified character string
* @return Start position of specified character string
* @throws IOException
*/
private int getStartOfSequence(DataInputStream dataInputStream, byte[] sequence) throws IOException {
int endIndex = getEndOfSequence(dataInputStream, sequence);
return (endIndex < 0) ? (-1) : (endIndex - sequence.length);
}
/**
* Acquire data length from header
* @param headerByteData Header data
* @return Data length
* @throws IOException
* @throws NumberFormatException
*/
private int parseContentLength(byte[] headerByteData) throws IOException, NumberFormatException {
ByteArrayInputStream bais = new ByteArrayInputStream(headerByteData);
Properties properties = new Properties();
properties.load(bais);
return Integer.parseInt(properties.getProperty(CONTENT_LENGTH));
}
/**
* Acquire image data for 1 frame
* @return Image data for 1 frame
* @throws IOException
*/
public Bitmap readMJpegFrame() throws IOException {
mark(FRAME_MAX_LENGTH);
int headerLength = getStartOfSequence(this, SOI_MARKER);
int contentLength;
reset();
byte[] headerData = new byte[headerLength];
readFully(headerData);
try {
contentLength = parseContentLength(headerData);
} catch (NumberFormatException e) {
e.getStackTrace();
contentLength = getEndOfSequence(this, EOF_MARKER);
}
reset();
byte[] frameData = new byte[contentLength];
skipBytes(headerLength);
readFully(frameData);
return BitmapFactory.decodeStream(new ByteArrayInputStream(frameData));
}
}