rtc_rtp/extension/video_orientation_extension/
mod.rs

1#[cfg(test)]
2mod video_orientation_extension_test;
3
4use std::convert::{TryFrom, TryInto};
5
6use bytes::BufMut;
7use serde::{Deserialize, Serialize};
8use shared::{
9    error::{Error, Result},
10    marshal::{Marshal, MarshalSize, Unmarshal},
11};
12
13// One byte header size
14pub const VIDEO_ORIENTATION_EXTENSION_SIZE: usize = 1;
15
16/// Coordination of Video Orientation in RTP streams.
17///
18/// Coordination of Video Orientation consists in signaling of the current
19/// orientation of the image captured on the sender side to the receiver for
20/// appropriate rendering and displaying.
21///
22/// C = Camera: indicates the direction of the camera used for this video
23///     stream. It can be used by the MTSI client in receiver to e.g. display
24///     the received video differently depending on the source camera.
25///
26/// 0: Front-facing camera, facing the user. If camera direction is
27///    unknown by the sending MTSI client in the terminal then this is the
28///    default value used.
29/// 1: Back-facing camera, facing away from the user.
30///
31/// F = Flip: indicates a horizontal (left-right flip) mirror operation on
32///     the video as sent on the link.
33///
34///    0                   1
35///    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
36///   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37///   |  ID   | len=0 |0 0 0 0 C F R R|
38///   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39#[derive(PartialEq, Eq, Debug, Default, Copy, Clone, Serialize, Deserialize)]
40pub struct VideoOrientationExtension {
41    pub direction: CameraDirection,
42    pub flip: bool,
43    pub rotation: VideoRotation,
44}
45
46#[derive(Default, PartialEq, Eq, Debug, Copy, Clone, Serialize, Deserialize)]
47pub enum CameraDirection {
48    #[default]
49    Front = 0,
50    Back = 1,
51}
52
53#[derive(Default, PartialEq, Eq, Debug, Copy, Clone, Serialize, Deserialize)]
54pub enum VideoRotation {
55    #[default]
56    Degree0 = 0,
57    Degree90 = 1,
58    Degree180 = 2,
59    Degree270 = 3,
60}
61
62impl MarshalSize for VideoOrientationExtension {
63    fn marshal_size(&self) -> usize {
64        VIDEO_ORIENTATION_EXTENSION_SIZE
65    }
66}
67
68impl Unmarshal for VideoOrientationExtension {
69    fn unmarshal<B>(buf: &mut B) -> Result<Self>
70    where
71        Self: Sized,
72        B: bytes::Buf,
73    {
74        if buf.remaining() < VIDEO_ORIENTATION_EXTENSION_SIZE {
75            return Err(Error::ErrBufferTooSmall);
76        }
77
78        let b = buf.get_u8();
79
80        let c = (b & 0b1000) >> 3;
81        let f = b & 0b0100;
82        let r = b & 0b0011;
83
84        Ok(VideoOrientationExtension {
85            direction: c.try_into()?,
86            flip: f > 0,
87            rotation: r.try_into()?,
88        })
89    }
90}
91
92impl Marshal for VideoOrientationExtension {
93    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
94        let c = (self.direction as u8) << 3;
95        let f = if self.flip { 0b0100 } else { 0 };
96        let r = self.rotation as u8;
97
98        buf.put_u8(c | f | r);
99
100        Ok(VIDEO_ORIENTATION_EXTENSION_SIZE)
101    }
102}
103
104impl TryFrom<u8> for CameraDirection {
105    type Error = shared::error::Error;
106
107    fn try_from(value: u8) -> Result<Self> {
108        match value {
109            0 => Ok(CameraDirection::Front),
110            1 => Ok(CameraDirection::Back),
111            _ => Err(shared::error::Error::Other(format!(
112                "Unhandled camera direction: {value}"
113            ))),
114        }
115    }
116}
117
118impl TryFrom<u8> for VideoRotation {
119    type Error = shared::error::Error;
120
121    fn try_from(value: u8) -> Result<Self> {
122        match value {
123            0 => Ok(VideoRotation::Degree0),
124            1 => Ok(VideoRotation::Degree90),
125            2 => Ok(VideoRotation::Degree180),
126            3 => Ok(VideoRotation::Degree270),
127            _ => Err(shared::error::Error::Other(format!(
128                "Unhandled video rotation: {value}"
129            ))),
130        }
131    }
132}