scythe/scratch/enc.patch

99 lines
4.7 KiB
Diff

--- src/encoder.rs
+++ src/encoder.rs
@@ -6,6 +6,7 @@
codec_ctx: *mut AVCodecContext,
hw_device_ctx: *mut AVBufferRef,
hw_frames_ctx: *mut AVBufferRef,
+ next_pts: i64,
}
impl VaapiEncoder {
@@ -70,6 +71,7 @@
codec_ctx,
hw_device_ctx,
hw_frames_ctx: hw_frames_ref,
+ next_pts: 0,
})
}
}
@@ -77,15 +79,63 @@
pub fn encode_frame(&mut self, frame: &Frame) -> Result<(), String> {
unsafe {
match frame {
- Frame::Raw { width, height, stride, data } => {
- // For Phase 2 X11 fallback:
- // 1. Convert BGRA to NV12 (omitted/mocked for brevity if not using swscale yet)
- // 2. Upload NV12 to a VAAPI AVFrame via av_hwframe_get_buffer and av_hwframe_transfer_data
- // 3. Send to avcodec_send_frame
- println!("VAAPI: Mock encoding Raw CPU frame (X11 fallback). Needs BGRA->NV12 swscale.");
- }
- Frame::DmaBuf { width, height, format, fd, stride, offset } => {
- // For Phase 2 Wayland zero-copy:
- // 1. Populate AVDRMFrameDescriptor with the FD and modifier.
- // 2. Create an AVFrame with format AV_PIX_FMT_DRM_PRIME.
- // 3. Use av_hwframe_map to map it to AV_PIX_FMT_VAAPI.
- // 4. Send to avcodec_send_frame.
- println!("VAAPI: Mock encoding DMA-BUF frame (Wayland zero-copy). FD: {}", fd);
+ Frame::Raw { width, height, stride: in_stride, data } => {
+ let mut bgra_frame = av_frame_alloc();
+ (*bgra_frame).format = AVPixelFormat::AV_PIX_FMT_BGRA as i32;
+ (*bgra_frame).width = *width as i32;
+ (*bgra_frame).height = *height as i32;
+ av_frame_get_buffer(bgra_frame, 32);
+
+ let bgra_stride = (*bgra_frame).linesize[0] as usize;
+ for y in 0..(*height as usize) {
+ let src_row = &data[y * (*in_stride as usize) .. y * (*in_stride as usize) + (*width as usize) * 4];
+ let dst_row = std::slice::from_raw_parts_mut(
+ (*bgra_frame).data[0].add(y * bgra_stride),
+ (*width as usize) * 4
+ );
+ dst_row.copy_from_slice(src_row);
+ }
+
+ let mut nv12_frame = av_frame_alloc();
+ (*nv12_frame).format = AVPixelFormat::AV_PIX_FMT_NV12 as i32;
+ (*nv12_frame).width = *width as i32;
+ (*nv12_frame).height = *height as i32;
+ av_frame_get_buffer(nv12_frame, 32);
+
+ let sws_ctx = sws_getContext(
+ *width as i32, *height as i32, AVPixelFormat::AV_PIX_FMT_BGRA,
+ *width as i32, *height as i32, AVPixelFormat::AV_PIX_FMT_NV12,
+ SWS_BILINEAR, ptr::null_mut(), ptr::null_mut(), ptr::null_mut()
+ );
+
+ sws_scale(
+ sws_ctx,
+ (*bgra_frame).data.as_ptr() as *const *const u8,
+ (*bgra_frame).linesize.as_ptr(),
+ 0,
+ *height as i32,
+ (*nv12_frame).data.as_ptr(),
+ (*nv12_frame).linesize.as_ptr()
+ );
+ sws_freeContext(sws_ctx);
+
+ let mut hw_frame = av_frame_alloc();
+ av_hwframe_get_buffer(self.hw_frames_ctx, hw_frame, 0);
+ av_hwframe_transfer_data(hw_frame, nv12_frame, 0);
+
+ (*hw_frame).pts = self.next_pts;
+ self.next_pts += 1;
+
+ if avcodec_send_frame(self.codec_ctx, hw_frame) >= 0 {
+ let mut pkt = av_packet_alloc();
+ while avcodec_receive_packet(self.codec_ctx, pkt) >= 0 {
+ println!("VAAPI: encoded packet of size {}", (*pkt).size);
+ av_packet_unref(pkt);
+ }
+ av_packet_free(&mut pkt);
+ }
+ av_frame_free(&mut hw_frame);
+ av_frame_free(&mut nv12_frame);
+ av_frame_free(&mut bgra_frame);
+ }
+ Frame::DmaBuf { width: _, height: _, format: _, fd, stride: _, offset: _ } => {
+ println!("VAAPI: Mock encoding DMA-BUF frame (Wayland zero-copy). FD: {}", fd);
}
}