2019-10-12 14:11:13 +00:00
// Copyright (C) 2019 Philippe Normand <philn@igalia.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
2022-01-15 19:18:47 +00:00
//
2022-03-14 08:22:53 +00:00
// SPDX-License-Identifier: MIT OR Apache-2.0
2019-10-12 14:11:13 +00:00
2021-06-03 18:20:54 +00:00
use gst ::glib ;
2019-10-12 14:11:13 +00:00
use gst ::prelude ::* ;
use gst ::subclass ::prelude ::* ;
use gst_video ::prelude ::* ;
use gst_video ::subclass ::prelude ::* ;
2020-11-22 17:21:45 +00:00
use once_cell ::sync ::Lazy ;
2019-10-12 14:11:13 +00:00
use std ::i32 ;
2022-05-11 13:20:37 +00:00
use std ::sync ::{ Mutex , MutexGuard } ;
2022-03-23 10:14:30 +00:00
const DEFAULT_N_THREADS : u32 = 0 ;
const DEFAULT_MAX_FRAME_DELAY : i64 = - 1 ;
2019-10-12 14:11:13 +00:00
2022-02-02 11:59:02 +00:00
struct State {
decoder : dav1d ::Decoder ,
2022-04-04 12:08:30 +00:00
input_state : gst_video ::VideoCodecState < 'static , gst_video ::video_codec_state ::Readable > ,
2019-10-12 14:11:13 +00:00
output_info : Option < gst_video ::VideoInfo > ,
video_meta_supported : bool ,
2022-04-01 18:51:06 +00:00
n_cpus : usize ,
2019-10-12 14:11:13 +00:00
}
2022-03-23 10:14:30 +00:00
// We make our own settings object so we don't have to deal with a Sync impl for dav1d::Settings
struct Settings {
n_threads : u32 ,
max_frame_delay : i64 ,
}
impl Default for Settings {
fn default ( ) -> Self {
Settings {
n_threads : DEFAULT_N_THREADS ,
max_frame_delay : DEFAULT_MAX_FRAME_DELAY ,
}
}
}
2021-03-07 16:22:24 +00:00
#[ derive(Default) ]
2019-10-12 14:11:13 +00:00
pub struct Dav1dDec {
2022-05-11 13:20:37 +00:00
state : Mutex < Option < State > > ,
2022-03-23 10:14:30 +00:00
settings : Mutex < Settings > ,
2019-10-12 14:11:13 +00:00
}
2020-11-22 17:21:45 +00:00
static CAT : Lazy < gst ::DebugCategory > = Lazy ::new ( | | {
gst ::DebugCategory ::new (
2019-10-12 14:11:13 +00:00
" dav1ddec " ,
gst ::DebugColorFlags ::empty ( ) ,
Some ( " Dav1d AV1 decoder " ) ,
2020-11-22 17:21:45 +00:00
)
} ) ;
2019-10-12 14:11:13 +00:00
impl Dav1dDec {
2022-04-01 18:51:06 +00:00
// FIXME: drop this once we have API from dav1d to query this value
// https://code.videolan.org/videolan/dav1d/-/merge_requests/1407
fn estimate_frame_delay ( & self , max_frame_delay : u32 , n_threads : u32 ) -> u32 {
if max_frame_delay > 0 {
std ::cmp ::min ( max_frame_delay , n_threads )
} else {
let n_tc = n_threads as f64 ;
std ::cmp ::min ( 8 , n_tc . sqrt ( ) . ceil ( ) as u32 )
}
}
2022-10-09 13:06:59 +00:00
fn gst_video_format_from_dav1d_picture ( & self , pic : & dav1d ::Picture ) -> gst_video ::VideoFormat {
2019-10-12 14:11:13 +00:00
let bpc = pic . bits_per_component ( ) ;
let format_desc = match ( pic . pixel_layout ( ) , bpc ) {
2022-02-03 11:23:51 +00:00
( dav1d ::PixelLayout ::I400 , Some ( dav1d ::BitsPerComponent ( 8 ) ) ) = > " GRAY8 " ,
#[ cfg(target_endian = " little " ) ]
( dav1d ::PixelLayout ::I400 , Some ( dav1d ::BitsPerComponent ( 16 ) ) ) = > " GRAY16_LE " ,
#[ cfg(target_endian = " big " ) ]
( dav1d ::PixelLayout ::I400 , Some ( dav1d ::BitsPerComponent ( 16 ) ) ) = > " GRAY16_BE " ,
2019-10-12 14:11:13 +00:00
// (dav1d::PixelLayout::I400, Some(dav1d::BitsPerComponent(10))) => "GRAY10_LE32",
( dav1d ::PixelLayout ::I420 , _ ) = > " I420 " ,
( dav1d ::PixelLayout ::I422 , Some ( dav1d ::BitsPerComponent ( 8 ) ) ) = > " Y42B " ,
( dav1d ::PixelLayout ::I422 , _ ) = > " I422 " ,
( dav1d ::PixelLayout ::I444 , _ ) = > " Y444 " ,
2022-02-03 11:23:51 +00:00
( layout , bpc ) = > {
2022-02-21 17:43:46 +00:00
gst ::warning! (
2022-02-03 11:23:51 +00:00
CAT ,
2022-10-09 13:06:59 +00:00
imp : self ,
2022-02-03 11:23:51 +00:00
" Unsupported dav1d format {:?}/{:?} " ,
layout ,
bpc
) ;
2019-10-12 14:11:13 +00:00
return gst_video ::VideoFormat ::Unknown ;
}
} ;
let f = if format_desc . starts_with ( " GRAY " ) {
format_desc . into ( )
} else {
match bpc {
Some ( b ) = > match b . 0 {
8 = > format_desc . into ( ) ,
_ = > {
let endianness = if cfg! ( target_endian = " little " ) {
" LE "
} else {
" BE "
} ;
format! ( " {f} _ {b} {e} " , f = format_desc , b = b . 0 , e = endianness )
}
} ,
None = > format_desc . into ( ) ,
}
} ;
2021-10-31 10:54:12 +00:00
f . parse ::< gst_video ::VideoFormat > ( ) . unwrap_or_else ( | _ | {
2022-10-09 13:06:59 +00:00
gst ::warning! ( CAT , imp : self , " Unsupported dav1d format: {} " , f ) ;
2019-10-12 14:11:13 +00:00
gst_video ::VideoFormat ::Unknown
} )
}
2022-02-02 14:26:31 +00:00
fn handle_resolution_change < ' s > (
& ' s self ,
2022-05-11 13:20:37 +00:00
mut state_guard : MutexGuard < ' s , Option < State > > ,
2019-10-12 14:11:13 +00:00
pic : & dav1d ::Picture ,
2022-05-11 13:20:37 +00:00
) -> Result < MutexGuard < ' s , Option < State > > , gst ::FlowError > {
let state = state_guard . as_ref ( ) . unwrap ( ) ;
2022-02-02 11:59:02 +00:00
2022-10-09 13:06:59 +00:00
let format = self . gst_video_format_from_dav1d_picture ( pic ) ;
2022-02-02 14:26:31 +00:00
if format = = gst_video ::VideoFormat ::Unknown {
return Err ( gst ::FlowError ::NotNegotiated ) ;
}
let need_negotiate = {
2022-02-02 11:59:02 +00:00
match state . output_info {
2019-10-12 14:11:13 +00:00
Some ( ref i ) = > {
( i . width ( ) ! = pic . width ( ) )
| | ( i . height ( ) ! = pic . height ( ) | | ( i . format ( ) ! = format ) )
}
None = > true ,
}
} ;
2022-02-02 14:26:31 +00:00
if ! need_negotiate {
return Ok ( state_guard ) ;
2019-10-12 14:11:13 +00:00
}
2022-02-02 14:26:31 +00:00
2022-02-21 17:43:46 +00:00
gst ::info! (
2019-10-12 14:11:13 +00:00
CAT ,
2022-10-09 13:06:59 +00:00
imp : self ,
2022-02-02 14:26:31 +00:00
" Negotiating format {:?} picture dimensions {}x{} " ,
format ,
2019-10-12 14:11:13 +00:00
pic . width ( ) ,
pic . height ( )
) ;
2022-02-02 11:59:02 +00:00
2022-04-04 12:08:30 +00:00
let input_state = state . input_state . clone ( ) ;
2022-02-02 11:59:02 +00:00
drop ( state_guard ) ;
2022-10-09 13:06:59 +00:00
let instance = self . instance ( ) ;
2022-02-02 11:59:02 +00:00
let output_state =
2022-10-09 13:06:59 +00:00
instance . set_output_state ( format , pic . width ( ) , pic . height ( ) , Some ( & input_state ) ) ? ;
instance . negotiate ( output_state ) ? ;
let out_state = instance . output_state ( ) . unwrap ( ) ;
2022-02-02 11:59:02 +00:00
2022-05-11 13:20:37 +00:00
state_guard = self . state . lock ( ) . unwrap ( ) ;
2022-02-02 11:59:02 +00:00
let state = state_guard . as_mut ( ) . unwrap ( ) ;
state . output_info = Some ( out_state . info ( ) ) ;
2019-10-12 14:11:13 +00:00
2022-02-02 14:26:31 +00:00
Ok ( state_guard )
2019-10-12 14:11:13 +00:00
}
2022-10-09 13:06:59 +00:00
fn flush_decoder ( & self , state : & mut State ) {
gst ::info! ( CAT , imp : self , " Flushing decoder " ) ;
2022-02-02 14:26:31 +00:00
2022-02-02 11:59:02 +00:00
state . decoder . flush ( ) ;
2019-10-12 14:11:13 +00:00
}
2022-02-02 14:26:31 +00:00
fn send_data (
2019-10-12 14:11:13 +00:00
& self ,
2022-05-11 13:20:37 +00:00
state_guard : & mut MutexGuard < Option < State > > ,
2022-02-02 14:26:31 +00:00
input_buffer : gst ::Buffer ,
2022-02-03 11:02:40 +00:00
frame : gst_video ::VideoCodecFrame ,
2022-02-02 14:26:31 +00:00
) -> Result < std ::ops ::ControlFlow < ( ) , ( ) > , gst ::FlowError > {
2022-02-21 17:43:46 +00:00
gst ::trace! (
2022-02-02 14:26:31 +00:00
CAT ,
2022-10-09 13:06:59 +00:00
imp : self ,
2022-02-02 14:26:31 +00:00
" Sending data to decoder for frame {} " ,
frame . system_frame_number ( )
) ;
2022-02-02 11:59:02 +00:00
let state = state_guard . as_mut ( ) . unwrap ( ) ;
2021-06-04 17:06:24 +00:00
let timestamp = frame . dts ( ) . map ( | ts | * ts as i64 ) ;
let duration = frame . duration ( ) . map ( | d | * d as i64 ) ;
2019-10-12 14:11:13 +00:00
2021-04-12 12:49:54 +00:00
let frame_number = Some ( frame . system_frame_number ( ) as i64 ) ;
2022-02-02 14:26:31 +00:00
2019-10-12 14:11:13 +00:00
let input_data = input_buffer
2022-02-02 14:26:31 +00:00
. into_mapped_buffer_readable ( )
2019-10-12 14:11:13 +00:00
. map_err ( | _ | gst ::FlowError ::Error ) ? ;
2022-02-02 14:26:31 +00:00
match state
. decoder
. send_data ( input_data , frame_number , timestamp , duration )
{
Ok ( ( ) ) = > {
2022-10-09 13:06:59 +00:00
gst ::trace! ( CAT , imp : self , " Decoder returned OK " ) ;
2022-02-02 14:26:31 +00:00
Ok ( std ::ops ::ControlFlow ::Break ( ( ) ) )
}
Err ( err ) if err . is_again ( ) = > {
2022-10-09 13:06:59 +00:00
gst ::trace! ( CAT , imp : self , " Decoder returned EAGAIN " ) ;
2022-02-02 14:26:31 +00:00
Ok ( std ::ops ::ControlFlow ::Continue ( ( ) ) )
}
Err ( err ) = > {
2022-02-21 17:43:46 +00:00
gst ::error! ( CAT , " Sending data failed (error code: {}) " , err ) ;
2022-10-09 13:06:59 +00:00
self . instance ( ) . release_frame ( frame ) ;
2022-06-30 12:44:07 +00:00
gst_video ::video_decoder_error! (
2022-10-09 13:06:59 +00:00
& * self . instance ( ) ,
2022-02-02 14:26:31 +00:00
1 ,
gst ::StreamError ::Decode ,
[ " Sending data failed (error code {}) " , err ]
)
2022-06-30 12:44:07 +00:00
. map ( | _ | std ::ops ::ControlFlow ::Break ( ( ) ) )
2019-10-12 14:11:13 +00:00
}
}
}
2022-02-02 14:26:31 +00:00
fn send_pending_data (
2019-10-12 14:11:13 +00:00
& self ,
2022-05-11 13:20:37 +00:00
state_guard : & mut MutexGuard < Option < State > > ,
2022-02-02 14:26:31 +00:00
) -> Result < std ::ops ::ControlFlow < ( ) , ( ) > , gst ::FlowError > {
2022-10-09 13:06:59 +00:00
gst ::trace! ( CAT , imp : self , " Sending pending data to decoder " ) ;
2022-02-02 14:26:31 +00:00
let state = state_guard . as_mut ( ) . unwrap ( ) ;
match state . decoder . send_pending_data ( ) {
Ok ( ( ) ) = > {
2022-10-09 13:06:59 +00:00
gst ::trace! ( CAT , imp : self , " Decoder returned OK " ) ;
2022-02-02 14:26:31 +00:00
Ok ( std ::ops ::ControlFlow ::Break ( ( ) ) )
}
Err ( err ) if err . is_again ( ) = > {
2022-10-09 13:06:59 +00:00
gst ::trace! ( CAT , imp : self , " Decoder returned EAGAIN " ) ;
2022-02-02 14:26:31 +00:00
Ok ( std ::ops ::ControlFlow ::Continue ( ( ) ) )
}
Err ( err ) = > {
2022-02-21 17:43:46 +00:00
gst ::error! ( CAT , " Sending data failed (error code: {}) " , err ) ;
2022-06-30 12:44:07 +00:00
gst_video ::video_decoder_error! (
2022-10-09 13:06:59 +00:00
& * self . instance ( ) ,
2022-02-02 14:26:31 +00:00
1 ,
gst ::StreamError ::Decode ,
[ " Sending data failed (error code {}) " , err ]
)
2022-06-30 12:44:07 +00:00
. map ( | _ | std ::ops ::ControlFlow ::Break ( ( ) ) )
2022-02-02 14:26:31 +00:00
}
}
}
fn decoded_picture_as_buffer (
& self ,
2022-05-11 13:20:37 +00:00
state_guard : & mut MutexGuard < Option < State > > ,
2019-10-12 14:11:13 +00:00
pic : & dav1d ::Picture ,
output_state : gst_video ::VideoCodecState < gst_video ::video_codec_state ::Readable > ,
) -> Result < gst ::Buffer , gst ::FlowError > {
let mut offsets = vec! [ ] ;
let mut strides = vec! [ ] ;
let mut acc_offset : usize = 0 ;
2022-02-02 11:59:02 +00:00
let state = state_guard . as_mut ( ) . unwrap ( ) ;
let video_meta_supported = state . video_meta_supported ;
2019-10-12 14:11:13 +00:00
2021-04-12 12:49:54 +00:00
let info = output_state . info ( ) ;
2019-10-12 14:11:13 +00:00
let mut out_buffer = gst ::Buffer ::new ( ) ;
let mut_buffer = out_buffer . get_mut ( ) . unwrap ( ) ;
2022-02-03 11:23:51 +00:00
let components = if info . is_yuv ( ) {
const YUV_COMPONENTS : [ dav1d ::PlanarImageComponent ; 3 ] = [
dav1d ::PlanarImageComponent ::Y ,
dav1d ::PlanarImageComponent ::U ,
dav1d ::PlanarImageComponent ::V ,
] ;
& YUV_COMPONENTS [ .. ]
} else if info . is_gray ( ) {
const GRAY_COMPONENTS : [ dav1d ::PlanarImageComponent ; 1 ] =
[ dav1d ::PlanarImageComponent ::Y ] ;
& GRAY_COMPONENTS [ .. ]
} else {
unreachable! ( ) ;
} ;
for & component in components {
let dest_stride : u32 = info . stride ( ) [ component as usize ] . try_into ( ) . unwrap ( ) ;
let plane = pic . plane ( component ) ;
let ( src_stride , height ) = pic . plane_data_geometry ( component ) ;
2019-10-12 14:11:13 +00:00
let mem = if video_meta_supported | | src_stride = = dest_stride {
gst ::Memory ::from_slice ( plane )
} else {
2022-02-21 17:43:46 +00:00
gst ::trace! (
2019-10-12 14:11:13 +00:00
gst ::CAT_PERFORMANCE ,
2022-10-09 13:06:59 +00:00
imp : self ,
2019-10-12 14:11:13 +00:00
" Copying decoded video frame component {:?} " ,
component
) ;
let src_slice = plane . as_ref ( ) ;
let mem = gst ::Memory ::with_size ( ( dest_stride * height ) as usize ) ;
let mut writable_mem = mem
. into_mapped_memory_writable ( )
. map_err ( | _ | gst ::FlowError ::Error ) ? ;
let len = std ::cmp ::min ( src_stride , dest_stride ) as usize ;
for ( out_line , in_line ) in writable_mem
. as_mut_slice ( )
. chunks_exact_mut ( dest_stride . try_into ( ) . unwrap ( ) )
. zip ( src_slice . chunks_exact ( src_stride . try_into ( ) . unwrap ( ) ) )
{
out_line . copy_from_slice ( & in_line [ .. len ] ) ;
}
writable_mem . into_memory ( )
} ;
2021-04-12 12:49:54 +00:00
let mem_size = mem . size ( ) ;
2019-10-12 14:11:13 +00:00
mut_buffer . append_memory ( mem ) ;
strides . push ( src_stride as i32 ) ;
offsets . push ( acc_offset ) ;
acc_offset + = mem_size ;
}
if video_meta_supported {
gst_video ::VideoMeta ::add_full (
out_buffer . get_mut ( ) . unwrap ( ) ,
2020-06-30 09:04:50 +00:00
gst_video ::VideoFrameFlags ::empty ( ) ,
2019-10-12 14:11:13 +00:00
info . format ( ) ,
info . width ( ) ,
info . height ( ) ,
& offsets ,
& strides [ .. ] ,
2020-06-08 08:08:27 +00:00
)
. unwrap ( ) ;
2019-10-12 14:11:13 +00:00
}
let duration = pic . duration ( ) as u64 ;
if duration > 0 {
out_buffer
. get_mut ( )
. unwrap ( )
2022-10-17 17:48:43 +00:00
. set_duration ( duration . nseconds ( ) ) ;
2019-10-12 14:11:13 +00:00
}
2022-02-02 14:26:31 +00:00
2019-10-12 14:11:13 +00:00
Ok ( out_buffer )
}
2022-02-02 14:26:31 +00:00
fn handle_picture < ' s > (
& ' s self ,
2022-05-11 13:20:37 +00:00
mut state_guard : MutexGuard < ' s , Option < State > > ,
2019-10-12 14:11:13 +00:00
pic : & dav1d ::Picture ,
2022-05-11 13:20:37 +00:00
) -> Result < MutexGuard < ' s , Option < State > > , gst ::FlowError > {
2022-10-09 13:06:59 +00:00
gst ::trace! ( CAT , imp : self , " Handling picture {} " , pic . offset ( ) ) ;
2022-02-02 14:26:31 +00:00
2022-10-09 13:06:59 +00:00
state_guard = self . handle_resolution_change ( state_guard , pic ) ? ;
2019-10-12 14:11:13 +00:00
2022-10-09 13:06:59 +00:00
let instance = self . instance ( ) ;
let output_state = instance
2021-04-12 12:49:54 +00:00
. output_state ( )
2019-10-12 14:11:13 +00:00
. expect ( " Output state not set. Shouldn't happen! " ) ;
let offset = pic . offset ( ) as i32 ;
2022-02-02 14:26:31 +00:00
2022-10-09 13:06:59 +00:00
let frame = instance . frame ( offset ) ;
if let Some ( mut frame ) = frame {
2022-02-02 14:26:31 +00:00
let output_buffer =
2022-10-09 13:06:59 +00:00
self . decoded_picture_as_buffer ( & mut state_guard , pic , output_state ) ? ;
2019-10-12 14:11:13 +00:00
frame . set_output_buffer ( output_buffer ) ;
2022-02-02 14:26:31 +00:00
drop ( state_guard ) ;
2022-10-09 13:06:59 +00:00
instance . finish_frame ( frame ) ? ;
2022-05-11 13:20:37 +00:00
Ok ( self . state . lock ( ) . unwrap ( ) )
2019-10-12 14:11:13 +00:00
} else {
2022-10-09 13:06:59 +00:00
gst ::warning! ( CAT , imp : self , " No frame found for offset {} " , offset ) ;
2022-02-02 14:26:31 +00:00
Ok ( state_guard )
2019-10-12 14:11:13 +00:00
}
}
2022-10-09 13:06:59 +00:00
fn drop_decoded_pictures ( & self , state_guard : & mut MutexGuard < Option < State > > ) {
while let Ok ( Some ( pic ) ) = self . pending_pictures ( state_guard ) {
gst ::debug! ( CAT , imp : self , " Dropping picture {} " , pic . offset ( ) ) ;
2019-10-12 14:11:13 +00:00
drop ( pic ) ;
}
}
2021-04-12 12:49:54 +00:00
fn pending_pictures (
2019-10-12 14:11:13 +00:00
& self ,
2022-05-11 13:20:37 +00:00
state_guard : & mut MutexGuard < Option < State > > ,
2022-02-02 14:26:31 +00:00
) -> Result < Option < dav1d ::Picture > , gst ::FlowError > {
2022-10-09 13:06:59 +00:00
gst ::trace! ( CAT , imp : self , " Retrieving pending picture " ) ;
2022-02-02 14:26:31 +00:00
2022-02-02 11:59:02 +00:00
let state = state_guard . as_mut ( ) . unwrap ( ) ;
2022-02-02 14:26:31 +00:00
match state . decoder . get_picture ( ) {
Ok ( pic ) = > {
2022-10-09 13:06:59 +00:00
gst ::trace! ( CAT , imp : self , " Retrieved picture {} " , pic . offset ( ) ) ;
2022-02-02 14:26:31 +00:00
Ok ( Some ( pic ) )
}
Err ( err ) if err . is_again ( ) = > {
2022-10-09 13:06:59 +00:00
gst ::trace! ( CAT , imp : self , " Decoder needs more data " ) ;
2022-02-02 14:26:31 +00:00
Ok ( None )
}
Err ( err ) = > {
2022-02-21 17:43:46 +00:00
gst ::error! (
2022-02-02 14:26:31 +00:00
CAT ,
2022-10-09 13:06:59 +00:00
imp : self ,
2022-02-02 14:26:31 +00:00
" Retrieving decoded picture failed (error code {}) " ,
err
) ;
gst_video ::video_decoder_error! (
2022-10-09 13:06:59 +00:00
& * self . instance ( ) ,
2022-02-02 14:26:31 +00:00
1 ,
gst ::StreamError ::Decode ,
[ " Retrieving decoded picture failed (error code {}) " , err ]
)
. map ( | _ | None )
2019-10-12 14:11:13 +00:00
}
}
}
2022-02-02 14:26:31 +00:00
fn forward_pending_pictures < ' s > (
& ' s self ,
2022-05-11 13:20:37 +00:00
mut state_guard : MutexGuard < ' s , Option < State > > ,
) -> Result < MutexGuard < Option < State > > , gst ::FlowError > {
2022-10-09 13:06:59 +00:00
while let Some ( pic ) = self . pending_pictures ( & mut state_guard ) ? {
state_guard = self . handle_picture ( state_guard , & pic ) ? ;
2019-10-12 14:11:13 +00:00
}
2022-02-02 14:26:31 +00:00
Ok ( state_guard )
2019-10-12 14:11:13 +00:00
}
}
2022-07-22 11:07:49 +00:00
fn video_output_formats ( ) -> impl IntoIterator < Item = gst_video ::VideoFormat > {
[
2022-02-03 11:23:51 +00:00
gst_video ::VideoFormat ::Gray8 ,
#[ cfg(target_endian = " little " ) ]
gst_video ::VideoFormat ::Gray16Le ,
#[ cfg(target_endian = " big " ) ]
gst_video ::VideoFormat ::Gray16Be ,
// #[cfg(target_endian = "little")]
// gst_video::VideoFormat::Gray10Le32,
2019-10-12 14:11:13 +00:00
gst_video ::VideoFormat ::I420 ,
gst_video ::VideoFormat ::Y42b ,
gst_video ::VideoFormat ::Y444 ,
#[ cfg(target_endian = " little " ) ]
gst_video ::VideoFormat ::I42010le ,
#[ cfg(target_endian = " little " ) ]
gst_video ::VideoFormat ::I42210le ,
#[ cfg(target_endian = " little " ) ]
gst_video ::VideoFormat ::Y44410le ,
#[ cfg(target_endian = " big " ) ]
gst_video ::VideoFormat ::I42010be ,
#[ cfg(target_endian = " big " ) ]
gst_video ::VideoFormat ::I42210be ,
#[ cfg(target_endian = " big " ) ]
gst_video ::VideoFormat ::Y44410be ,
#[ cfg(target_endian = " little " ) ]
gst_video ::VideoFormat ::I42012le ,
#[ cfg(target_endian = " little " ) ]
gst_video ::VideoFormat ::I42212le ,
#[ cfg(target_endian = " little " ) ]
gst_video ::VideoFormat ::Y44412le ,
#[ cfg(target_endian = " big " ) ]
gst_video ::VideoFormat ::I42012be ,
#[ cfg(target_endian = " big " ) ]
gst_video ::VideoFormat ::I42212be ,
#[ cfg(target_endian = " big " ) ]
gst_video ::VideoFormat ::Y44412be ,
2022-07-22 11:07:49 +00:00
]
2019-10-12 14:11:13 +00:00
}
2021-03-07 16:22:24 +00:00
#[ glib::object_subclass ]
2019-10-12 14:11:13 +00:00
impl ObjectSubclass for Dav1dDec {
2022-10-23 15:42:58 +00:00
const NAME : & 'static str = " GstDav1dDec " ;
2020-11-15 13:50:12 +00:00
type Type = super ::Dav1dDec ;
2019-10-12 14:11:13 +00:00
type ParentType = gst_video ::VideoDecoder ;
2021-01-21 18:21:29 +00:00
}
2019-10-12 14:11:13 +00:00
2022-03-23 10:14:30 +00:00
impl ObjectImpl for Dav1dDec {
fn properties ( ) -> & 'static [ glib ::ParamSpec ] {
static PROPERTIES : Lazy < Vec < glib ::ParamSpec > > = Lazy ::new ( | | {
vec! [
2022-08-18 12:04:15 +00:00
glib ::ParamSpecUInt ::builder ( " n-threads " )
. nick ( " Number of threads " )
. blurb ( " Number of threads to use while decoding (set to 0 to use number of logical cores) " )
. default_value ( DEFAULT_N_THREADS )
. mutable_ready ( )
. build ( ) ,
glib ::ParamSpecInt64 ::builder ( " max-frame-delay " )
. nick ( " Maximum frame delay " )
. blurb ( " Maximum delay in frames for the decoder (set to 1 for low latency, 0 to be equal to the number of logical cores. -1 to choose between these two based on pipeline liveness) " )
. minimum ( - 1 )
. maximum ( std ::u32 ::MAX . into ( ) )
. default_value ( DEFAULT_MAX_FRAME_DELAY )
. mutable_ready ( )
. build ( ) ,
2022-03-23 10:14:30 +00:00
]
} ) ;
PROPERTIES . as_ref ( )
}
2022-10-09 13:06:59 +00:00
fn set_property ( & self , _id : usize , value : & glib ::Value , pspec : & glib ::ParamSpec ) {
2022-03-23 10:14:30 +00:00
let mut settings = self . settings . lock ( ) . unwrap ( ) ;
match pspec . name ( ) {
" n-threads " = > {
settings . n_threads = value . get ( ) . expect ( " type checked upstream " ) ;
}
" max-frame-delay " = > {
settings . max_frame_delay = value . get ( ) . expect ( " type checked upstream " ) ;
}
_ = > unimplemented! ( ) ,
}
}
2022-10-09 13:06:59 +00:00
fn property ( & self , _id : usize , pspec : & glib ::ParamSpec ) -> glib ::Value {
2022-03-23 10:14:30 +00:00
let settings = self . settings . lock ( ) . unwrap ( ) ;
match pspec . name ( ) {
" n-threads " = > settings . n_threads . to_value ( ) ,
" max-frame-delay " = > settings . max_frame_delay . to_value ( ) ,
_ = > unimplemented! ( ) ,
}
}
}
2019-10-12 14:11:13 +00:00
2021-10-23 08:57:31 +00:00
impl GstObjectImpl for Dav1dDec { }
2021-01-21 18:21:29 +00:00
impl ElementImpl for Dav1dDec {
fn metadata ( ) -> Option < & 'static gst ::subclass ::ElementMetadata > {
static ELEMENT_METADATA : Lazy < gst ::subclass ::ElementMetadata > = Lazy ::new ( | | {
gst ::subclass ::ElementMetadata ::new (
" Dav1d AV1 Decoder " ,
" Codec/Decoder/Video " ,
" Decode AV1 video streams with dav1d " ,
" Philippe Normand <philn@igalia.com> " ,
)
} ) ;
Some ( & * ELEMENT_METADATA )
2019-10-12 14:11:13 +00:00
}
2021-01-21 18:21:29 +00:00
fn pad_templates ( ) -> & 'static [ gst ::PadTemplate ] {
static PAD_TEMPLATES : Lazy < Vec < gst ::PadTemplate > > = Lazy ::new ( | | {
2022-02-02 15:10:30 +00:00
let sink_caps = if gst ::version ( ) > = ( 1 , 19 , 0 , 0 ) {
gst ::Caps ::builder ( " video/x-av1 " )
. field ( " stream-format " , " obu-stream " )
. field ( " alignment " , gst ::List ::new ( [ " frame " , " tu " ] ) )
. build ( )
} else {
gst ::Caps ::builder ( " video/x-av1 " ) . build ( )
} ;
2021-01-21 18:21:29 +00:00
let sink_pad_template = gst ::PadTemplate ::new (
" sink " ,
gst ::PadDirection ::Sink ,
gst ::PadPresence ::Always ,
& sink_caps ,
)
. unwrap ( ) ;
2019-10-12 14:11:13 +00:00
2022-07-22 11:07:49 +00:00
let src_caps = gst_video ::VideoCapsBuilder ::new ( )
. format_list ( video_output_formats ( ) )
2021-11-06 07:34:10 +00:00
. build ( ) ;
2021-01-21 18:21:29 +00:00
let src_pad_template = gst ::PadTemplate ::new (
" src " ,
gst ::PadDirection ::Src ,
gst ::PadPresence ::Always ,
& src_caps ,
)
. unwrap ( ) ;
vec! [ src_pad_template , sink_pad_template ]
} ) ;
PAD_TEMPLATES . as_ref ( )
}
}
2019-10-12 14:11:13 +00:00
impl VideoDecoderImpl for Dav1dDec {
2022-10-09 13:06:59 +00:00
fn src_query ( & self , query : & mut gst ::QueryRef ) -> bool {
2022-05-11 13:59:49 +00:00
match query . view_mut ( ) {
gst ::QueryViewMut ::Latency ( q ) = > {
let state_guard = self . state . lock ( ) . unwrap ( ) ;
let max_frame_delay = {
let settings = self . settings . lock ( ) . unwrap ( ) ;
settings . max_frame_delay
} ;
match * state_guard {
Some ( ref state ) = > match state . output_info {
Some ( ref info ) = > {
let mut upstream_latency = gst ::query ::Latency ::new ( ) ;
2022-10-09 13:06:59 +00:00
if self . instance ( ) . sink_pad ( ) . peer_query ( & mut upstream_latency ) {
2022-05-11 13:59:49 +00:00
let ( live , mut min , mut max ) = upstream_latency . result ( ) ;
// For autodetection: 1 if live, else whatever dav1d gives us
let frame_latency : u64 = if max_frame_delay < 0 & & live {
1
} else {
self . estimate_frame_delay (
max_frame_delay as u32 ,
state . n_cpus as u32 ,
)
. into ( )
} ;
let fps_n = match info . fps ( ) . numer ( ) {
0 = > 30 , // Pretend we're at 30fps if we don't know latency,
n = > n ,
} ;
2022-10-17 17:48:43 +00:00
let latency = frame_latency * ( info . fps ( ) . denom ( ) as u64 ) . seconds ( )
2022-05-11 13:59:49 +00:00
/ ( fps_n as u64 ) ;
2022-10-09 13:06:59 +00:00
gst ::debug! ( CAT , imp : self , " Reporting latency of {} " , latency ) ;
2022-05-11 13:59:49 +00:00
min + = latency ;
max = max . opt_add ( latency ) ;
q . set ( live , min , max ) ;
true
2022-04-01 18:51:06 +00:00
} else {
2022-05-11 13:59:49 +00:00
// peer latency query failed
false
}
2022-04-01 18:51:06 +00:00
}
2022-05-11 13:59:49 +00:00
// output info not available => fps unknown
None = > false ,
} ,
// no state yet
2022-04-01 18:51:06 +00:00
None = > false ,
2022-05-11 13:59:49 +00:00
}
2022-04-01 18:51:06 +00:00
}
2022-10-09 13:06:59 +00:00
_ = > VideoDecoderImplExt ::parent_src_query ( self , query ) ,
2022-04-01 18:51:06 +00:00
}
}
2022-10-09 13:06:59 +00:00
fn stop ( & self ) -> Result < ( ) , gst ::ErrorMessage > {
2022-02-02 11:59:02 +00:00
{
2022-05-11 13:20:37 +00:00
let mut state_guard = self . state . lock ( ) . unwrap ( ) ;
2022-02-02 11:59:02 +00:00
* state_guard = None ;
}
2022-10-09 13:06:59 +00:00
self . parent_stop ( )
2022-02-02 11:59:02 +00:00
}
2019-10-12 14:11:13 +00:00
fn set_format (
& self ,
2022-02-02 11:59:02 +00:00
input_state : & gst_video ::VideoCodecState < 'static , gst_video ::video_codec_state ::Readable > ,
2019-10-12 14:11:13 +00:00
) -> Result < ( ) , gst ::LoggableError > {
2022-05-11 13:20:37 +00:00
let mut state_guard = self . state . lock ( ) . unwrap ( ) ;
2022-04-04 12:08:30 +00:00
let settings = self . settings . lock ( ) . unwrap ( ) ;
let mut decoder_settings = dav1d ::Settings ::new ( ) ;
let max_frame_delay : u32 ;
let n_cpus = num_cpus ::get ( ) ;
2022-10-09 13:06:59 +00:00
gst ::info! ( CAT , imp : self , " Detected {} logical CPUs " , n_cpus ) ;
2022-04-04 12:08:30 +00:00
if settings . max_frame_delay = = - 1 {
let mut latency_query = gst ::query ::Latency ::new ( ) ;
let mut is_live = false ;
2022-10-09 13:06:59 +00:00
if self . instance ( ) . sink_pad ( ) . peer_query ( & mut latency_query ) {
2022-04-04 12:08:30 +00:00
is_live = latency_query . result ( ) . 0 ;
}
max_frame_delay = if is_live { 1 } else { 0 } ;
} else {
max_frame_delay = settings . max_frame_delay . try_into ( ) . unwrap ( ) ;
2019-10-12 14:11:13 +00:00
}
2022-04-04 12:08:30 +00:00
gst ::info! (
CAT ,
2022-10-09 13:06:59 +00:00
imp : self ,
2022-04-04 12:08:30 +00:00
" Creating decoder with n-threads={} and max-frame-delay={} " ,
settings . n_threads ,
max_frame_delay
) ;
decoder_settings . set_n_threads ( settings . n_threads ) ;
decoder_settings . set_max_frame_delay ( max_frame_delay ) ;
let decoder = dav1d ::Decoder ::with_settings ( & decoder_settings ) . map_err ( | err | {
gst ::loggable_error! ( CAT , " Failed to create decoder instance: {} " , err )
} ) ? ;
* state_guard = Some ( State {
decoder ,
input_state : input_state . clone ( ) ,
output_info : None ,
video_meta_supported : false ,
n_cpus ,
} ) ;
2022-10-09 13:06:59 +00:00
self . parent_set_format ( input_state )
2019-10-12 14:11:13 +00:00
}
fn handle_frame (
& self ,
frame : gst_video ::VideoCodecFrame ,
) -> Result < gst ::FlowSuccess , gst ::FlowError > {
2022-02-02 14:26:31 +00:00
let input_buffer = frame
. input_buffer_owned ( )
. expect ( " frame without input buffer " ) ;
{
2022-05-11 13:20:37 +00:00
let mut state_guard = self . state . lock ( ) . unwrap ( ) ;
2022-10-09 13:06:59 +00:00
state_guard = self . forward_pending_pictures ( state_guard ) ? ;
if self . send_data ( & mut state_guard , input_buffer , frame ) ?
2022-02-02 14:26:31 +00:00
= = std ::ops ::ControlFlow ::Continue ( ( ) )
{
loop {
2022-10-09 13:06:59 +00:00
state_guard = self . forward_pending_pictures ( state_guard ) ? ;
if self . send_pending_data ( & mut state_guard ) ? = = std ::ops ::ControlFlow ::Break ( ( ) )
2022-02-02 14:26:31 +00:00
{
break ;
}
}
}
2022-10-09 13:06:59 +00:00
let _state_guard = self . forward_pending_pictures ( state_guard ) ? ;
2019-10-12 14:11:13 +00:00
}
Ok ( gst ::FlowSuccess ::Ok )
}
2022-10-09 13:06:59 +00:00
fn flush ( & self ) -> bool {
gst ::info! ( CAT , imp : self , " Flushing " ) ;
2022-02-02 14:26:31 +00:00
{
2022-05-11 13:20:37 +00:00
let mut state_guard = self . state . lock ( ) . unwrap ( ) ;
2022-04-04 12:08:30 +00:00
if state_guard . is_some ( ) {
2022-05-11 13:20:37 +00:00
let state = state_guard . as_mut ( ) . unwrap ( ) ;
2022-10-09 13:06:59 +00:00
self . flush_decoder ( state ) ;
self . drop_decoded_pictures ( & mut state_guard ) ;
2022-04-04 12:08:30 +00:00
}
2022-02-02 14:26:31 +00:00
}
2019-10-12 14:11:13 +00:00
true
}
2022-10-09 13:06:59 +00:00
fn drain ( & self ) -> Result < gst ::FlowSuccess , gst ::FlowError > {
gst ::info! ( CAT , imp : self , " Draining " ) ;
2022-02-02 14:26:31 +00:00
{
2022-05-11 13:20:37 +00:00
let mut state_guard = self . state . lock ( ) . unwrap ( ) ;
2022-04-04 12:08:30 +00:00
if state_guard . is_some ( ) {
2022-05-11 13:20:37 +00:00
let state = state_guard . as_mut ( ) . unwrap ( ) ;
2022-10-09 13:06:59 +00:00
self . flush_decoder ( state ) ;
let _state_guard = self . forward_pending_pictures ( state_guard ) ? ;
2022-04-04 12:08:30 +00:00
}
2022-02-02 14:26:31 +00:00
}
2022-10-09 13:06:59 +00:00
self . parent_drain ( )
2019-10-12 14:11:13 +00:00
}
2022-10-09 13:06:59 +00:00
fn finish ( & self ) -> Result < gst ::FlowSuccess , gst ::FlowError > {
gst ::info! ( CAT , imp : self , " Finishing " ) ;
2022-02-02 14:26:31 +00:00
{
2022-05-11 13:20:37 +00:00
let mut state_guard = self . state . lock ( ) . unwrap ( ) ;
2022-04-04 12:08:30 +00:00
if state_guard . is_some ( ) {
2022-05-11 13:20:37 +00:00
let state = state_guard . as_mut ( ) . unwrap ( ) ;
2022-10-09 13:06:59 +00:00
self . flush_decoder ( state ) ;
let _state_guard = self . forward_pending_pictures ( state_guard ) ? ;
2022-04-04 12:08:30 +00:00
}
2022-02-02 14:26:31 +00:00
}
2022-10-09 13:06:59 +00:00
self . parent_finish ( )
2019-10-12 14:11:13 +00:00
}
fn decide_allocation (
& self ,
2022-01-22 10:18:02 +00:00
query : & mut gst ::query ::Allocation ,
2021-12-06 17:11:06 +00:00
) -> Result < ( ) , gst ::LoggableError > {
2022-02-02 11:59:02 +00:00
{
2022-05-11 13:20:37 +00:00
let mut state_guard = self . state . lock ( ) . unwrap ( ) ;
2022-02-02 11:59:02 +00:00
let state = state_guard . as_mut ( ) . unwrap ( ) ;
state . video_meta_supported = query
. find_allocation_meta ::< gst_video ::VideoMeta > ( )
. is_some ( ) ;
}
2019-10-12 14:11:13 +00:00
2022-10-09 13:06:59 +00:00
self . parent_decide_allocation ( query )
2019-10-12 14:11:13 +00:00
}
}