@ -34,6 +34,7 @@
# endif
# include "avcodec.h"
# include "hwaccel.h"
# include "internal.h"
# include "pthread_internal.h"
# include "thread.h"
@ -101,6 +102,7 @@ typedef struct PerThreadContext {
int die ; ///< Set when the thread should exit.
int hwaccel_serializing ;
int async_serializing ;
} PerThreadContext ;
/**
@ -116,6 +118,7 @@ typedef struct FrameThreadContext {
* is used .
*/
pthread_mutex_t hwaccel_mutex ;
pthread_mutex_t async_mutex ;
int next_decoding ; ///< The next context to submit a packet to.
int next_finished ; ///< The next context to return output from.
@ -191,6 +194,11 @@ static attribute_align_arg void *frame_worker_thread(void *arg)
pthread_mutex_unlock ( & p - > parent - > hwaccel_mutex ) ;
}
if ( p - > async_serializing ) {
p - > async_serializing = 0 ;
pthread_mutex_unlock ( & p - > parent - > async_mutex ) ;
}
atomic_store ( & p - > state , STATE_INPUT_READY ) ;
pthread_mutex_lock ( & p - > progress_mutex ) ;
@ -414,7 +422,11 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
FrameThreadContext * fctx = avctx - > internal - > thread_ctx ;
int finished = fctx - > next_finished ;
PerThreadContext * p ;
int err ;
int err , ret ;
/* release the async lock, permitting blocked hwaccel threads to
* go forward while we are in this function */
pthread_mutex_unlock ( & fctx - > async_mutex ) ;
/*
* Submit a packet to the next decoding thread .
@ -422,9 +434,11 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
p = & fctx - > threads [ fctx - > next_decoding ] ;
err = update_context_from_user ( p - > avctx , avctx ) ;
if ( err ) return err ;
if ( err )
goto finish ;
err = submit_packet ( p , avpkt ) ;
if ( err ) return err ;
if ( err )
goto finish ;
/*
* If we ' re still receiving the initial packets , don ' t return a frame .
@ -434,8 +448,10 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
if ( fctx - > next_decoding > = ( avctx - > thread_count - 1 ) ) fctx - > delaying = 0 ;
* got_picture_ptr = 0 ;
if ( avpkt - > size )
return avpkt - > size ;
if ( avpkt - > size ) {
ret = avpkt - > size ;
goto finish ;
}
}
/*
@ -477,7 +493,12 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
fctx - > next_finished = finished ;
/* return the size of the consumed packet if no error occurred */
return ( p - > result > = 0 ) ? avpkt - > size : p - > result ;
ret = ( p - > result > = 0 ) ? avpkt - > size : p - > result ;
finish :
pthread_mutex_lock ( & fctx - > async_mutex ) ;
if ( err < 0 )
return err ;
return ret ;
}
void ff_thread_report_progress ( ThreadFrame * f , int n , int field )
@ -532,6 +553,13 @@ void ff_thread_finish_setup(AVCodecContext *avctx) {
p - > hwaccel_serializing = 1 ;
}
/* this assumes that no hwaccel calls happen before ff_thread_finish_setup() */
if ( avctx - > hwaccel & &
! ( avctx - > hwaccel - > caps_internal & HWACCEL_CAP_ASYNC_SAFE ) ) {
p - > async_serializing = 1 ;
pthread_mutex_lock ( & p - > parent - > async_mutex ) ;
}
pthread_mutex_lock ( & p - > progress_mutex ) ;
atomic_store ( & p - > state , STATE_SETUP_FINISHED ) ;
@ -545,6 +573,8 @@ static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count
{
int i ;
pthread_mutex_unlock ( & fctx - > async_mutex ) ;
for ( i = 0 ; i < thread_count ; i + + ) {
PerThreadContext * p = & fctx - > threads [ i ] ;
@ -555,6 +585,8 @@ static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count
pthread_mutex_unlock ( & p - > progress_mutex ) ;
}
}
pthread_mutex_lock ( & fctx - > async_mutex ) ;
}
void ff_frame_thread_free ( AVCodecContext * avctx , int thread_count )
@ -613,6 +645,10 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
av_freep ( & fctx - > threads ) ;
pthread_mutex_destroy ( & fctx - > buffer_mutex ) ;
pthread_mutex_destroy ( & fctx - > hwaccel_mutex ) ;
pthread_mutex_unlock ( & fctx - > async_mutex ) ;
pthread_mutex_destroy ( & fctx - > async_mutex ) ;
av_freep ( & avctx - > internal - > thread_ctx ) ;
}
@ -655,6 +691,10 @@ int ff_frame_thread_init(AVCodecContext *avctx)
pthread_mutex_init ( & fctx - > buffer_mutex , NULL ) ;
pthread_mutex_init ( & fctx - > hwaccel_mutex , NULL ) ;
pthread_mutex_init ( & fctx - > async_mutex , NULL ) ;
pthread_mutex_lock ( & fctx - > async_mutex ) ;
fctx - > delaying = 1 ;
for ( i = 0 ; i < thread_count ; i + + ) {