1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! Video decode config and [`VideoDecoder`] trait.
#![forbid(unsafe_code)]
use crate::error::DecodeError;
use mediaway_common::{
CodecKind, GpuDeviceHandle, Packet, PixelFormat, Rational, StreamInfo, VideoFrame,
};
/// How the caller prefers to receive decoded frames.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum VideoOutputPreference {
/// Prefer GPU handles ([`mediaway_common::VideoFrameStorage::Gpu`]).
#[default]
ZeroCopyGpu,
/// Accept CPU frames (may imply copy/readback — backends must document cost).
CpuFramesOk,
}
/// Parameters for opening a video decoder session.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VideoDecoderConfig {
/// Input codec (Stage 1 Windows: [`CodecKind::H264`]).
pub codec: CodecKind,
/// Expected width (may be refined from bitstream).
pub width: u32,
/// Expected height (may be refined from bitstream).
pub height: u32,
/// Timestamp timebase for input packets and output frames.
pub time_base: Rational,
/// Preferred output pixel format when the backend converts.
pub pixel_format: PixelFormat,
/// Output path preference (Zero-Copy vs CPU).
pub output: VideoOutputPreference,
/// GPU device handle when [`VideoOutputPreference::ZeroCopyGpu`].
///
/// `None` means unset (Zero-Copy open fails). `Some(GpuDeviceHandle::DirectX11(handle))`
/// specifies the device that owns returned textures; other variants select other backends
/// (see [`GpuDeviceHandle`](mediaway_common::GpuDeviceHandle) for platform options).
pub gpu_device: Option<GpuDeviceHandle>,
/// Codec configuration bytes (AVCC / extradata); may be empty until first keyframe.
pub extra_data: mediaway_common::Bytes,
}
impl VideoDecoderConfig {
/// H.264 defaults for a given size. Prefer setting fields explicitly in apps.
#[must_use]
pub const fn h264(width: u32, height: u32, time_base: Rational) -> Self {
Self {
codec: CodecKind::H264,
width,
height,
time_base,
pixel_format: PixelFormat::Nv12,
output: VideoOutputPreference::ZeroCopyGpu,
gpu_device: None,
extra_data: mediaway_common::Bytes::new(),
}
}
/// HEVC defaults for a given size. Prefer setting fields explicitly in apps.
#[must_use]
pub const fn hevc(width: u32, height: u32, time_base: Rational) -> Self {
Self {
codec: CodecKind::Hevc,
width,
height,
time_base,
pixel_format: PixelFormat::Nv12,
output: VideoOutputPreference::ZeroCopyGpu,
gpu_device: None,
extra_data: mediaway_common::Bytes::new(),
}
}
/// AV1 defaults for a given size. Prefer setting fields explicitly in apps.
#[must_use]
pub const fn av1(width: u32, height: u32, time_base: Rational) -> Self {
Self {
codec: CodecKind::Av1,
width,
height,
time_base,
pixel_format: PixelFormat::Nv12,
output: VideoOutputPreference::ZeroCopyGpu,
gpu_device: None,
extra_data: mediaway_common::Bytes::new(),
}
}
/// VP9 defaults for a given size. Prefer setting fields explicitly in apps.
#[must_use]
pub const fn vp9(width: u32, height: u32, time_base: Rational) -> Self {
Self {
codec: CodecKind::Vp9,
width,
height,
time_base,
pixel_format: PixelFormat::Nv12,
output: VideoOutputPreference::ZeroCopyGpu,
gpu_device: None,
extra_data: mediaway_common::Bytes::new(),
}
}
}
/// Streaming hardware (or backend) video decoder.
///
/// Push packets, then [`poll_frame`](VideoDecoder::poll_frame) until `Ok(None)`,
/// then [`flush`](VideoDecoder::flush) and drain again.
pub trait VideoDecoder {
/// Stream metadata (updated when size / extradata become available).
fn stream_info(&self) -> &StreamInfo;
/// Submit one compressed packet. May produce zero or more frames (drain via poll).
///
/// # Errors
///
/// Returns [`DecodeError`] when the packet is rejected or the session failed.
fn push_packet(&mut self, packet: &Packet) -> Result<(), DecodeError>;
/// Pull the next decoded frame, if any.
///
/// For GPU frames, the texture remains valid until the next
/// [`push_packet`](Self::push_packet) / [`poll_frame`](Self::poll_frame) /
/// [`flush`](Self::flush) that recycles the surface (see platform ADR).
///
/// # Errors
///
/// Returns [`DecodeError`] on backend failure.
fn poll_frame(&mut self) -> Result<Option<VideoFrame>, DecodeError>;
/// Signal end-of-input; drain remaining frames with [`poll_frame`](Self::poll_frame).
///
/// # Errors
///
/// Returns [`DecodeError`] on backend failure.
fn flush(&mut self) -> Result<(), DecodeError>;
}