dav1ddec: Clean up state tracking a bit

And especially don't keep a decoder instance around while in Null state.
This commit is contained in:
Sebastian Dröge 2022-02-02 13:59:02 +02:00 committed by Sebastian Dröge
parent 6e28a17280
commit b795c0c392

View file

@ -21,7 +21,8 @@ use std::i32;
use std::sync::Mutex; use std::sync::Mutex;
#[derive(Default)] #[derive(Default)]
struct NegotiationInfos { struct State {
decoder: dav1d::Decoder,
input_state: input_state:
Option<gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>>, Option<gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>>,
output_info: Option<gst_video::VideoInfo>, output_info: Option<gst_video::VideoInfo>,
@ -30,8 +31,7 @@ struct NegotiationInfos {
#[derive(Default)] #[derive(Default)]
pub struct Dav1dDec { pub struct Dav1dDec {
decoder: Mutex<dav1d::Decoder>, state: Mutex<Option<State>>,
negotiation_infos: Mutex<NegotiationInfos>,
} }
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| { static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
@ -93,9 +93,11 @@ impl Dav1dDec {
pic: &dav1d::Picture, pic: &dav1d::Picture,
format: gst_video::VideoFormat, format: gst_video::VideoFormat,
) -> Result<(), gst::FlowError> { ) -> Result<(), gst::FlowError> {
let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().unwrap();
let negotiate = { let negotiate = {
let negotiation_infos = self.negotiation_infos.lock().unwrap(); match state.output_info {
match negotiation_infos.output_info {
Some(ref i) => { Some(ref i) => {
(i.width() != pic.width()) (i.width() != pic.width())
|| (i.height() != pic.height() || (i.format() != format)) || (i.height() != pic.height() || (i.format() != format))
@ -113,24 +115,26 @@ impl Dav1dDec {
pic.width(), pic.width(),
pic.height() pic.height()
); );
let output_state = {
let negotiation_infos = self.negotiation_infos.lock().unwrap(); let input_state = state.input_state.as_ref().cloned();
let input_state = negotiation_infos.input_state.as_ref(); drop(state_guard);
element.set_output_state(format, pic.width(), pic.height(), input_state)
}?; let output_state =
element.set_output_state(format, pic.width(), pic.height(), input_state.as_ref())?;
element.negotiate(output_state)?; element.negotiate(output_state)?;
let out_state = element.output_state().unwrap(); let out_state = element.output_state().unwrap();
{
let mut negotiation_infos = self.negotiation_infos.lock().unwrap(); let mut state_guard = self.state.lock().unwrap();
negotiation_infos.output_info = Some(out_state.info()); let state = state_guard.as_mut().unwrap();
} state.output_info = Some(out_state.info());
Ok(()) Ok(())
} }
fn flush_decoder(&self, _element: &super::Dav1dDec) { fn flush_decoder(&self, _element: &super::Dav1dDec) {
let decoder = self.decoder.lock().unwrap(); let mut state_guard = self.state.lock().unwrap();
decoder.flush(); let state = state_guard.as_mut().unwrap();
state.decoder.flush();
} }
fn decode( fn decode(
@ -139,7 +143,9 @@ impl Dav1dDec {
input_buffer: &gst::BufferRef, input_buffer: &gst::BufferRef,
frame: &gst_video::VideoCodecFrame, frame: &gst_video::VideoCodecFrame,
) -> Result<Vec<(dav1d::Picture, gst_video::VideoFormat)>, gst::FlowError> { ) -> Result<Vec<(dav1d::Picture, gst_video::VideoFormat)>, gst::FlowError> {
let mut decoder = self.decoder.lock().unwrap(); let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().unwrap();
let timestamp = frame.dts().map(|ts| *ts as i64); let timestamp = frame.dts().map(|ts| *ts as i64);
let duration = frame.duration().map(|d| *d as i64); let duration = frame.duration().map(|d| *d as i64);
@ -147,7 +153,11 @@ impl Dav1dDec {
let input_data = input_buffer let input_data = input_buffer
.map_readable() .map_readable()
.map_err(|_| gst::FlowError::Error)?; .map_err(|_| gst::FlowError::Error)?;
let pictures = match decoder.decode(input_data, frame_number, timestamp, duration, || {}) { let pictures =
match state
.decoder
.decode(input_data, frame_number, timestamp, duration, || {})
{
Ok(pictures) => pictures, Ok(pictures) => pictures,
Err(err) => { Err(err) => {
gst_error!(CAT, "Decoding failed (error code: {})", err); gst_error!(CAT, "Decoding failed (error code: {})", err);
@ -183,7 +193,10 @@ impl Dav1dDec {
let mut strides = vec![]; let mut strides = vec![];
let mut acc_offset: usize = 0; let mut acc_offset: usize = 0;
let video_meta_supported = self.negotiation_infos.lock().unwrap().video_meta_supported; let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().unwrap();
let video_meta_supported = state.video_meta_supported;
drop(state_guard);
let info = output_state.info(); let info = output_state.info();
let mut out_buffer = gst::Buffer::new(); let mut out_buffer = gst::Buffer::new();
@ -282,8 +295,10 @@ impl Dav1dDec {
} }
fn drop_decoded_pictures(&self, element: &super::Dav1dDec) { fn drop_decoded_pictures(&self, element: &super::Dav1dDec) {
let mut decoder = self.decoder.lock().unwrap(); let mut state_guard = self.state.lock().unwrap();
while let Ok(pic) = decoder.get_picture() { let state = state_guard.as_mut().unwrap();
while let Ok(pic) = state.decoder.get_picture() {
gst_debug!(CAT, obj: element, "Dropping picture"); gst_debug!(CAT, obj: element, "Dropping picture");
drop(pic); drop(pic);
} }
@ -293,9 +308,11 @@ impl Dav1dDec {
&self, &self,
element: &super::Dav1dDec, element: &super::Dav1dDec,
) -> Result<Vec<(dav1d::Picture, gst_video::VideoFormat)>, gst::FlowError> { ) -> Result<Vec<(dav1d::Picture, gst_video::VideoFormat)>, gst::FlowError> {
let mut decoder = self.decoder.lock().unwrap(); let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().unwrap();
let mut pictures = vec![]; let mut pictures = vec![];
while let Ok(pic) = decoder.get_picture() { while let Ok(pic) = state.decoder.get_picture() {
let format = self.gst_video_format_from_dav1d_picture(element, &pic); let format = self.gst_video_format_from_dav1d_picture(element, &pic);
if format == gst_video::VideoFormat::Unknown { if format == gst_video::VideoFormat::Unknown {
return Err(gst::FlowError::NotNegotiated); return Err(gst::FlowError::NotNegotiated);
@ -418,24 +435,39 @@ impl ElementImpl for Dav1dDec {
impl VideoDecoderImpl for Dav1dDec { impl VideoDecoderImpl for Dav1dDec {
fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> { fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
{ {
let mut infos = self.negotiation_infos.lock().unwrap(); let mut state_guard = self.state.lock().unwrap();
infos.output_info = None; *state_guard = Some(State {
decoder: dav1d::Decoder::new(),
input_state: None,
output_info: None,
video_meta_supported: false,
});
} }
self.parent_start(element) self.parent_start(element)
} }
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
{
let mut state_guard = self.state.lock().unwrap();
*state_guard = None;
}
self.parent_stop(element)
}
fn set_format( fn set_format(
&self, &self,
element: &Self::Type, element: &Self::Type,
state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>, input_state: &gst_video::VideoCodecState<'static, gst_video::video_codec_state::Readable>,
) -> Result<(), gst::LoggableError> { ) -> Result<(), gst::LoggableError> {
{ {
let mut infos = self.negotiation_infos.lock().unwrap(); let mut state_guard = self.state.lock().unwrap();
infos.input_state = Some(state.clone()); let state = state_guard.as_mut().unwrap();
state.input_state = Some(input_state.clone());
} }
self.parent_set_format(element, state) self.parent_set_format(element, input_state)
} }
fn handle_frame( fn handle_frame(
@ -477,9 +509,13 @@ impl VideoDecoderImpl for Dav1dDec {
element: &Self::Type, element: &Self::Type,
query: &mut gst::query::Allocation, query: &mut gst::query::Allocation,
) -> Result<(), gst::LoggableError> { ) -> Result<(), gst::LoggableError> {
self.negotiation_infos.lock().unwrap().video_meta_supported = query {
let mut state_guard = self.state.lock().unwrap();
let state = state_guard.as_mut().unwrap();
state.video_meta_supported = query
.find_allocation_meta::<gst_video::VideoMeta>() .find_allocation_meta::<gst_video::VideoMeta>()
.is_some(); .is_some();
}
self.parent_decide_allocation(element, query) self.parent_decide_allocation(element, query)
} }