99 lines
4.7 KiB
Diff
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);
|
|
}
|
|
}
|