#[cfg(test)]
mod video_orientation_extension_test;
use std::convert::{TryFrom, TryInto};
use bytes::BufMut;
use serde::{Deserialize, Serialize};
use util::marshal::Unmarshal;
use util::{Marshal, MarshalSize};
use crate::Error;
pub const VIDEO_ORIENTATION_EXTENSION_SIZE: usize = 1;
#[derive(PartialEq, Eq, Debug, Default, Copy, Clone, Serialize, Deserialize)]
pub struct VideoOrientationExtension {
pub direction: CameraDirection,
pub flip: bool,
pub rotation: VideoRotation,
}
#[derive(Default, PartialEq, Eq, Debug, Copy, Clone, Serialize, Deserialize)]
pub enum CameraDirection {
#[default]
Front = 0,
Back = 1,
}
#[derive(Default, PartialEq, Eq, Debug, Copy, Clone, Serialize, Deserialize)]
pub enum VideoRotation {
#[default]
Degree0 = 0,
Degree90 = 1,
Degree180 = 2,
Degree270 = 3,
}
impl MarshalSize for VideoOrientationExtension {
fn marshal_size(&self) -> usize {
VIDEO_ORIENTATION_EXTENSION_SIZE
}
}
impl Unmarshal for VideoOrientationExtension {
fn unmarshal<B>(buf: &mut B) -> util::Result<Self>
where
Self: Sized,
B: bytes::Buf,
{
if buf.remaining() < VIDEO_ORIENTATION_EXTENSION_SIZE {
return Err(Error::ErrBufferTooSmall.into());
}
let b = buf.get_u8();
let c = (b & 0b1000) >> 3;
let f = b & 0b0100;
let r = b & 0b0011;
Ok(VideoOrientationExtension {
direction: c.try_into()?,
flip: f > 0,
rotation: r.try_into()?,
})
}
}
impl Marshal for VideoOrientationExtension {
fn marshal_to(&self, mut buf: &mut [u8]) -> util::Result<usize> {
let c = (self.direction as u8) << 3;
let f = if self.flip { 0b0100 } else { 0 };
let r = self.rotation as u8;
buf.put_u8(c | f | r);
Ok(VIDEO_ORIENTATION_EXTENSION_SIZE)
}
}
impl TryFrom<u8> for CameraDirection {
type Error = util::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(CameraDirection::Front),
1 => Ok(CameraDirection::Back),
_ => Err(util::Error::Other(format!(
"Unhandled camera direction: {value}"
))),
}
}
}
impl TryFrom<u8> for VideoRotation {
type Error = util::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(VideoRotation::Degree0),
1 => Ok(VideoRotation::Degree90),
2 => Ok(VideoRotation::Degree180),
3 => Ok(VideoRotation::Degree270),
_ => Err(util::Error::Other(format!(
"Unhandled video rotation: {value}"
))),
}
}
}