Skip to main content

moq_audio/
activity.rs

1/// Whether a packet carried coded audio, or none at all.
2///
3/// Rides along with the audio it describes: on [`Frame`](crate::Frame) coming
4/// out of [`decode`](crate::decode), and on
5/// [`encode::Encoded`](crate::encode::Encoded) going in. Codecs without a
6/// discontinuous mode (PCM, AAC) are always [`Active`](Self::Active).
7///
8/// Read off the packet, so a consumer gets the same answer as the publisher and
9/// gets one for senders that are not us. Two things follow from that, and both
10/// are why this reports what arrived rather than what the speaker was doing:
11///
12/// - Opus marks withheld audio but not silence itself. A run of
13///   [`Dtx`](Self::Dtx) is interrupted every few hundred milliseconds by an
14///   ordinarily coded frame of the silence, which reads [`Active`](Self::Active)
15///   because nothing distinguishes it from speech resuming. So audio is never
16///   reported as silence, but silence is reported as audio a frame at a time.
17///   Hold a talking indicator across the gap rather than following it frame by
18///   frame.
19/// - A frame that codes nothing usually means the sender withheld it, but RFC
20///   6716 section 3.2.1 lets one stand for a frame that went missing on the way
21///   instead. A relay that repacketizes loss that way reads as
22///   [`Dtx`](Self::Dtx).
23#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
24#[non_exhaustive]
25pub enum Activity {
26	/// The packet coded audio for this frame.
27	#[default]
28	Active,
29	/// The packet coded no audio for this frame, which the sender does while its
30	/// input is silent.
31	Dtx,
32}
33
34impl Activity {
35	/// Whether the packet coded audio for this frame.
36	pub fn is_active(self) -> bool {
37		matches!(self, Self::Active)
38	}
39
40	/// Whether the packet coded no audio for this frame.
41	pub fn is_dtx(self) -> bool {
42		matches!(self, Self::Dtx)
43	}
44}