Skip to content

Commit 9aba319

Browse files
committed
added opencv feature
1 parent 591f051 commit 9aba319

File tree

9 files changed

+732
-20
lines changed

9 files changed

+732
-20
lines changed

Cargo.lock

Lines changed: 614 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "silence-core"
3-
version = "0.1.5"
3+
version = "0.1.6"
44
edition = "2021"
55
description = "Core audio I/O abstractions for the silence crate."
66
license = "Apache-2.0"
@@ -20,9 +20,13 @@ io = ["dep:cpal"]
2020
opus = ["dep:opus"]
2121

2222
# Enables all the features
23-
full = ["io", "opus", "serde", "async"]
23+
full = ["io", "opus", "serde", "av1", "opencv"]
2424

25-
async = []
25+
# Enables image input
26+
opencv = ["dep:opencv"]
27+
28+
# Enables image encoding to av1
29+
av1 = ["dep:ravif", "opencv"]
2630

2731
[package.metadata.docs.rs]
2832
all-features = true
@@ -33,4 +37,6 @@ parking_lot = "0.12.3"
3337
cpal = {version = "0.15.3", optional = true}
3438
serde = { version = "1.0.215", optional = true, features = ["derive"] }
3539
tokio = {version = "1.41.1", features = ["sync"]}
36-
opus = {version = "0.3.0", optional = true}
40+
opus = {version = "0.3.0", optional = true}
41+
ravif = {version = "0.11.11", optional = true}
42+
opencv = {version = "0.93.4", optional = true}

src/avif/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
//!

src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,9 @@ mod tests;
2929

3030
#[cfg(feature = "opus")]
3131
pub mod opus;
32+
33+
#[cfg(feature = "opencv")]
34+
pub mod opencv;
35+
36+
#[cfg(feature = "av1")]
37+
pub mod avif;

src/opencv/capture.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//! Offers the ability to receive camera input.
2+
3+
use anyhow::bail;
4+
use opencv::{
5+
core::{Mat, MatTraitConst, MatTraitConstManual, Size_},
6+
videoio::{VideoCapture, VideoCaptureTrait, VideoCaptureTraitConst, CAP_ANY},
7+
};
8+
9+
//Reinport important functions
10+
pub use opencv::imgproc::{cvt_color_def, COLOR_BGR2RGB};
11+
12+
/// Webcam struct definition
13+
/// The struct wraps the ```VideoCapture``` type, and has custom functions for it.
14+
/// You can create a new instance with the ```new``` functions.
15+
#[derive(Debug)]
16+
pub struct Webcam(VideoCapture);
17+
18+
impl Webcam {
19+
/// Create new ```Webcam``` instance with api preference and camera index
20+
/// If you want to use the default api_preference you should use ```new_def(i32)``` instead
21+
/// API preference consts are available at the [opencv documentation](https://docs.rs/opencv/latest/opencv/index.html). Some exmaples for this const are: ```CAP_MSMF```, ```CAP_V4L```.
22+
pub fn new(camera_idx: i32, api_preference: i32) -> anyhow::Result<Self> {
23+
let video_capture_handle = VideoCapture::new(camera_idx, api_preference)?;
24+
25+
if !video_capture_handle.is_opened()? {
26+
bail!("Failed to open capture device.")
27+
}
28+
29+
Ok(Self(video_capture_handle))
30+
}
31+
32+
/// Create new ```Webcam``` instance with auto camera detection.
33+
/// Please note that this function tries to auto detect the camera.
34+
/// If you have more than one camera you should use the ```new_def(i32)``` function to define which camera you are wanting to use.
35+
pub fn new_def_auto_detect() -> anyhow::Result<Self> {
36+
let video_capture_handle = VideoCapture::new_def(CAP_ANY)?;
37+
38+
if !video_capture_handle.is_opened()? {
39+
bail!("Failed to open capture device.")
40+
}
41+
42+
Ok(Self(video_capture_handle))
43+
}
44+
45+
/// Create new ```Webcam``` instance from the camera index.
46+
/// The passed in argument defines which camera this function creates a new instance from
47+
pub fn new_def(camera_idx: i32) -> anyhow::Result<Self> {
48+
let video_capture_handle = VideoCapture::new_def(camera_idx)?;
49+
50+
if !video_capture_handle.is_opened()? {
51+
bail!("Failed to open capture device.")
52+
}
53+
54+
Ok(Self(video_capture_handle))
55+
}
56+
57+
/// Reads an image out of the ```VideoCapture``` buffer, this removes the bytes of the image from the buffer.
58+
/// Returns a tuple of the raw image bytes and the size of the image.
59+
/// Please note the image's bytes returned by this function are automaticly converted from [BRG8](https://learn.microsoft.com/en-us/windows/win32/wic/-wic-codec-native-pixel-formats#rgbbgr-color-model) (Which is returned by opencv by default) to RGB8
60+
pub fn get_frame(&mut self) -> anyhow::Result<(Vec<u8>, Size_<i32>)> {
61+
//Create frame which will be overwritten
62+
let mut frame = Mat::default();
63+
64+
//Read frame
65+
self.0.read(&mut frame)?;
66+
67+
//Create corrected_frame
68+
let mut corrected_frame = Mat::default();
69+
70+
//Color correction
71+
cvt_color_def(&frame, &mut corrected_frame, COLOR_BGR2RGB)?;
72+
73+
//Return captured frame
74+
Ok((
75+
corrected_frame.data_bytes()?.to_vec(),
76+
corrected_frame.size()?,
77+
))
78+
}
79+
80+
/// Get the backend api's name
81+
pub fn get_backend_name(&self) -> anyhow::Result<String> {
82+
Ok(self.0.get_backend_name()?)
83+
}
84+
85+
/// This function drops the inner ```VideoCapture``` instance.
86+
/// If this function is called the instance wont be able to capture any frames, you will need to create a new instance.
87+
pub fn release(&mut self) -> anyhow::Result<()> {
88+
Ok(self.0.release()?)
89+
}
90+
}

