arcly_stream/codec/
mod.rs1mod bitreader;
26pub mod parser;
27
28#[cfg(test)]
29pub(crate) mod testutil;
30
31pub use parser::{CodecConfig, CodecParser, VideoParams};
32
33#[cfg(feature = "_nal")]
34pub mod nal;
35
36#[cfg(feature = "codec-h264")]
37#[cfg_attr(docsrs, doc(cfg(feature = "codec-h264")))]
38pub mod h264;
39
40#[cfg(feature = "codec-h265")]
41#[cfg_attr(docsrs, doc(cfg(feature = "codec-h265")))]
42pub mod h265;
43
44#[cfg(feature = "codec-vvc")]
45#[cfg_attr(docsrs, doc(cfg(feature = "codec-vvc")))]
46pub mod vvc;
47
48#[cfg(feature = "codec-av1")]
49#[cfg_attr(docsrs, doc(cfg(feature = "codec-av1")))]
50pub mod av1;
51
52#[cfg(feature = "codec-av1")]
53pub(crate) mod obu;
54
55#[cfg(feature = "codec-vp9")]
56#[cfg_attr(docsrs, doc(cfg(feature = "codec-vp9")))]
57pub mod vp9;
58
59#[cfg(feature = "codec-aac")]
60#[cfg_attr(docsrs, doc(cfg(feature = "codec-aac")))]
61pub mod aac;
62
63#[cfg(feature = "codec-aac")]
65pub use aac::{parse_adts, AdtsHeader};
66#[cfg(feature = "codec-h264")]
67pub use h264::{annexb_to_avcc, avcc_to_annexb, iter_nals_annexb, parse_sps, SpsInfo};
68
69pub mod dispatch {
75 use super::*;
76 use crate::CodecId;
77
78 #[allow(unused_variables)]
80 pub fn parse_config(codec: CodecId, data: &[u8]) -> Option<VideoParams> {
81 match codec {
82 #[cfg(feature = "codec-h264")]
83 CodecId::H264 => <h264::H264 as CodecParser>::parse_config(data),
84 #[cfg(feature = "codec-h265")]
85 CodecId::H265 => <h265::H265 as CodecParser>::parse_config(data),
86 #[cfg(feature = "codec-vvc")]
87 CodecId::VVC => <vvc::Vvc as CodecParser>::parse_config(data),
88 #[cfg(feature = "codec-av1")]
89 CodecId::AV1 => <av1::Av1 as CodecParser>::parse_config(data),
90 #[cfg(feature = "codec-vp9")]
91 CodecId::VP9 => <vp9::Vp9 as CodecParser>::parse_config(data),
92 _ => None,
93 }
94 }
95
96 #[allow(unused_variables)]
98 pub fn is_random_access_point(codec: CodecId, data: &[u8]) -> bool {
99 match codec {
100 #[cfg(feature = "codec-h264")]
101 CodecId::H264 => <h264::H264 as CodecParser>::is_random_access_point(data),
102 #[cfg(feature = "codec-h265")]
103 CodecId::H265 => <h265::H265 as CodecParser>::is_random_access_point(data),
104 #[cfg(feature = "codec-vvc")]
105 CodecId::VVC => <vvc::Vvc as CodecParser>::is_random_access_point(data),
106 #[cfg(feature = "codec-av1")]
107 CodecId::AV1 => <av1::Av1 as CodecParser>::is_random_access_point(data),
108 #[cfg(feature = "codec-vp9")]
109 CodecId::VP9 => <vp9::Vp9 as CodecParser>::is_random_access_point(data),
110 _ => false,
111 }
112 }
113
114 #[allow(unused_variables)]
124 pub fn parameter_sets(codec: CodecId, annexb: &[u8]) -> Option<bytes::Bytes> {
125 use crate::codec::nal::iter_nals;
126 let is_param_set = |nal: &[u8]| -> bool {
127 let Some(&b0) = nal.first() else { return false };
128 match codec {
129 #[cfg(feature = "codec-h264")]
130 CodecId::H264 => matches!(b0 & 0x1f, h264::NAL_SPS | h264::NAL_PPS),
131 #[cfg(feature = "codec-h265")]
132 CodecId::H265 => {
133 matches!(
134 (b0 >> 1) & 0x3f,
135 h265::NAL_VPS | h265::NAL_SPS | h265::NAL_PPS
136 )
137 }
138 _ => false,
139 }
140 };
141 let mut out = Vec::new();
142 for nal in iter_nals(annexb) {
143 if is_param_set(nal) {
144 out.extend_from_slice(&[0, 0, 0, 1]);
145 out.extend_from_slice(nal);
146 }
147 }
148 (!out.is_empty()).then(|| bytes::Bytes::from(out))
149 }
150
151 #[allow(unused_variables)]
153 pub fn hls_codec_string(codec: CodecId, params: &VideoParams) -> Option<String> {
154 match codec {
155 #[cfg(feature = "codec-h264")]
156 CodecId::H264 => Some(<h264::H264 as CodecParser>::hls_codec_string(params)),
157 #[cfg(feature = "codec-h265")]
158 CodecId::H265 => Some(<h265::H265 as CodecParser>::hls_codec_string(params)),
159 #[cfg(feature = "codec-vvc")]
160 CodecId::VVC => Some(<vvc::Vvc as CodecParser>::hls_codec_string(params)),
161 #[cfg(feature = "codec-av1")]
162 CodecId::AV1 => Some(<av1::Av1 as CodecParser>::hls_codec_string(params)),
163 #[cfg(feature = "codec-vp9")]
164 CodecId::VP9 => Some(<vp9::Vp9 as CodecParser>::hls_codec_string(params)),
165 _ => None,
166 }
167 }
168}