media 0.1.0

A pure rust implementation of media framework
Documentation
use std::num::NonZeroU32;

use crate::{
    error::MediaError,
    invalid_param_error,
    media::MediaFrameType,
    media_frame::{Data, MediaFrame, MediaFrameData, MediaFrameDescription, MemoryData, MemoryPlanes, PlaneInformation},
    video::{PixelFormat, VideoFrameDescription},
    DEFAULT_ALIGNMENT,
};

impl<'a> MemoryData<'a> {
    pub fn new_video_data(format: PixelFormat, width: NonZeroU32, height: NonZeroU32) -> Result<Self, MediaError> {
        let (size, planes) = format.calc_data(width.get(), height.get(), DEFAULT_ALIGNMENT);

        Ok(Self {
            data: Data::Owned(vec![0; size as usize]),
            planes,
        })
    }

    pub fn attach_video_data(format: PixelFormat, width: NonZeroU32, height: NonZeroU32, buffer: &'a [u8]) -> Result<Self, MediaError> {
        let (size, planes) = format.calc_data(width.get(), height.get(), 1);

        if buffer.len() != size as usize {
            return Err(MediaError::Invalid("buffer size".to_string()).into());
        }

        Ok(Self {
            data: Data::Borrowed(buffer),
            planes,
        })
    }

    pub fn attach_video_data_with_stride(
        format: PixelFormat,
        width: NonZeroU32,
        height: NonZeroU32,
        stride: NonZeroU32,
        buffer: &'a [u8],
    ) -> Result<Self, MediaError> {
        if stride.get() < width.get() {
            return Err(invalid_param_error!(stride).into());
        }

        let (size, planes) = format.calc_data_with_stride(height.get(), stride.get());

        if buffer.len() != size as usize {
            return Err(MediaError::Invalid("buffer size".to_string()).into());
        }

        let data = Self {
            data: Data::Borrowed(buffer),
            planes,
        };

        Ok(data)
    }

    pub fn attach_packed_video_data(format: PixelFormat, height: NonZeroU32, stride: NonZeroU32, buffer: &'a [u8]) -> Result<Self, MediaError> {
        if !format.is_packed() {
            return Err(MediaError::Unsupported("format".to_string()).into());
        }

        if buffer.len() != (stride.get() * height.get()) as usize {
            return Err(MediaError::Invalid("buffer size".to_string()).into());
        }

        let planes = MemoryPlanes::from_slice(&[PlaneInformation::Video(stride.get(), height.get())]);

        let data = Self {
            data: Data::Borrowed(buffer),
            planes,
        };

        Ok(data)
    }
}

impl<'a> MediaFrame<'a> {
    pub fn new_video_frame(desc: VideoFrameDescription) -> Result<Self, MediaError> {
        let data = MemoryData::new_video_data(desc.format, desc.width, desc.height)?;

        Ok(Self {
            media_type: MediaFrameType::Video,
            source: None,
            timestamp: 0,
            desc: MediaFrameDescription::Video(desc),
            metadata: None,
            data: MediaFrameData::Memory(data),
        })
    }

    fn from_data(desc: VideoFrameDescription, data: MemoryData<'a>) -> Self {
        Self {
            media_type: MediaFrameType::Video,
            source: None,
            timestamp: 0,
            desc: MediaFrameDescription::Video(desc),
            metadata: None,
            data: MediaFrameData::Memory(data),
        }
    }

    pub fn from_data_buffer(desc: VideoFrameDescription, buffer: &'a [u8]) -> Result<Self, MediaError> {
        let data = MemoryData::attach_video_data(desc.format, desc.width, desc.height, buffer)?;

        Ok(Self::from_data(desc, data))
    }

    pub fn from_data_buffer_with_stride(desc: VideoFrameDescription, stride: NonZeroU32, buffer: &'a [u8]) -> Result<Self, MediaError> {
        let data = MemoryData::attach_video_data_with_stride(desc.format, desc.width, desc.height, stride, buffer)?;

        Ok(Self::from_data(desc, data))
    }

    pub fn from_packed_data_buffer(desc: VideoFrameDescription, stride: NonZeroU32, buffer: &'a [u8]) -> Result<Self, MediaError> {
        let data = MemoryData::attach_packed_video_data(desc.format, desc.height, stride, buffer)?;

        Ok(Self::from_data(desc, data))
    }
}