I need to implement a oldschool live web-converence system without websocket without comet. Starting with POC I need to have some kind of buffer(max 40kb) filled by one camera using multiple POST requests having the video-chunks.
Having multiple GET requests to that servlet should copy all chunks to that response using chunked transfer-encoding.
This is the javascript
function start(){
var opts = {
video: {deviceId:val('cams')},
audio: {deviceId:val('mics')}
};
navigator.mediaDevices.getUserMedia(opts).then(function(stream) {
var r = new MediaRecorder(stream);
r.ondataavailable = function(d){
var type = d.type;
if (type=='dataavailable') {
var data = d.data;
console.log(d);
var blob = data.arrayBuffer();
blob.then(function(d){
var x = new X();
x.open('POST','video');
x.setRequestHeader('X-Chunk-Type', data.type);
x.setRequestHeader('X-Timecode', d.timecode);
x.send(new Int8Array(d));
});
}
}
r.start(100);
}).catch(function(err) {
document.disabledDevices.push(opts.video.deviceId);
reloadIO();
});
}
This is my servlet bound to /video
public class VideoEcho implements Servlet {
private ServletConfig config;
private final ChunkBuffer buffer = new ChunkBuffer(1024 * 40); // 40kb
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
}
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
HttpServletRequest r = (HttpServletRequest) req;
HttpServletResponse resp = (HttpServletResponse) res;
if ("POST".equals(r.getMethod())) {
buffer.addChunk(r);
} else {
buffer.getIncomminListeners().add(new ReplyIncommingChunk(resp));
while (true)
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
ChunkBuffer is this:
public class ChunkBuffer {
public interface ChunkIncommingListeners {
void incomming(byte[] data);
}
private final int maxBufferSize;
private int bytesInUse;
private final byte[][] cache;
private int cacheItems = 0;
private final Set<ChunkIncommingListeners> incomminListeners = new LinkedHashSet<ChunkIncommingListeners>();
public Set<ChunkIncommingListeners> getIncomminListeners() {
return incomminListeners;
}
public ChunkBuffer(int maxBufferSize) {
this.maxBufferSize = maxBufferSize;
this.cache = new byte[maxBufferSize][];
}
public void addChunk(HttpServletRequest req) {
int size = req.getContentLength();
byte[] chunk = new byte[size];
try {
req.getInputStream().read(chunk);
addNewest(chunk);
this.bytesInUse += size;
for (ChunkIncommingListeners chunkIncommingListeners : incomminListeners) {
new Thread(new Runnable() {
@Override
public void run() {
chunkIncommingListeners.incomming(chunk);
}
}).start();
}
} catch (IOException e) {
e.printStackTrace();
}
while (bytesInUse > maxBufferSize) {
removeOldest();
}
}
private void addNewest(byte[] chunk) {
cache[cacheItems] = chunk;
cacheItems++;
}
private void removeOldest() {
bytesInUse -= cache[0].length;
System.arraycopy(cache, 1, cache, 0, cacheItems);
cacheItems--;
}
}
and ReplyIncommingChunk is this:
public class ReplyIncommingChunk implements ChunkIncommingListeners {
private HttpServletResponse res;
private ServletOutputStream outputStream;
public ReplyIncommingChunk(HttpServletResponse res) {
this.res = res;
try {
res.setHeader("Transfer-Encoding", "chunked");
res.setContentType("video/x-matroska;codecs=avc1,opus");
outputStream = res.getOutputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void incomming(byte[] data) {
try {
String hex = Integer.toHexString(data.length) + "\r\n";
outputStream.write(hex.getBytes(StandardCharsets.US_ASCII));
outputStream.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Problem:
If I use this HTML
<video src="https://localhost:8443/video" controls="true"></video>
I can neither see the video nor see any communication using the Chrome-Devtools that any bytes are transported using the GET-Request.
Any idea?
from Share Webcam Servlet
No comments:
Post a Comment