-
-
Notifications
You must be signed in to change notification settings - Fork 170
/
Copy pathvideo_capture_http_stream.rs
46 lines (37 loc) · 1.49 KB
/
video_capture_http_stream.rs
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
//! Example code to stream mjpeg over http
use std::io::Write;
use std::net::{SocketAddr, TcpListener};
use opencv::core::{Mat, Vector};
use opencv::imgcodecs::{imencode, IMWRITE_JPEG_QUALITY};
use opencv::prelude::*;
use opencv::videoio::{VideoCapture, VideoCaptureTraitConst, CAP_ANY};
const BASE_RESPONSE: &[u8] = b"HTTP/1.1 200 OK\r\nContent-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut cam = VideoCapture::new(0, CAP_ANY)?;
assert!(cam.is_opened()?, "Unable to open default camera!");
// Bind listener to a port
let address: SocketAddr = "127.0.0.1:8080".parse()?;
let listener = TcpListener::bind(address)?;
println!("Listening for connections at {address}");
// Accept the first incoming connection
let (mut stream, addr) = listener.accept()?;
println!("Client connected: {addr}");
// Write intial response
stream.write_all(BASE_RESPONSE)?;
// Reduce jpeg quality for streaming
let encode_params = Vector::from_slice(&[IMWRITE_JPEG_QUALITY, 70]);
let mut buffer = Mat::default();
let mut frame = Vector::default();
loop {
// Read frame from the camera & encode it
cam.read(&mut buffer)?;
imencode(".jpg", &buffer, &mut frame, &encode_params)?;
// Construct HTTP frame and send it to the peer
let header = format!(
"--frame\r\nContent-Type: image/jpeg\r\nContent-Length: {}\r\n\r\n",
frame.len()
);
let packet = [header.as_bytes(), frame.as_slice()].concat();
stream.write_all(&packet)?;
}
}