mirror of
https://github.com/nestriness/nestri.git
synced 2025-12-12 08:45:38 +02:00
⭐ feat(runner): DMA-BUF support for Intel/AMD GPUs (#283)
## Description Adds DMA-BUF support for non-NVIDIA GPUs using GL elements as conversion workaround. Tested with QSV and VA encoders, note that H.264 seems to only work for QSV encoder, for `vah264(lp)enc` theres major CPU usage with DMA-BUF enabled. Don't mind the branch name, I was working on relay before and changed gears to runner after noticing some DMA-BUF stuff 😅 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Chores** - Added a `.dockerignore` file to exclude the `target` directory from Docker builds. - Updated `.gitignore` to ignore the `target` directory. - **New Features** - Enhanced video processing pipeline with updated handling of DMA-BUF support, including improved compatibility for different GPU vendors and refined video element configurations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
6e19b2e9a0
commit
d7e6da12ac
1
packages/server/.dockerignore
Normal file
1
packages/server/.dockerignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
target/
|
||||||
1
packages/server/.gitignore
vendored
1
packages/server/.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
*.mp4
|
*.mp4
|
||||||
|
target/
|
||||||
@@ -172,7 +172,7 @@ fn handle_encoder_audio(args: &args::Args) -> String {
|
|||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
// Parse command line arguments
|
// Parse command line arguments
|
||||||
let mut args = args::Args::new();
|
let args = args::Args::new();
|
||||||
if args.app.verbose {
|
if args.app.verbose {
|
||||||
args.debug_print();
|
args.debug_print();
|
||||||
}
|
}
|
||||||
@@ -206,10 +206,10 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
let gpu = gpu.unwrap();
|
let gpu = gpu.unwrap();
|
||||||
|
|
||||||
// TODO: Currently DMA-BUF only works for NVIDIA
|
if args.app.dma_buf {
|
||||||
if args.app.dma_buf && *gpu.vendor() != GPUVendor::NVIDIA {
|
log::warn!(
|
||||||
log::warn!("DMA-BUF is currently unsupported outside NVIDIA GPUs, force disabling..");
|
"DMA-BUF is experimental, it may or may not improve performance, or even work at all."
|
||||||
args.app.dma_buf = false;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle video encoder selection
|
// Handle video encoder selection
|
||||||
@@ -288,7 +288,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
))?;
|
))?;
|
||||||
caps_filter.set_property("caps", &caps);
|
caps_filter.set_property("caps", &caps);
|
||||||
|
|
||||||
// GL Upload Element
|
// GL Upload element
|
||||||
let glupload = gst::ElementFactory::make("glupload").build()?;
|
let glupload = gst::ElementFactory::make("glupload").build()?;
|
||||||
|
|
||||||
// GL color convert element
|
// GL color convert element
|
||||||
@@ -299,6 +299,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
let gl_caps = gst::Caps::from_str("video/x-raw(memory:GLMemory),format=NV12")?;
|
let gl_caps = gst::Caps::from_str("video/x-raw(memory:GLMemory),format=NV12")?;
|
||||||
gl_caps_filter.set_property("caps", &gl_caps);
|
gl_caps_filter.set_property("caps", &gl_caps);
|
||||||
|
|
||||||
|
// GL download element (needed only for DMA-BUF outside NVIDIA GPUs)
|
||||||
|
let gl_download = gst::ElementFactory::make("gldownload").build()?;
|
||||||
|
|
||||||
// Video Converter Element
|
// Video Converter Element
|
||||||
let video_converter = gst::ElementFactory::make("videoconvert").build()?;
|
let video_converter = gst::ElementFactory::make("videoconvert").build()?;
|
||||||
|
|
||||||
@@ -372,7 +375,11 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
// If DMA-BUF is enabled, add glupload, color conversion and caps filter
|
// If DMA-BUF is enabled, add glupload, color conversion and caps filter
|
||||||
if args.app.dma_buf {
|
if args.app.dma_buf {
|
||||||
pipeline.add_many(&[&glupload, &glcolorconvert, &gl_caps_filter])?;
|
if *gpu.vendor() == GPUVendor::NVIDIA {
|
||||||
|
pipeline.add_many(&[&glupload, &glcolorconvert, &gl_caps_filter])?;
|
||||||
|
} else {
|
||||||
|
pipeline.add_many(&[&glupload, &glcolorconvert, &gl_caps_filter, &gl_download])?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link main audio branch
|
// Link main audio branch
|
||||||
@@ -389,19 +396,31 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
// With DMA-BUF, also link glupload and it's caps
|
// With DMA-BUF, also link glupload and it's caps
|
||||||
if args.app.dma_buf {
|
if args.app.dma_buf {
|
||||||
// Link video source to caps_filter, glupload, gl_caps_filter, video_converter, video_encoder, webrtcsink
|
if *gpu.vendor() == GPUVendor::NVIDIA {
|
||||||
gst::Element::link_many(&[
|
gst::Element::link_many(&[
|
||||||
&video_source,
|
&video_source,
|
||||||
&caps_filter,
|
&caps_filter,
|
||||||
&video_queue,
|
&video_queue,
|
||||||
&video_clocksync,
|
&video_clocksync,
|
||||||
&glupload,
|
&glupload,
|
||||||
&glcolorconvert,
|
&glcolorconvert,
|
||||||
&gl_caps_filter,
|
&gl_caps_filter,
|
||||||
&video_encoder,
|
&video_encoder,
|
||||||
])?;
|
])?;
|
||||||
|
} else {
|
||||||
|
gst::Element::link_many(&[
|
||||||
|
&video_source,
|
||||||
|
&caps_filter,
|
||||||
|
&video_queue,
|
||||||
|
&video_clocksync,
|
||||||
|
&glupload,
|
||||||
|
&glcolorconvert,
|
||||||
|
&gl_caps_filter,
|
||||||
|
&gl_download,
|
||||||
|
&video_encoder,
|
||||||
|
])?;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Link video source to caps_filter, video_converter, video_encoder, webrtcsink
|
|
||||||
gst::Element::link_many(&[
|
gst::Element::link_many(&[
|
||||||
&video_source,
|
&video_source,
|
||||||
&caps_filter,
|
&caps_filter,
|
||||||
@@ -437,7 +456,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
let result = run_pipeline(pipeline.clone()).await;
|
let result = run_pipeline(pipeline.clone()).await;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => log::info!("All tasks completed successfully"),
|
Ok(_) => log::info!("All tasks finished"),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Error occurred in one of the tasks: {}", e);
|
log::error!("Error occurred in one of the tasks: {}", e);
|
||||||
return Err("Error occurred in one of the tasks".into());
|
return Err("Error occurred in one of the tasks".into());
|
||||||
|
|||||||
Reference in New Issue
Block a user