use crate::{
DecoderError, DecoderEvent, EncodedInputChunk, EncodedOutputChunk, InputFrame, OutputFrame,
VulkanEncoderError,
parser::{
decoder_instructions::compile_to_decoder_instructions,
h264::{AccessUnit, H264Parser},
reference_manager::ReferenceContext,
},
vulkan_decoder::{FrameSorter, VulkanDecoder},
vulkan_encoder::VulkanEncoder,
};
pub struct WgpuTexturesDecoder {
pub(crate) vulkan_decoder: VulkanDecoder<'static>,
pub(crate) parser: H264Parser,
pub(crate) reference_ctx: ReferenceContext,
pub(crate) frame_sorter: FrameSorter<wgpu::Texture>,
}
impl WgpuTexturesDecoder {
pub fn decode(
&mut self,
frame: EncodedInputChunk<'_>,
) -> Result<Vec<OutputFrame<wgpu::Texture>>, DecoderError> {
self.process_event(DecoderEvent::DecodeChunk(frame))
}
pub fn flush(&mut self) -> Result<Vec<OutputFrame<wgpu::Texture>>, DecoderError> {
self.process_event(DecoderEvent::Flush)
}
pub fn process_event(
&mut self,
event: DecoderEvent<'_>,
) -> Result<Vec<OutputFrame<wgpu::Texture>>, DecoderError> {
match event {
DecoderEvent::DecodeChunk(chunk) => {
let nalus = self.parser.parse(chunk.data, chunk.pts)?;
self.decode_access_units(nalus)
}
DecoderEvent::SignalFrameEnd => {
let access_units = self.parser.flush()?;
self.decode_access_units(access_units)
}
DecoderEvent::SignalDataLoss => {
self.reference_ctx.mark_missed_frames();
Ok(Vec::new())
}
DecoderEvent::Flush => {
let access_units = self.parser.flush()?;
let mut frames = self.decode_access_units(access_units)?;
frames.append(&mut self.frame_sorter.flush());
Ok(frames)
}
}
}
fn decode_access_units(
&mut self,
access_units: Vec<AccessUnit>,
) -> Result<Vec<OutputFrame<wgpu::Texture>>, DecoderError> {
let instructions = compile_to_decoder_instructions(&mut self.reference_ctx, access_units)?;
let unsorted_frames = self.vulkan_decoder.decode_to_wgpu_textures(&instructions)?;
let sorted_frames = self.frame_sorter.put_frames(unsorted_frames);
Ok(sorted_frames)
}
}
pub struct WgpuTexturesEncoder {
pub(crate) vulkan_encoder: VulkanEncoder<'static>,
}
impl WgpuTexturesEncoder {
pub fn encode(
&mut self,
frame: InputFrame<wgpu::Texture>,
force_keyframe: bool,
) -> Result<EncodedOutputChunk<Vec<u8>>, VulkanEncoderError> {
self.vulkan_encoder.encode_texture(frame, force_keyframe)
}
pub fn sps(&self) -> Result<Vec<u8>, VulkanEncoderError> {
self.vulkan_encoder.stream_parameters(true, false)
}
pub fn pps(&self) -> Result<Vec<u8>, VulkanEncoderError> {
self.vulkan_encoder.stream_parameters(false, true)
}
}
#[derive(thiserror::Error, Debug)]
pub enum WgpuInitError {
#[error("Wgpu instance error: {0}")]
WgpuInstanceError(#[from] wgpu::hal::InstanceError),
#[error("Wgpu device error: {0}")]
WgpuDeviceError(#[from] wgpu::hal::DeviceError),
#[error("Wgpu request device error: {0}")]
WgpuRequestDeviceError(#[from] wgpu::RequestDeviceError),
#[error("Cannot create a wgpu adapter")]
WgpuAdapterNotCreated,
}