Fix Windows cross-platform compilation by guarding Unix-specific mmap and Hyprland IPC
This commit is contained in:
parent
19dc591f19
commit
83751c3de6
2 changed files with 111 additions and 79 deletions
157
src/encoder.rs
157
src/encoder.rs
|
|
@ -232,85 +232,92 @@ impl VaapiEncoder {
|
|||
av_packet_free(&mut pkt);
|
||||
}
|
||||
} else {
|
||||
let mmap_size = (*stride as usize) * (*dma_height as usize);
|
||||
let ptr = libc::mmap(
|
||||
ptr::null_mut(),
|
||||
mmap_size,
|
||||
libc::PROT_READ,
|
||||
libc::MAP_SHARED,
|
||||
*fd,
|
||||
*offset as libc::off_t,
|
||||
);
|
||||
if ptr != libc::MAP_FAILED {
|
||||
let mut bgra_frame = av_frame_alloc();
|
||||
(*bgra_frame).format = AVPixelFormat::AV_PIX_FMT_BGRA as i32;
|
||||
(*bgra_frame).width = *dma_width as i32;
|
||||
(*bgra_frame).height = *dma_height as i32;
|
||||
av_frame_get_buffer(bgra_frame, 32);
|
||||
|
||||
let bgra_stride = (*bgra_frame).linesize[0] as usize;
|
||||
for y in 0..(*dma_height as usize) {
|
||||
let src_row = std::slice::from_raw_parts(
|
||||
(ptr as *const u8).add(y * (*stride as usize)),
|
||||
(*dma_width as usize) * 4
|
||||
);
|
||||
let dst_row = std::slice::from_raw_parts_mut(
|
||||
(*bgra_frame).data[0].add(y * bgra_stride),
|
||||
(*dma_width as usize) * 4
|
||||
);
|
||||
dst_row.copy_from_slice(src_row);
|
||||
}
|
||||
libc::munmap(ptr, mmap_size);
|
||||
|
||||
let mut nv12_frame = av_frame_alloc();
|
||||
(*nv12_frame).format = AVPixelFormat::AV_PIX_FMT_NV12 as i32;
|
||||
(*nv12_frame).width = *dma_width as i32;
|
||||
(*nv12_frame).height = *dma_height as i32;
|
||||
av_frame_get_buffer(nv12_frame, 32);
|
||||
|
||||
if self.sws_ctx.is_null() {
|
||||
self.sws_ctx = sws_getContext(
|
||||
*dma_width as i32, *dma_height as i32, AVPixelFormat::AV_PIX_FMT_BGRA,
|
||||
*dma_width as i32, *dma_height as i32, AVPixelFormat::AV_PIX_FMT_NV12,
|
||||
2, ptr::null_mut(), ptr::null_mut(), ptr::null_mut()
|
||||
);
|
||||
}
|
||||
|
||||
sws_scale(
|
||||
self.sws_ctx,
|
||||
(*bgra_frame).data.as_ptr() as *const *const u8,
|
||||
(*bgra_frame).linesize.as_ptr(),
|
||||
0,
|
||||
*dma_height as i32,
|
||||
(*nv12_frame).data.as_ptr(),
|
||||
(*nv12_frame).linesize.as_ptr()
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let mmap_size = (*stride as usize) * (*dma_height as usize);
|
||||
let ptr = libc::mmap(
|
||||
ptr::null_mut(),
|
||||
mmap_size,
|
||||
libc::PROT_READ,
|
||||
libc::MAP_SHARED,
|
||||
*fd,
|
||||
*offset as libc::off_t,
|
||||
);
|
||||
if ptr != libc::MAP_FAILED {
|
||||
let mut bgra_frame = av_frame_alloc();
|
||||
(*bgra_frame).format = AVPixelFormat::AV_PIX_FMT_BGRA as i32;
|
||||
(*bgra_frame).width = *dma_width as i32;
|
||||
(*bgra_frame).height = *dma_height as i32;
|
||||
av_frame_get_buffer(bgra_frame, 32);
|
||||
|
||||
let mut fresh_hw_frame = av_frame_alloc();
|
||||
(*fresh_hw_frame).format = AVPixelFormat::AV_PIX_FMT_VAAPI as i32;
|
||||
let get_buf_ret = av_hwframe_get_buffer(self.hw_frames_ctx, fresh_hw_frame, 0);
|
||||
let transfer_ret = av_hwframe_transfer_data(fresh_hw_frame, nv12_frame, 0);
|
||||
(*fresh_hw_frame).pts = self.next_pts;
|
||||
self.next_pts += 1;
|
||||
|
||||
let send_ret = avcodec_send_frame(self.codec_ctx, fresh_hw_frame);
|
||||
if send_ret >= 0 {
|
||||
let mut pkt = av_packet_alloc();
|
||||
while avcodec_receive_packet(self.codec_ctx, pkt) >= 0 {
|
||||
let new_pkt = av_packet_alloc();
|
||||
av_packet_move_ref(new_pkt, pkt);
|
||||
packets.push(crate::ring::Packet::new(new_pkt));
|
||||
let bgra_stride = (*bgra_frame).linesize[0] as usize;
|
||||
for y in 0..(*dma_height as usize) {
|
||||
let src_row = std::slice::from_raw_parts(
|
||||
(ptr as *const u8).add(y * (*stride as usize)),
|
||||
(*dma_width as usize) * 4
|
||||
);
|
||||
let dst_row = std::slice::from_raw_parts_mut(
|
||||
(*bgra_frame).data[0].add(y * bgra_stride),
|
||||
(*dma_width as usize) * 4
|
||||
);
|
||||
dst_row.copy_from_slice(src_row);
|
||||
}
|
||||
av_packet_free(&mut pkt);
|
||||
} else {
|
||||
eprintln!("get_buf: {}, transfer: {}, send_ret: {}", get_buf_ret, transfer_ret, send_ret);
|
||||
}
|
||||
av_frame_free(&mut fresh_hw_frame);
|
||||
libc::munmap(ptr, mmap_size);
|
||||
|
||||
av_frame_free(&mut nv12_frame);
|
||||
av_frame_free(&mut bgra_frame);
|
||||
} else {
|
||||
eprintln!("mmap failed on dma-buf fd {}: {}", *fd, std::io::Error::last_os_error());
|
||||
let mut nv12_frame = av_frame_alloc();
|
||||
(*nv12_frame).format = AVPixelFormat::AV_PIX_FMT_NV12 as i32;
|
||||
(*nv12_frame).width = *dma_width as i32;
|
||||
(*nv12_frame).height = *dma_height as i32;
|
||||
av_frame_get_buffer(nv12_frame, 32);
|
||||
|
||||
if self.sws_ctx.is_null() {
|
||||
self.sws_ctx = sws_getContext(
|
||||
*dma_width as i32, *dma_height as i32, AVPixelFormat::AV_PIX_FMT_BGRA,
|
||||
*dma_width as i32, *dma_height as i32, AVPixelFormat::AV_PIX_FMT_NV12,
|
||||
2, ptr::null_mut(), ptr::null_mut(), ptr::null_mut()
|
||||
);
|
||||
}
|
||||
|
||||
sws_scale(
|
||||
self.sws_ctx,
|
||||
(*bgra_frame).data.as_ptr() as *const *const u8,
|
||||
(*bgra_frame).linesize.as_ptr(),
|
||||
0,
|
||||
*dma_height as i32,
|
||||
(*nv12_frame).data.as_ptr(),
|
||||
(*nv12_frame).linesize.as_ptr()
|
||||
);
|
||||
|
||||
let mut fresh_hw_frame = av_frame_alloc();
|
||||
(*fresh_hw_frame).format = AVPixelFormat::AV_PIX_FMT_VAAPI as i32;
|
||||
let get_buf_ret = av_hwframe_get_buffer(self.hw_frames_ctx, fresh_hw_frame, 0);
|
||||
let transfer_ret = av_hwframe_transfer_data(fresh_hw_frame, nv12_frame, 0);
|
||||
(*fresh_hw_frame).pts = self.next_pts;
|
||||
self.next_pts += 1;
|
||||
|
||||
let send_ret = avcodec_send_frame(self.codec_ctx, fresh_hw_frame);
|
||||
if send_ret >= 0 {
|
||||
let mut pkt = av_packet_alloc();
|
||||
while avcodec_receive_packet(self.codec_ctx, pkt) >= 0 {
|
||||
let new_pkt = av_packet_alloc();
|
||||
av_packet_move_ref(new_pkt, pkt);
|
||||
packets.push(crate::ring::Packet::new(new_pkt));
|
||||
}
|
||||
av_packet_free(&mut pkt);
|
||||
} else {
|
||||
eprintln!("get_buf: {}, transfer: {}, send_ret: {}", get_buf_ret, transfer_ret, send_ret);
|
||||
}
|
||||
av_frame_free(&mut fresh_hw_frame);
|
||||
|
||||
av_frame_free(&mut nv12_frame);
|
||||
av_frame_free(&mut bgra_frame);
|
||||
} else {
|
||||
eprintln!("mmap failed on dma-buf fd {}: {}", *fd, std::io::Error::last_os_error());
|
||||
}
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
eprintln!("DMA-BUF mmap is only supported on Unix");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,27 @@
|
|||
#[cfg(unix)]
|
||||
use std::process::Command;
|
||||
#[cfg(unix)]
|
||||
use std::env;
|
||||
#[cfg(unix)]
|
||||
use std::io::{BufRead, BufReader};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::net::UnixStream;
|
||||
#[cfg(unix)]
|
||||
use std::path::PathBuf;
|
||||
use crate::config::VrecConfig;
|
||||
|
||||
pub fn is_hyprland() -> bool {
|
||||
env::var("HYPRLAND_INSTANCE_SIGNATURE").is_ok()
|
||||
|| env::var("XDG_CURRENT_DESKTOP")
|
||||
.map(|d| d.to_lowercase().contains("hyprland"))
|
||||
.unwrap_or(false)
|
||||
#[cfg(unix)]
|
||||
{
|
||||
env::var("HYPRLAND_INSTANCE_SIGNATURE").is_ok()
|
||||
|| env::var("XDG_CURRENT_DESKTOP")
|
||||
.map(|d| d.to_lowercase().contains("hyprland"))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert standard hotkey format (e.g. "Ctrl+Shift+R") to Hyprland bind format ("CONTROL_SHIFT, R")
|
||||
|
|
@ -50,6 +62,7 @@ pub fn hotkey_to_hyprland(hotkey: &str) -> Option<(String, String)> {
|
|||
Some((mod_str, key.to_string()))
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
/// Dynamically inject binds and window rules into running Hyprland without touching hyprland.conf
|
||||
pub fn register_hyprland_binds(config: &VrecConfig) {
|
||||
if !is_hyprland() {
|
||||
|
|
@ -97,6 +110,10 @@ pub fn register_hyprland_binds(config: &VrecConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
pub fn register_hyprland_binds(_config: &VrecConfig) {}
|
||||
|
||||
#[cfg(unix)]
|
||||
/// Dynamically remove binds from running Hyprland
|
||||
pub fn unregister_hyprland_binds(config: &VrecConfig) {
|
||||
if !is_hyprland() {
|
||||
|
|
@ -123,6 +140,10 @@ pub fn unregister_hyprland_binds(config: &VrecConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
pub fn unregister_hyprland_binds(_config: &VrecConfig) {}
|
||||
|
||||
#[cfg(unix)]
|
||||
/// Find Hyprland socket2 for live event listening
|
||||
fn get_hyprland_socket2() -> Option<PathBuf> {
|
||||
let sig = env::var("HYPRLAND_INSTANCE_SIGNATURE").ok()?;
|
||||
|
|
@ -139,6 +160,7 @@ fn get_hyprland_socket2() -> Option<PathBuf> {
|
|||
None
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
/// Background watcher for Hyprland config reloads so dynamic binds are never lost
|
||||
pub fn spawn_hyprland_reload_watcher() {
|
||||
if !is_hyprland() {
|
||||
|
|
@ -164,6 +186,9 @@ pub fn spawn_hyprland_reload_watcher() {
|
|||
});
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
pub fn spawn_hyprland_reload_watcher() {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue