summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2010-02-09 20:28:42 +0000
committerReinhard Tartler <siretart@tauware.de>2010-02-09 20:28:42 +0000
commite5bea45df76a4888e37bc33f8cc803ec15d3ab7b (patch)
treed1827a645579e4bd7530569dab54971fa9116c04
parent9e3935dfd8c68608534206859b16239a652db37f (diff)
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--Changelog2
-rw-r--r--doc/APIchanges8
-rw-r--r--libavcodec/avcodec.h28
-rw-r--r--libavcodec/utils.c40
4 files changed, 76 insertions, 2 deletions
diff --git a/Changelog b/Changelog
index 3d13d8de80..a3d3da02e7 100644
--- a/Changelog
+++ b/Changelog
@@ -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;
+}