I'm using the rust crate ffmpeg-next to decode some video into individual frames for usage in another library. Problem is when I run my test it only seems to use a single core. I've tried modifying the threading configuration for my decoder as you can see below, but It doesn't seem to be do anything
let context_decoder =
ffmpeg_next::codec::context::Context::from_parameters(input_stream.parameters())?;
let mut decoder = context_decoder.decoder().video()?;
let mut threading_config = decoder.threading();
threading_config.count = num_cpus::get();
threading_config.kind = ThreadingType::Frame;
decoder.set_threading(threading_config);
Related
I am trying to create a cryptographically secure random number generator in a Rust program based on ChaCha.
Currently I have
let mut rand = ChaChaRng::new_unseeded();
let rand_num = &rand.gen_range(1, 7);
The problem is that this results in the same random numbers being produced, because (I think) 'new_unseeded()' just uses 0 as the seed.
The documentation I found doesn't have any examples
Is there a method I could call instead so that rand will be seeded by the system in an appropriately random way? (Possibly something like the from_entropy() method?)
Looks like in the more recent versions of the rand crate, the ChaCha generator has moved out to a companion crate rand_chacha. Here's usage:
use rand_chacha::ChaChaRng;
use rand_chacha::rand_core::SeedableRng;
use rand::Rng;
fn main() {
let mut rand = ChaChaRng::from_entropy();
let rand_num = &rand.gen_range(1..7);
println!("{}", rand_num);
}
I have read that the RP2040 has two cores. How can I use the second core in a Rust program?
I do not need to go all the way to generic multithreading, I just want to have two threads, each of which owns one of the cores, and they can communicate with each other.
The Rust book's section about Fearless Concurrency (suggested by Jeremy) is not much help.
thread::spawn(|| {
let mut x = 0;
x = x + 1;
});
fails to compile
error[E0433]: failed to resolve: use of undeclared crate or module `thread`
--> src/main.rs:108:5
|
108 | thread::spawn(|| {
| ^^^^^^ use of undeclared crate or module `thread`
which is hardly surprising given that thread is part of std and the RP2040 is a #![no_std] environment.
In the C API there is a function multicore_launch_core1. Is there an equivalent Rust API?
As you have already discovered, the multi threading facilities of the Rust std library rely on the facilities of an OS kernel which are not available when working in a bare metal embedded environment.
The actual process of getting the second core to execute code is a little complex and low level. It is described in the RP2040 datasheet in the section titled "2.8.2. Launching Code On Processor Core 1".
In summary - after the second core boots up, it goes into a sleep state waiting for instructions to be sent to it over the SIO FIFO, which is a communications channel between the two cores. The instructions sent through provides an interrupt vector table, a stack pointer and an entry point for the core to begin executing.
Luckily, the rp2040_hal crate provides a higher level abstraction for this . The example below is from the multicore module of this crate:
use rp2040_hal::{pac, gpio::Pins, sio::Sio, multicore::{Multicore, Stack}};
static mut CORE1_STACK: Stack<4096> = Stack::new();
fn core1_task() -> ! {
loop {}
}
fn main() -> ! {
let mut pac = pac::Peripherals::take().unwrap();
let mut sio = Sio::new(pac.SIO);
// Other init code above this line
let mut mc = Multicore::new(&mut pac.PSM, &mut pac.PPB, &mut sio.fifo);
let cores = mc.cores();
let core1 = &mut cores[1];
let _test = core1.spawn(unsafe { &mut CORE1_STACK.mem }, core1_task);
// The rest of your application below this line
}
In the above example, the code within the core1_task function will be executed on the second core, while the first core continues to execute the main function. There are more complete examples in the crate's examples directory.
Disclaimer: I have not used this crate or microcontroller myself - all info was found from online documentation.
I'm trying to calculate curve pairings for the BLS cryptosystem given a public key and message. I generate the key with the bls_signatures crate and ultimately want to crunch e(pub_key, HashToCurve(message)) using the blstrs crate (since I found a pairing function there).
let priv_key = bls_signatures::PrivateKey::new(&[0_u8; 32]); // not secure, but repeatable
let mut buff = std::io::Cursor::new(vec![]);
let _bytes_written = priv_key
.public_key()
.as_affine()
.write_raw(&mut buff);
let mut pub_key_affine_bytes: Vec<u8> = buff.into_inner();
The first problem is that paired::bls12_381::G1Affine::write_raw() seems to be adding an extraneous zero to the beginning, giving me 97 bytes instead of 96:
assert!(pub_key_affine_bytes.len() == 97_usize); // instead of 96
assert!(pub_key_affine_bytes[0] == 0_u8); // regardless of key used... which seems wrong
I can "fix" it for now via let _ = pub_key_affine_bytes.remove(0); but when I try to convert to a blstrs::G1Affine (in the hopes of using blstrs::pairing() to reach my goal, but maybe there's a better way?), the blstrs library doesn't like it:
let pub_key_affine_bytes: [u8; 96] = pub_key_affine_bytes.try_into().unwrap();
assert!(blstrs::G1Affine::from_uncompressed(&pub_key_affine_bytes) == None); // instead of Some(_)
It's probably obvious by now, but I'm new to both Rust and this type of cryptography, so any guidance is welcome. How would you calculate pairings given a public key and message?
I just realized this simple solution as I was done looking through all the source code and writing up my original answer. It's as easy as changing the enabled features in your Cargo.toml to disable the usage of paired and enable blstrs to be used internally.
[package]
name = "blst_test"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
blstrs = "^0.3"
bls-signatures = {version="0.10.0", default-features= false, features=["blst"] }
With that fixed, the following works just fine
fn main() {
let priv_key = bls_signatures::PrivateKey::new(&[0_u8; 32]); // not secure, but repeatable
let affine = priv_key
.public_key()
.as_affine(); // blstrs::G1Affine, no longer from paired!
println!("{:?}", affine);
}
Is there any mistake I am making in applying delay the delay?
This is the code I am working with to blink led 3 and 4 after with a delay.
use cortex_m_rt::entry;
use stm32f30x_hal as hal;
use hal::delay::Delay;
use hal::prelude::*;
use hal::stm32f30x;
use panic_halt;
#[entry]
fn main() -> ! {
let device_p = stm32f30x::Peripherals::take().unwrap();
let core_periphs=cortex_m::Peripherals::take().unwrap();
let mut reset_clock_control = device_p.RCC.constrain();
let mut gpioe = device_p.GPIOE.split(&mut reset_clock_control.ahb);
**let mut flash = device_p.FLASH.constrain();
let clocks = reset_clock_control.cfgr.freeze(&mut flash.acr);
let mut delay = Delay::new(core_periphs.SYST,clocks);**
let mut led_3 = gpioe
.pe9
.into_push_pull_output(&mut (gpioe.moder), &mut (gpioe.otyper));
let mut led_4=gpioe.pe8.into_push_pull_output(&mut gpioe.moder,&mut gpioe.otyper);
loop {
led_3.set_high();
**delay.delay_ms(2_000_u16);**
led_4.set_high();
}
}
If I am not using delay part it is working fine
I think you set up your clocks wrong. For the delay to work correctly you should use the system clock.
This is how to create the Delay for STM32 based on this sample (stm32f4xx, but should work for you, too):
// Set up the system clock. We want to run at 48MHz for this one.
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.sysclk(48.mhz()).freeze();
// Create a delay abstraction based on SysTick
let mut delay = hal::delay::Delay::new(cp.SYST, clocks);
where dp are my device peripherals (e.g. let dp = stm32::Peripherals::take().unwrap()) and cp are the core peripherals.
So this uses the sysclk.
Alternatively you could also try to replace your delay with cortex_m::delay(8_000_000);, where the delay is given using the number of clock cycles.
In the loop you set the LED high led_3.set_high();. However never set led_3 low again so it would never blink. So change your loop to:
led_3.set_high();
led_4.set_low();
delay.delay_ms(2_000_u16);
led_4.set_high();
led_3.set_low();
I am trying to send a stream of data with a specific size without the content length header. I believe hyper::body::Body::wrap_stream is what I'm looking for. However, I'm not sure how to extend the example of creating a vector of results given in documentation to incorporate a custom size.
I'm looking for something like this, but I don't know the best way to resolve issues with vec![Ok(0); bytes].
let chunks: Vec<Result<_, std::io::Error>> = vec![Ok(0); bytes];
let stream = futures_util::stream::iter(chunks);
let body = Body::wrap_stream(stream);
The problem here is that Result does not implement Clone so you can't use this syntax to initialize the Vec.
You can make it work by changing it as follow:
let mut chunks: Vec<Result<_, std::io::Error>> = Vec::new();
chunks.resize_with(bytes, || Ok(0));
This way, you initialize independent Result values.