[FFmpeg-devel] [PATCH 2/2] av_lockmgr_register defines behavior on failure.

Manfred Georg mgeorg at google.com
Wed Oct 1 00:20:43 CEST 2014


The register function now specifies that the user callback should
leave things in the same state that it found them on failure but
that failure to destroy is ignored by ffmpeg.  The register
function is also now explicit about its behavior on failure (it now
unregisters the previous callback and destroys all mutex).
---
 libavcodec/avcodec.h | 24 +++++++++++++++---------
 libavcodec/utils.c   | 31 +++++++++++++++++++++----------
 2 files changed, 36 insertions(+), 19 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 94e82f7..69e7012 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -5120,16 +5120,22 @@ enum AVLockOp {
 
 /**
  * Register a user provided lock manager supporting the operations
- * specified by AVLockOp. 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.
+ * specified by AVLockOp.  The "mutex" argument to the function points
+ * to a (void *) where the lockmgr should store/get a pointer to a user
+ * allocated mutex.  It is NULL upon AV_LOCK_CREATE and equal to the
+ * value left by the last call for all other ops.  If the lock manager
+ * is unable to perform the op then it should leave the mutex in the same
+ * state as when it was called.  However, when called with AV_LOCK_DESTROY
+ * the mutex will always be assumed to have been successfully destroyed.
+ * If av_lockmgr_register succeeds it will return 0, if it fails it will
+ * return -1 and destroy all mutex and unregister all callbacks.
+ *
+ * @param cb User defined callback.  FFmpeg invokes calls to this
+ *           callback and the previously registered callback during the
+ *           call to av_lockmgr_register().  The callback will be used to
+ *           create more than one mutex; however, it is legal for all the
+ *           created mutex to use the same underlying locking mechanism.
  *           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));
 
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 778bdc6..717c5b1 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -3457,22 +3457,33 @@ AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel)
 int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op))
 {
     if (lockmgr_cb) {
-        if (lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY))
-            return -1;
-        if (lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY))
-            return -1;
-        codec_mutex = NULL;
-        avformat_mutex = NULL;
+        // There is no good way to rollback a failure to destroy the
+        // mutex, so we ignore failures.
+        lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY);
+        lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY);
     }
 
-    lockmgr_cb = cb;
+    lockmgr_cb = NULL;
+    codec_mutex = NULL;
+    avformat_mutex = NULL;
 
-    if (lockmgr_cb) {
-        if (lockmgr_cb(&codec_mutex, AV_LOCK_CREATE))
+    if (cb) {
+        void *new_codec_mutex = NULL;
+        void *new_avformat_mutex = NULL;
+        if (cb(&new_codec_mutex, AV_LOCK_CREATE)) {
             return -1;
-        if (lockmgr_cb(&avformat_mutex, AV_LOCK_CREATE))
+        }
+        if (cb(&new_avformat_mutex, AV_LOCK_CREATE))
+        {
+            // Ignore failures to destroy the newly created mutex.
+            cb(&new_codec_mutex, AV_LOCK_DESTROY);
             return -1;
+        }
+        lockmgr_cb = cb;
+        codec_mutex = new_codec_mutex;
+        avformat_mutex = new_avformat_mutex;
     }
+
     return 0;
 }
 
-- 
2.1.0.rc2.206.gedb03e5



More information about the ffmpeg-devel mailing list