@ -89,6 +89,7 @@ typedef struct PerThreadContext {
atomic_int state ;
# if FF_API_THREAD_SAFE_CALLBACKS
/**
* Array of frames passed to ff_thread_release_buffer ( ) .
* Frames are released after all threads referencing them are finished .
@ -102,6 +103,7 @@ typedef struct PerThreadContext {
const enum AVPixelFormat * available_formats ; ///< Format array for get_format()
enum AVPixelFormat result_format ; ///< get_format() result
# endif
int die ; ///< Set when the thread should exit.
@ -137,8 +139,10 @@ typedef struct FrameThreadContext {
*/
} FrameThreadContext ;
# if FF_API_THREAD_SAFE_CALLBACKS
# define THREAD_SAFE_CALLBACKS(avctx) \
( ( avctx ) - > thread_safe_callbacks | | ( avctx ) - > get_buffer2 = = avcodec_default_get_buffer2 )
# endif
static void async_lock ( FrameThreadContext * fctx )
{
@ -178,8 +182,14 @@ static attribute_align_arg void *frame_worker_thread(void *arg)
if ( p - > die ) break ;
if ( ! codec - > update_thread_context & & THREAD_SAFE_CALLBACKS ( avctx ) )
FF_DISABLE_DEPRECATION_WARNINGS
if ( ! codec - > update_thread_context
# if FF_API_THREAD_SAFE_CALLBACKS
& & THREAD_SAFE_CALLBACKS ( avctx )
# endif
)
ff_thread_finish_setup ( avctx ) ;
FF_ENABLE_DEPRECATION_WARNINGS
/* If a decoder supports hwaccel, then it must call ff_get_format().
* Since that call must happen before ff_thread_finish_setup ( ) , the
@ -344,7 +354,11 @@ static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src)
dst - > frame_number = src - > frame_number ;
dst - > reordered_opaque = src - > reordered_opaque ;
# if FF_API_THREAD_SAFE_CALLBACKS
FF_DISABLE_DEPRECATION_WARNINGS
dst - > thread_safe_callbacks = src - > thread_safe_callbacks ;
FF_ENABLE_DEPRECATION_WARNINGS
# endif
if ( src - > slice_count & & src - > slice_offset ) {
if ( dst - > slice_count < src - > slice_count ) {
@ -360,6 +374,7 @@ static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src)
return 0 ;
}
# if FF_API_THREAD_SAFE_CALLBACKS
/// Releases the buffers that this decoding thread was the last user of.
static void release_delayed_buffers ( PerThreadContext * p )
{
@ -380,6 +395,7 @@ static void release_delayed_buffers(PerThreadContext *p)
pthread_mutex_unlock ( & fctx - > buffer_mutex ) ;
}
}
# endif
static int submit_packet ( PerThreadContext * p , AVCodecContext * user_avctx ,
AVPacket * avpkt )
@ -403,7 +419,9 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx,
( p - > avctx - > debug & FF_DEBUG_THREADS ) ! = 0 ,
memory_order_relaxed ) ;
# if FF_API_THREAD_SAFE_CALLBACKS
release_delayed_buffers ( p ) ;
# endif
if ( prev_thread ) {
int err ;
@ -433,6 +451,8 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx,
pthread_cond_signal ( & p - > input_cond ) ;
pthread_mutex_unlock ( & p - > mutex ) ;
# if FF_API_THREAD_SAFE_CALLBACKS
FF_DISABLE_DEPRECATION_WARNINGS
/*
* If the client doesn ' t have a thread - safe get_buffer ( ) ,
* then decoding threads call back to the main thread ,
@ -466,6 +486,8 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx,
pthread_mutex_unlock ( & p - > progress_mutex ) ;
}
}
FF_ENABLE_DEPRECATION_WARNINGS
# endif
fctx - > prev_thread = p ;
fctx - > next_decoding + + ;
@ -657,7 +679,7 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
{
FrameThreadContext * fctx = avctx - > internal - > thread_ctx ;
const AVCodec * codec = avctx - > codec ;
int i , j ;
int i ;
park_frame_worker_threads ( fctx , thread_count ) ;
@ -690,7 +712,9 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
if ( codec - > close & & p - > avctx )
codec - > close ( p - > avctx ) ;
# if FF_API_THREAD_SAFE_CALLBACKS
release_delayed_buffers ( p ) ;
# endif
av_frame_free ( & p - > frame ) ;
}
@ -704,9 +728,11 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
pthread_cond_destroy ( & p - > output_cond ) ;
av_packet_unref ( & p - > avpkt ) ;
for ( j = 0 ; j < p - > released_buffers_allocated ; j + + )
# if FF_API_THREAD_SAFE_CALLBACKS
for ( int j = 0 ; j < p - > released_buffers_allocated ; j + + )
av_frame_free ( & p - > released_buffers [ j ] ) ;
av_freep ( & p - > released_buffers ) ;
# endif
if ( p - > avctx ) {
if ( codec - > priv_class )
@ -889,7 +915,9 @@ void ff_thread_flush(AVCodecContext *avctx)
av_frame_unref ( p - > frame ) ;
p - > result = 0 ;
# if FF_API_THREAD_SAFE_CALLBACKS
release_delayed_buffers ( p ) ;
# endif
if ( avctx - > codec - > flush )
avctx - > codec - > flush ( p - > avctx ) ;
@ -899,10 +927,16 @@ void ff_thread_flush(AVCodecContext *avctx)
int ff_thread_can_start_frame ( AVCodecContext * avctx )
{
PerThreadContext * p = avctx - > internal - > thread_ctx ;
FF_DISABLE_DEPRECATION_WARNINGS
if ( ( avctx - > active_thread_type & FF_THREAD_FRAME ) & & atomic_load ( & p - > state ) ! = STATE_SETTING_UP & &
( avctx - > codec - > update_thread_context | | ! THREAD_SAFE_CALLBACKS ( avctx ) ) ) {
( avctx - > codec - > update_thread_context
# if FF_API_THREAD_SAFE_CALLBACKS
| | ! THREAD_SAFE_CALLBACKS ( avctx )
# endif
) ) {
return 0 ;
}
FF_ENABLE_DEPRECATION_WARNINGS
return 1 ;
}
@ -916,8 +950,14 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int
if ( ! ( avctx - > active_thread_type & FF_THREAD_FRAME ) )
return ff_get_buffer ( avctx , f - > f , flags ) ;
FF_DISABLE_DEPRECATION_WARNINGS
if ( atomic_load ( & p - > state ) ! = STATE_SETTING_UP & &
( avctx - > codec - > update_thread_context | | ! THREAD_SAFE_CALLBACKS ( avctx ) ) ) {
( avctx - > codec - > update_thread_context
# if FF_API_THREAD_SAFE_CALLBACKS
| | ! THREAD_SAFE_CALLBACKS ( avctx )
# endif
) ) {
FF_ENABLE_DEPRECATION_WARNINGS
av_log ( avctx , AV_LOG_ERROR , " get_buffer() cannot be called after ff_thread_finish_setup() \n " ) ;
return - 1 ;
}
@ -935,6 +975,10 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int
}
pthread_mutex_lock ( & p - > parent - > buffer_mutex ) ;
# if !FF_API_THREAD_SAFE_CALLBACKS
err = ff_get_buffer ( avctx , f - > f , flags ) ;
# else
FF_DISABLE_DEPRECATION_WARNINGS
if ( THREAD_SAFE_CALLBACKS ( avctx ) ) {
err = ff_get_buffer ( avctx , f - > f , flags ) ;
} else {
@ -954,6 +998,8 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int
}
if ( ! THREAD_SAFE_CALLBACKS ( avctx ) & & ! avctx - > codec - > update_thread_context )
ff_thread_finish_setup ( avctx ) ;
FF_ENABLE_DEPRECATION_WARNINGS
# endif
if ( err )
av_buffer_unref ( & f - > progress ) ;
@ -962,6 +1008,8 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int
return err ;
}
# if FF_API_THREAD_SAFE_CALLBACKS
FF_DISABLE_DEPRECATION_WARNINGS
enum AVPixelFormat ff_thread_get_format ( AVCodecContext * avctx , const enum AVPixelFormat * fmt )
{
enum AVPixelFormat res ;
@ -987,6 +1035,8 @@ enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixe
return res ;
}
FF_ENABLE_DEPRECATION_WARNINGS
# endif
int ff_thread_get_buffer ( AVCodecContext * avctx , ThreadFrame * f , int flags )
{
@ -998,12 +1048,16 @@ int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags)
void ff_thread_release_buffer ( AVCodecContext * avctx , ThreadFrame * f )
{
# if FF_API_THREAD_SAFE_CALLBACKS
FF_DISABLE_DEPRECATION_WARNINGS
PerThreadContext * p = avctx - > internal - > thread_ctx ;
FrameThreadContext * fctx ;
AVFrame * dst ;
int ret = 0 ;
int can_direct_free = ! ( avctx - > active_thread_type & FF_THREAD_FRAME ) | |
THREAD_SAFE_CALLBACKS ( avctx ) ;
FF_ENABLE_DEPRECATION_WARNINGS
# endif
if ( ! f - > f )
return ;
@ -1014,6 +1068,9 @@ void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f)
av_buffer_unref ( & f - > progress ) ;
f - > owner [ 0 ] = f - > owner [ 1 ] = NULL ;
# if !FF_API_THREAD_SAFE_CALLBACKS
av_frame_unref ( f - > f ) ;
# else
// when the frame buffers are not allocated, just reset it to clean state
if ( can_direct_free | | ! f - > f - > buf [ 0 ] ) {
av_frame_unref ( f - > f ) ;
@ -1055,4 +1112,5 @@ fail:
memset ( f - > f - > extended_buf , 0 , f - > f - > nb_extended_buf * sizeof ( * f - > f - > extended_buf ) ) ;
av_frame_unref ( f - > f ) ;
}
# endif
}