1
//! POD types for the video-playback surface
2
//! (SUPER_PLAN_2 ยง4 Priority 6 + research).
3
//!
4
//! Same "dumb widget" architecture as camera/screencap
5
//! (`azul_layout::widgets::video::VideoWidget`): a background thread decodes
6
//! the source (vk-video - GPU decode + HTTP-range fetch) and its writeback
7
//! uploads each frame into the shared GL-texture `ImageRef` + recomposites.
8
//! Defined here in `azul-core` so the config crosses the FFI without
9
//! `azul-layout` (or vk-video) as a dependency.
10
//!
11
//! Unlike the camera/screencap configs this carries a `source` string, so
12
//! it's `Clone` but not `Copy`.
13

            
14
use crate::resources::RawImageFormat;
15
use azul_css::{AzString, U8Vec};
16

            
17
/// Where a video widget pulls its H.264/MP4 data from โ€” strongly typed so the
18
/// decode worker matches on it directly (no `RefAny` downcast). Mirrors
19
/// [`crate::screencap::ScreenCaptureSource`].
20
#[repr(C, u8)]
21
#[derive(Debug, Clone, PartialEq)]
22
pub enum VideoSource {
23
    /// An HTTP(S) URL, fetched on the decode thread via an HTTP range request.
24
    Url(AzString),
25
    /// A local filesystem path.
26
    File(AzString),
27
    /// Raw MP4 bytes already in memory.
28
    Bytes(U8Vec),
29
}
30

            
31
impl Default for VideoSource {
32
    fn default() -> Self {
33
        VideoSource::Url(AzString::from_const_str(""))
34
    }
35
}
36

            
37
/// Requested video-playback configuration.
38
#[repr(C)]
39
#[derive(Debug, Clone, PartialEq)]
40
pub struct VideoConfig {
41
    /// Where to load the video from (URL / file path / in-memory bytes).
42
    pub source: VideoSource,
43
    /// Seek / scrub position in seconds. Changing it across a relayout makes the
44
    /// widget's merge callback tell the decode worker to seek (scrubbing
45
    /// timeline) โ€” the decoder survives relayout like the map's tile cache.
46
    pub timestamp: f32,
47
    /// Start playing automatically on mount.
48
    pub autoplay: bool,
49
    /// Restart from the beginning when the stream ends.
50
    pub looping: bool,
51
    /// Texture format the decoder delivers. `BGRA8` is the portable default;
52
    /// `Nv12` (a later `RawImageFormat` addition) is the zero-copy path.
53
    pub output_format: RawImageFormat,
54
}
55

            
56
impl Default for VideoConfig {
57
    fn default() -> Self {
58
        Self {
59
            source: VideoSource::default(),
60
            timestamp: 0.0,
61
            autoplay: true,
62
            looping: false,
63
            output_format: RawImageFormat::BGRA8,
64
        }
65
    }
66
}
67

            
68
impl VideoConfig {
69
    /// A default config playing `source` (autoplay on, no loop, BGRA8, t=0).
70
    pub fn new(source: VideoSource) -> Self {
71
        Self {
72
            source,
73
            ..Self::default()
74
        }
75
    }
76
}
77

            
78
/// One captured or decoded frame - tightly-packed RGBA8 pixels
79
/// (`width * height * 4`). The unit a capture/decode worker produces, the
80
/// `set_on_frame` hook hands to user code (effects / save / send), and (P8)
81
/// azul-meet sends over UDP. Defined here (like [`crate::audio::AudioFrame`])
82
/// so it crosses the FFI without `azul-layout` as a dependency.
83
#[repr(C)]
84
#[derive(Debug, Clone, PartialEq)]
85
pub struct VideoFrame {
86
    /// Frame width in px.
87
    pub width: u32,
88
    /// Frame height in px.
89
    pub height: u32,
90
    /// Tightly-packed RGBA8 pixel bytes (`width * height * 4`).
91
    pub bytes: U8Vec,
92
}
93

            
94
impl VideoFrame {
95
    /// A frame wrapping `bytes` (tightly-packed RGBA8, `width * height * 4`).
96
    pub fn new(width: u32, height: u32, bytes: U8Vec) -> Self {
97
        Self {
98
            width,
99
            height,
100
            bytes,
101
        }
102
    }
103
}
104

            
105
// FFI Option wrapper for a frame-pull hook / accessor. `copy = false` (U8Vec).
106
impl_option!(VideoFrame, OptionVideoFrame, copy = false, [Clone, Debug]);
107

            
108
// FFI `Vec<VideoFrame>` wrapper โ€” the list a batch decode (`DecodedVideo`,
109
// `dll::desktop::extra::video_codec::pipeline`) hands back across the C ABI.
110
// `VideoFrame` derives Debug + Clone + PartialEq, so mirror exactly those Vec
111
// trait impls (no PartialOrd: `VideoFrame` isn't `PartialOrd`).
112
impl_vec!(VideoFrame, VideoFrameVec, VideoFrameVecDestructor, VideoFrameVecDestructorType, VideoFrameVecSlice, OptionVideoFrame);
113
impl_vec_debug!(VideoFrame, VideoFrameVec);
114
impl_vec_clone!(VideoFrame, VideoFrameVec, VideoFrameVecDestructor);
115
impl_vec_partialeq!(VideoFrame, VideoFrameVec);