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
This commit is contained in:
parent
9e3935dfd8
commit
e5bea45df7
@ -12,7 +12,7 @@ version 0.5.1:
|
|||||||
- (L)GPL license upgrade support
|
- (L)GPL license upgrade support
|
||||||
- AMR-NB decoding/encoding, AMR-WB decoding via OpenCORE libraries
|
- AMR-NB decoding/encoding, AMR-WB decoding via OpenCORE libraries
|
||||||
- enable symbol versioning by default for linkers that support it
|
- enable symbol versioning by default for linkers that support it
|
||||||
|
- backport av_lockmgr_register(), see doc/APIchanges for details
|
||||||
|
|
||||||
|
|
||||||
version 0.5:
|
version 0.5:
|
||||||
|
@ -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
|
20090301 - r17682 - lavf 52.31.0 - Generic metadata API
|
||||||
This version introduce a new metadata API (see av_metadata_get() and friends).
|
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
|
The old API is now deprecated and shouldn't be used anymore. This especially
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include "libavutil/avutil.h"
|
#include "libavutil/avutil.h"
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_MAJOR 52
|
#define LIBAVCODEC_VERSION_MAJOR 52
|
||||||
#define LIBAVCODEC_VERSION_MINOR 20
|
#define LIBAVCODEC_VERSION_MINOR 21
|
||||||
#define LIBAVCODEC_VERSION_MICRO 0
|
#define LIBAVCODEC_VERSION_MICRO 0
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
#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);
|
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 */
|
#endif /* AVCODEC_AVCODEC_H */
|
||||||
|
@ -65,6 +65,8 @@ const uint8_t ff_reverse[256]={
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int volatile entangled_thread_counter=0;
|
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)
|
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;
|
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++;
|
entangled_thread_counter++;
|
||||||
if(entangled_thread_counter != 1){
|
if(entangled_thread_counter != 1){
|
||||||
av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n");
|
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;
|
ret=0;
|
||||||
end:
|
end:
|
||||||
entangled_thread_counter--;
|
entangled_thread_counter--;
|
||||||
|
|
||||||
|
/* Release any user-supplied mutex. */
|
||||||
|
if (ff_lockmgr_cb) {
|
||||||
|
(*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,6 +596,12 @@ int avcodec_decode_subtitle(AVCodecContext *avctx, AVSubtitle *sub,
|
|||||||
|
|
||||||
int avcodec_close(AVCodecContext *avctx)
|
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++;
|
entangled_thread_counter++;
|
||||||
if(entangled_thread_counter != 1){
|
if(entangled_thread_counter != 1){
|
||||||
av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n");
|
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);
|
av_freep(&avctx->priv_data);
|
||||||
avctx->codec = NULL;
|
avctx->codec = NULL;
|
||||||
entangled_thread_counter--;
|
entangled_thread_counter--;
|
||||||
|
|
||||||
|
/* Release any user-supplied mutex. */
|
||||||
|
if (ff_lockmgr_cb) {
|
||||||
|
(*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1152,3 +1176,19 @@ AVHWAccel *ff_find_hwaccel(enum CodecID codec_id, enum PixelFormat pix_fmt)
|
|||||||
}
|
}
|
||||||
return NULL;
|
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;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user