diff options
author | Reinhard Tartler <siretart@tauware.de> | 2010-02-09 20:28:42 +0000 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2010-02-09 20:28:42 +0000 |
commit | e5bea45df76a4888e37bc33f8cc803ec15d3ab7b (patch) | |
tree | d1827a645579e4bd7530569dab54971fa9116c04 | |
parent | 9e3935dfd8c68608534206859b16239a652db37f (diff) | |
download | ffmpeg-e5bea45df76a4888e37bc33f8cc803ec15d3ab7b.tar.gz |
Add a lock manager API to libavcodec.
Allows an application to register a callback that manages mutexes
on behalf of FFmpeg.
With this callback registered FFmpeg is fully thread safe.
backport r19025 by andoma
NB: This is a feature backport with little regression potential. It was
requested at FOSDEM 2010 by ben@geexbox.org for use by geexbox and the
enna mediacenter in the upcoming debian/squeeze and ubuntu/lucid
release.
Approved by DonDiego on #ffmpeg-devel
Originally committed as revision 21731 to svn://svn.ffmpeg.org/ffmpeg/branches/0.5
-rw-r--r-- | Changelog | 2 | ||||
-rw-r--r-- | doc/APIchanges | 8 | ||||
-rw-r--r-- | libavcodec/avcodec.h | 28 | ||||
-rw-r--r-- | libavcodec/utils.c | 40 |
4 files changed, 76 insertions, 2 deletions
@@ -12,7 +12,7 @@ version 0.5.1: - (L)GPL license upgrade support - AMR-NB decoding/encoding, AMR-WB decoding via OpenCORE libraries - enable symbol versioning by default for linkers that support it - +- backport av_lockmgr_register(), see doc/APIchanges for details version 0.5: diff --git a/doc/APIchanges b/doc/APIchanges index 07e680a04d..db7e245a09 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -1,3 +1,11 @@ +20090601 - r19025 - lavc 52.30.0 - av_lockmgr_register() + av_lockmgr_register() can be used to register a callback function + that lavc (and in the future, libraries that depend on lavc) can use + to implement mutexes. The application should provide a callback function + the implements the AV_LOCK_* operations described in avcodec.h. + When the lock manager is registered FFmpeg is guaranteed to behave + correct also in a multi-threaded application. + 20090301 - r17682 - lavf 52.31.0 - Generic metadata API This version introduce a new metadata API (see av_metadata_get() and friends). The old API is now deprecated and shouldn't be used anymore. This especially diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index b078bc98c2..0794fbef68 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -30,7 +30,7 @@ #include "libavutil/avutil.h" #define LIBAVCODEC_VERSION_MAJOR 52 -#define LIBAVCODEC_VERSION_MINOR 20 +#define LIBAVCODEC_VERSION_MINOR 21 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ @@ -3344,4 +3344,30 @@ void av_register_hwaccel(AVHWAccel *hwaccel); */ AVHWAccel *av_hwaccel_next(AVHWAccel *hwaccel); + +/** + * Lock operation used by lockmgr + */ +enum AVLockOp { + AV_LOCK_CREATE, ///< Create a mutex + AV_LOCK_OBTAIN, ///< Lock the mutex + AV_LOCK_RELEASE, ///< Unlock the mutex + AV_LOCK_DESTROY, ///< Free mutex resources +}; + +/** + * Register a user provided lock manager supporting the operations + * specified by AVLockOp. \p mutex points to a (void *) where the + * lockmgr should store/get a pointer to a user allocated mutex. It's + * NULL upon AV_LOCK_CREATE and != NULL for all other ops. + * + * @param cb User defined callback. Note: FFmpeg may invoke calls to this + * callback during the call to av_lockmgr_register(). + * Thus, the application must be prepared to handle that. + * If cb is set to NULL the lockmgr will be unregistered. + * Also note that during unregistration the previously registered + * lockmgr callback may also be invoked. + */ +int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)); + #endif /* AVCODEC_AVCODEC_H */ diff --git a/libavcodec/utils.c b/libavcodec/utils.c index b6412a5313..f628774cd7 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -65,6 +65,8 @@ const uint8_t ff_reverse[256]={ }; static int volatile entangled_thread_counter=0; +int (*ff_lockmgr_cb)(void **mutex, enum AVLockOp op); +static void *codec_mutex; void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size) { @@ -420,6 +422,12 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) { int ret= -1; + /* If there is a user-supplied mutex locking routine, call it. */ + if (ff_lockmgr_cb) { + if ((*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN)) + return -1; + } + entangled_thread_counter++; if(entangled_thread_counter != 1){ av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n"); @@ -464,6 +472,11 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) ret=0; end: entangled_thread_counter--; + + /* Release any user-supplied mutex. */ + if (ff_lockmgr_cb) { + (*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE); + } return ret; } @@ -583,6 +596,12 @@ int avcodec_decode_subtitle(AVCodecContext *avctx, AVSubtitle *sub, int avcodec_close(AVCodecContext *avctx) { + /* If there is a user-supplied mutex locking routine, call it. */ + if (ff_lockmgr_cb) { + if ((*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN)) + return -1; + } + entangled_thread_counter++; if(entangled_thread_counter != 1){ av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n"); @@ -598,6 +617,11 @@ int avcodec_close(AVCodecContext *avctx) av_freep(&avctx->priv_data); avctx->codec = NULL; entangled_thread_counter--; + + /* Release any user-supplied mutex. */ + if (ff_lockmgr_cb) { + (*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE); + } return 0; } @@ -1152,3 +1176,19 @@ AVHWAccel *ff_find_hwaccel(enum CodecID codec_id, enum PixelFormat pix_fmt) } return NULL; } + +int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) +{ + if (ff_lockmgr_cb) { + if (ff_lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY)) + return -1; + } + + ff_lockmgr_cb = cb; + + if (ff_lockmgr_cb) { + if (ff_lockmgr_cb(&codec_mutex, AV_LOCK_CREATE)) + return -1; + } + return 0; +} |