server: HW cleanup

This commit is contained in:
Lily Tsuru 2024-10-06 20:43:37 -04:00
parent fb3f589fd0
commit 084efc28da
4 changed files with 53 additions and 68 deletions

View file

@ -35,7 +35,7 @@ fn set_frame_flags(frame: &mut ffmpeg::Frame, force_keyframe: bool) {
}
}
fn create_frame(
fn create_hardware_frame(
width: u32,
height: u32,
pixel_format: ffmpeg::format::Pixel,
@ -89,7 +89,6 @@ fn encoder_thread_main(
force_keyframe = false;
}
encoder = Some(H264Encoder::new_nvenc(
&dev,
@ -98,13 +97,6 @@ fn encoder_thread_main(
5 * (1000 * 1000),
)?);
let mut producer_frame_locked = frame.lock().expect("Couldn't lock producer frame");
let mut producer_frame = producer_frame_locked.as_mut().expect("NOOOO");
unsafe {
(*producer_frame.as_mut_ptr()).hw_frames_ctx = encoder.as_mut().unwrap().get_hw_context().as_raw_mut();
}
}
EncodeThreadInput::ForceKeyframe => {
@ -125,8 +117,7 @@ fn encoder_thread_main(
set_frame_flags(producer_frame, force_keyframe);
unsafe {
(*producer_frame.as_mut_ptr()).pts = frame_number as i64;
(*producer_frame.as_mut_ptr()).pts = frame_number as i64;
}
if enc.is_hardware() {

View file

@ -6,7 +6,6 @@ use ffmpeg::error::EAGAIN;
use ffmpeg::{codec as lavc, packet}; // lavc
use crate::types::Size;
/// this is required for libx264 to like. Work
@ -37,12 +36,12 @@ fn create_context_and_set_common_parameters(
video_encoder_context.set_height(size.height);
video_encoder_context.set_frame_rate(Some(ffmpeg::Rational(1, max_framerate as i32)));
video_encoder_context.set_bit_rate(bitrate);
//video_encoder_context.set_max_bit_rate(bitrate);
video_encoder_context.set_bit_rate(bitrate / 4);
video_encoder_context.set_max_bit_rate(bitrate);
// qp TODO:
video_encoder_context.set_qmax(30);
video_encoder_context.set_qmin(35);
//video_encoder_context.set_qmax(30);
//video_encoder_context.set_qmin(35);
video_encoder_context.set_time_base(ffmpeg::Rational(1, max_framerate as i32).invert());
video_encoder_context.set_format(ffmpeg::format::Pixel::YUV420P);
@ -71,7 +70,14 @@ pub enum H264Encoder {
Nvenc {
encoder: ffmpeg::encoder::video::Encoder,
hw_context: HwFrameContext,
// FIXME: This will be needed if the user wants to encode
// frames always stored in GPU memory. For now we let ffmpeg upload
// and download frames to the GPU, but at some point
// it would be a good idea to have, say,
// new_nvenc_hwframe(dev, ...)
// new_nvenc_cpuframe(...) (has the same behaviour as current new_nvenc)
//hw_context: HwFrameContext,
},
}
@ -111,7 +117,6 @@ impl H264Encoder {
dict.set("forced-idr", "1");
let encoder = video_encoder_context
.open_as_with(encoder, dict)
.with_context(|| "While opening x264 video codec")?;
@ -124,33 +129,34 @@ impl H264Encoder {
cuda_device: &CudaDevice,
size: Size,
max_framerate: u32,
bitrate: usize
bitrate: usize,
) -> anyhow::Result<Self> {
let (mut encoder, mut video_encoder_context) =
create_context_and_set_common_parameters("h264_nvenc", &size, max_framerate, bitrate)
.with_context(|| "while trying to create encoder")?;
.with_context(|| "while trying to create encoder")?;
/*
(See FIXMEs above)
let cuda_device_context = super::hwdevice::CudaDeviceContextBuilder::new()?
.set_cuda_context((*cuda_device.cu_primary_ctx()) as *mut _)
.build()
.set_cuda_context((*cuda_device.cu_primary_ctx()) as *mut _)
.build()
.with_context(|| "while trying to create CUDA device context")?;
let mut hw_frame_context = super::hwframe::HwFrameContextBuilder::new(cuda_device_context)?
.set_width(size.width)
.set_height(size.height)
.set_sw_format(ffmpeg::format::Pixel::ZRGB32)
.set_format(ffmpeg::format::Pixel::CUDA)
.build()
let mut hw_frame_context = super::hwframe::HwFrameContextBuilder::new(cuda_device_context)?
.set_width(size.width)
.set_height(size.height)
.set_sw_format(ffmpeg::format::Pixel::ZRGB32)
.set_format(ffmpeg::format::Pixel::CUDA)
.build()
.with_context(|| "while trying to create CUDA frame context")?;
// lol you do not need unsafe code to set this my guy.
*/
video_encoder_context.set_format(ffmpeg::format::Pixel::ZRGB32);
unsafe {
//(*video_encoder_context.as_mut_ptr()).hw_frames_ctx = hw_frame_context.as_raw_mut();
//(*video_encoder_context.as_mut_ptr()).delay = 0;
//(*video_encoder_context.as_mut_ptr()).refs = 0;
}
video_encoder_context.set_qmin(38);
video_encoder_context.set_qmax(35);
// set h264_nvenc options
let mut dict = ffmpeg::Dictionary::new();
@ -161,19 +167,20 @@ impl H264Encoder {
dict.set("profile", "main");
// TODO:
dict.set("crf", "43");
dict.set("crf_max", "48");
dict.set("rc", "vbr");
//dict.set("qp", "45");
dict.set("forced-idr", "1");
// damn you
dict.set("delay", "0");
dict.set("zerolatency", "1");
let encoder = video_encoder_context
.open_as_with(encoder, dict)
.with_context(|| "While opening h264_nvenc video codec")?;
Ok(Self::Nvenc { encoder: encoder, hw_context: hw_frame_context })
.open_as_with(encoder, dict)
.with_context(|| "While opening h264_nvenc video codec")?;
Ok(Self::Nvenc { encoder: encoder })
}
// FIXME: It's a bit pointless to have this have a mut borrow,
@ -185,12 +192,12 @@ impl H264Encoder {
}
}
pub fn get_hw_context(&mut self) -> &mut HwFrameContext {
match self {
Self::Nvenc { encoder: _, hw_context } => hw_context,
_ => panic!("should not use H264Encoder::get_hw_context() on a Software encoder")
}
}
//pub fn get_hw_context(&mut self) -> &mut HwFrameContext {
// match self {
// Self::Nvenc { encoder: _, hw_context } => hw_context,
// _ => panic!("should not use H264Encoder::get_hw_context() on a Software encoder")
// }
//}
pub fn send_frame(&mut self, frame: &ffmpeg::Frame) {
match self {
@ -198,10 +205,7 @@ impl H264Encoder {
encoder.send_frame(frame).unwrap();
}
Self::Nvenc {
encoder,
hw_context,
} => {
Self::Nvenc { encoder } => {
// Realistically this should be the same right?
encoder.send_frame(frame).unwrap();
//todo!("Requires support.");
@ -215,13 +219,10 @@ impl H264Encoder {
encoder.send_eof().unwrap();
}
Self::Nvenc {
encoder,
hw_context,
} => {
Self::Nvenc { encoder } => {
// Realistically this should be the same right?
encoder.send_eof().unwrap();
// todo!("Requires support.");
// todo!("Requires support.");
}
}
}
@ -230,14 +231,7 @@ impl H264Encoder {
return match self {
Self::Software { encoder } => encoder.receive_packet(packet),
Self::Nvenc {
encoder,
hw_context,
} => {
// Realistically this should be the same right?
encoder.receive_packet(packet)
//todo!("Requires support.");
}
Self::Nvenc { encoder } => encoder.receive_packet(packet),
};
}

View file

@ -44,7 +44,7 @@ impl HwFrameContextBuilder {
pub fn new(mut cuda_device_context: CudaDeviceContext) -> anyhow::Result<Self> {
let buffer = unsafe { ffmpeg::sys::av_hwframe_ctx_alloc(cuda_device_context.as_raw_mut()) };
if buffer.is_null() {
return Err(anyhow::anyhow!("could not allocate a hwframe"));
return Err(anyhow::anyhow!("could not allocate a hwframe context"));
}
Ok(Self { cuda_device_context, buffer })

View file

@ -2,7 +2,7 @@ pub mod encoder_thread;
pub mod h264_encoder;
//pub mod lc_muxer;
/// Re-export of `ffmpeg_the_third` crate in an infinitely less obtuse name.
/// Re-export of `ffmpeg` crate.
pub use ffmpeg as ffmpeg;
pub mod hwdevice;