src/opencv/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
//! This crate provides fucntionality for camera I/O.
2+
3+
pub mod capture;

src/opus/decode.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ pub fn decode_sample_set_size_opus(
4545

4646
///
4747
/// Decodes a list of [`SoundPacket`]-s, into one raw sample.
48-
///
48+
///
4949
/// # Behavior
5050
/// The function takes a [`Decoder`] and a list of [`SoundPacket`]-s to decode. All information about the decoding process is included in said [`SoundPacket`]-s.
51-
///
51+
///
5252
/// # Error
5353
/// Returns an error, if the [`SoundPacket`] is corrupted (Contains invalid data)
54-
///
54+
///
5555
pub fn decode_samples_opus(
5656
mut decoder: Decoder,
5757
sound_packets: Vec<SoundPacket>,
@@ -61,8 +61,7 @@ pub fn decode_samples_opus(
6161
for sound_packet in sound_packets {
6262
let super::encode::EncoderType::Opus(fec) = sound_packet.encoder_type;
6363

64-
let decoded_samples =
65-
decode_sample_set_size_opus(&mut decoder, sound_packet, fec)?;
64+
let decoded_samples = decode_sample_set_size_opus(&mut decoder, sound_packet, fec)?;
6665

6766
samples.extend(decoded_samples);
6867
}

src/opus/encode.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ pub fn encode_sample_set_size_opus(
6464

6565
///
6666
/// Encodes raw samples (f32) into a list of [`SoundPacket`]-s.
67-
///
67+
///
6868
/// # Behavior
6969
/// Returns a list of the encoded [`SoundPacket`]-s. The frame duration and the channels ([`Channels`]) is needed to know the [`SoundPacket`]'s size.
70-
///
70+
///
7171
/// # Error
7272
/// Returns an error if the following arguments are invalid:
7373
/// * Invalid raw samples

src/tests.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,11 @@ mod tests {
105105
)
106106
.unwrap();
107107

108-
let sound_packets =
109-
encode_samples_opus(encoder, &sample, 20, channels).unwrap();
108+
let sound_packets = encode_samples_opus(encoder, &sample, 20, channels).unwrap();
110109

111110
let decoder = create_opus_decoder(48000).unwrap();
112111

113-
let decoded_buf =
114-
decode_samples_opus(decoder, sound_packets).unwrap();
112+
let decoded_buf = decode_samples_opus(decoder, sound_packets).unwrap();
115113

116114
let err_callback = |err| eprintln!("an error occurred on stream: {}", err);
117115

0 commit comments

Comments
 (0)