[FFmpeg-devel] [PATCH 16/17] avcodec/msmpeg4dec: Make initializing VLCs thread-safe
Andreas Rheinhardt
andreas.rheinhardt at outlook.com
Sat Feb 12 08:41:30 EET 2022
This automatically makes the remaining mpegvideo-decoders
(namely msmpeg4v[1-3], mss2, VC-1, VC-1 Image, WMV-[1-3]
and WMV-3 Image) init-threadsafe.
These were the last native codecs that were not init-threadsafe;
only wrappers for external libraries and for hardware accelerations
are now not init-threadsafe.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
---
The above is based around the assumption that my other patches
marking the VP56 and 8bps decoders as init-threadsafe are already
applied.
Here is an incomplete list of non-native codecs that are not
init-threadsafe yet even after all these patches have been applied
(this list is incomplete because it only contains codecs that
I include in a fairly, but not completely extensive build of mine;
the threading flags stand for frame-slice-other; if all frame-threaded
decoders were init-threadsafe, one could avoid locking around
ff_thread_init() in avcodec_open2(). This only affects libopenjpeg
and I guess that it is init-threadsafe (as are probably most of the
following entries):
Encoder libaom-av1 is not init-threadsafe yet.
Codec supports threading: 0, 0, 1
Encoder libcodec2 is not init-threadsafe yet.
Encoder libfdk_aac is not init-threadsafe yet.
Encoder libgsm is not init-threadsafe yet.
Encoder libgsm_ms is not init-threadsafe yet.
Encoder libilbc is not init-threadsafe yet.
Encoder libmp3lame is not init-threadsafe yet.
Encoder libopencore_amrnb is not init-threadsafe yet.
Encoder libopenjpeg is not init-threadsafe yet.
Codec supports threading: 1, 0, 0
Encoder libopus is not init-threadsafe yet.
Encoder libshine is not init-threadsafe yet.
Encoder libspeex is not init-threadsafe yet.
Encoder libtheora is not init-threadsafe yet.
Encoder libtwolame is not init-threadsafe yet.
Encoder libvorbis is not init-threadsafe yet.
Encoder libvpx is not init-threadsafe yet.
Codec supports threading: 0, 0, 1
Encoder libvpx-vp9 is not init-threadsafe yet.
Codec supports threading: 0, 0, 1
Encoder libwebp_anim is not init-threadsafe yet.
Encoder libwebp is not init-threadsafe yet.
Encoder libx265 is not init-threadsafe yet.
Codec supports threading: 0, 0, 1
Encoder libxavs is not init-threadsafe yet.
Codec supports threading: 0, 0, 1
Encoder libxavs2 is not init-threadsafe yet.
Codec supports threading: 0, 0, 1
Encoder h263_v4l2m2m is not init-threadsafe yet.
Encoder h264_nvenc is not init-threadsafe yet.
Encoder h264_qsv is not init-threadsafe yet.
Encoder h264_v4l2m2m is not init-threadsafe yet.
Encoder h264_vaapi is not init-threadsafe yet.
Encoder hevc_nvenc is not init-threadsafe yet.
Encoder hevc_qsv is not init-threadsafe yet.
Encoder hevc_v4l2m2m is not init-threadsafe yet.
Encoder hevc_vaapi is not init-threadsafe yet.
Encoder mjpeg_qsv is not init-threadsafe yet.
Encoder mjpeg_vaapi is not init-threadsafe yet.
Encoder mpeg2_qsv is not init-threadsafe yet.
Encoder mpeg2_vaapi is not init-threadsafe yet.
Encoder mpeg4_v4l2m2m is not init-threadsafe yet.
Encoder vp8_v4l2m2m is not init-threadsafe yet.
Encoder vp8_vaapi is not init-threadsafe yet.
Encoder vp9_vaapi is not init-threadsafe yet.
Encoder vp9_qsv is not init-threadsafe yet.
Decoder h263_v4l2m2m is not init-threadsafe yet.
Decoder h264_crystalhd is not init-threadsafe yet.
Decoder h264_v4l2m2m is not init-threadsafe yet.
Decoder h264_qsv is not init-threadsafe yet.
Decoder h264_rkmpp is not init-threadsafe yet.
Decoder hevc_qsv is not init-threadsafe yet.
Decoder hevc_rkmpp is not init-threadsafe yet.
Decoder hevc_v4l2m2m is not init-threadsafe yet.
Decoder mpeg4_crystalhd is not init-threadsafe yet.
Decoder mpeg4_v4l2m2m is not init-threadsafe yet.
Decoder mpeg1_v4l2m2m is not init-threadsafe yet.
Decoder mpeg2_crystalhd is not init-threadsafe yet.
Decoder mpeg2_v4l2m2m is not init-threadsafe yet.
Decoder mpeg2_qsv is not init-threadsafe yet.
Decoder msmpeg4_crystalhd is not init-threadsafe yet.
Decoder vc1_crystalhd is not init-threadsafe yet.
Decoder vc1_qsv is not init-threadsafe yet.
Decoder vc1_v4l2m2m is not init-threadsafe yet.
Decoder vp8_rkmpp is not init-threadsafe yet.
Decoder vp8_v4l2m2m is not init-threadsafe yet.
Decoder vp9_rkmpp is not init-threadsafe yet.
Decoder vp9_v4l2m2m is not init-threadsafe yet.
Decoder wmv3_crystalhd is not init-threadsafe yet.
Decoder libaribb24 is not init-threadsafe yet.
Decoder libcelt is not init-threadsafe yet.
Decoder libcodec2 is not init-threadsafe yet.
Decoder libdavs2 is not init-threadsafe yet.
Codec supports threading: 0, 0, 1
Decoder libgsm is not init-threadsafe yet.
Decoder libgsm_ms is not init-threadsafe yet.
Decoder libilbc is not init-threadsafe yet.
Decoder libopencore_amrnb is not init-threadsafe yet.
Decoder libopencore_amrwb is not init-threadsafe yet.
Decoder libopenjpeg is not init-threadsafe yet.
Codec supports threading: 1, 0, 0
Decoder libopus is not init-threadsafe yet.
Decoder libspeex is not init-threadsafe yet.
Decoder libuavs3d is not init-threadsafe yet.
Codec supports threading: 0, 0, 1
Decoder libvorbis is not init-threadsafe yet.
Decoder libvpx is not init-threadsafe yet.
Codec supports threading: 0, 0, 1
Decoder libvpx-vp9 is not init-threadsafe yet.
Codec supports threading: 0, 0, 1
Decoder libzvbi_teletextdec is not init-threadsafe yet.
Decoder libaom-av1 is not init-threadsafe yet.
Codec supports threading: 0, 0, 1
Decoder av1_cuvid is not init-threadsafe yet.
Decoder av1_qsv is not init-threadsafe yet.
Decoder h264_cuvid is not init-threadsafe yet.
Decoder hevc_cuvid is not init-threadsafe yet.
Decoder mjpeg_cuvid is not init-threadsafe yet.
Decoder mjpeg_qsv is not init-threadsafe yet.
Decoder mpeg1_cuvid is not init-threadsafe yet.
Decoder mpeg2_cuvid is not init-threadsafe yet.
Decoder mpeg4_cuvid is not init-threadsafe yet.
Decoder vc1_cuvid is not init-threadsafe yet.
Decoder vp8_cuvid is not init-threadsafe yet.
Decoder vp8_qsv is not init-threadsafe yet.
Decoder vp9_cuvid is not init-threadsafe yet.
Decoder vp9_qsv is not init-threadsafe yet.
libavcodec/msmpeg4dec.c | 47 ++++++++++++++++++++++++-----------------
libavcodec/mss2.c | 1 +
libavcodec/vc1dec.c | 4 ++++
libavcodec/wmv2dec.c | 2 +-
4 files changed, 34 insertions(+), 20 deletions(-)
diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c
index 3d2dcb9429..ba72c7ee50 100644
--- a/libavcodec/msmpeg4dec.c
+++ b/libavcodec/msmpeg4dec.c
@@ -22,6 +22,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/thread.h"
+
#include "avcodec.h"
#include "internal.h"
#include "mpegutils.h"
@@ -292,22 +294,10 @@ static int msmpeg4v34_decode_mb(MpegEncContext *s, int16_t block[6][64])
}
/* init all vlc decoding tables */
-av_cold int ff_msmpeg4_decode_init(AVCodecContext *avctx)
+static av_cold void msmpeg4_decode_init_static(void)
{
- MpegEncContext *s = avctx->priv_data;
- static volatile int done = 0;
- int ret;
MVTable *mv;
- if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
- return ret;
-
- if (ff_h263_decode_init(avctx) < 0)
- return -1;
-
- ff_msmpeg4_common_init(s);
-
- if (!done) {
INIT_FIRST_VLC_RL(ff_rl_table[0], 642);
INIT_FIRST_VLC_RL(ff_rl_table[1], 1104);
INIT_FIRST_VLC_RL(ff_rl_table[2], 554);
@@ -372,8 +362,21 @@ av_cold int ff_msmpeg4_decode_init(AVCodecContext *avctx)
INIT_VLC_STATIC(&ff_inter_intra_vlc, INTER_INTRA_VLC_BITS, 4,
&ff_table_inter_intra[0][1], 2, 1,
&ff_table_inter_intra[0][0], 2, 1, 8);
- done = 1;
- }
+}
+
+av_cold int ff_msmpeg4_decode_init(AVCodecContext *avctx)
+{
+ static AVOnce init_static_once = AV_ONCE_INIT;
+ MpegEncContext *s = avctx->priv_data;
+ int ret;
+
+ if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
+ return ret;
+
+ if (ff_h263_decode_init(avctx) < 0)
+ return -1;
+
+ ff_msmpeg4_common_init(s);
switch(s->msmpeg4_version){
case 1:
@@ -394,6 +397,8 @@ av_cold int ff_msmpeg4_decode_init(AVCodecContext *avctx)
s->slice_height= s->mb_height; //to avoid 1/0 if the first frame is not a keyframe
+ ff_thread_once(&init_static_once, msmpeg4_decode_init_static);
+
return 0;
}
@@ -866,7 +871,8 @@ const AVCodec ff_msmpeg4v1_decoder = {
.close = ff_h263_decode_end,
.decode = ff_h263_decode_frame,
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
- .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
+ FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
.max_lowres = 3,
.pix_fmts = (const enum AVPixelFormat[]) {
AV_PIX_FMT_YUV420P,
@@ -884,7 +890,8 @@ const AVCodec ff_msmpeg4v2_decoder = {
.close = ff_h263_decode_end,
.decode = ff_h263_decode_frame,
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
- .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
+ FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
.max_lowres = 3,
.pix_fmts = (const enum AVPixelFormat[]) {
AV_PIX_FMT_YUV420P,
@@ -902,7 +909,8 @@ const AVCodec ff_msmpeg4v3_decoder = {
.close = ff_h263_decode_end,
.decode = ff_h263_decode_frame,
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
- .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
+ FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
.max_lowres = 3,
.pix_fmts = (const enum AVPixelFormat[]) {
AV_PIX_FMT_YUV420P,
@@ -920,7 +928,8 @@ const AVCodec ff_wmv1_decoder = {
.close = ff_h263_decode_end,
.decode = ff_h263_decode_frame,
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
- .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
+ FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
.max_lowres = 3,
.pix_fmts = (const enum AVPixelFormat[]) {
AV_PIX_FMT_YUV420P,
diff --git a/libavcodec/mss2.c b/libavcodec/mss2.c
index d7a19f6ad2..3b756c9399 100644
--- a/libavcodec/mss2.c
+++ b/libavcodec/mss2.c
@@ -855,4 +855,5 @@ const AVCodec ff_mss2_decoder = {
.close = mss2_decode_end,
.decode = mss2_decode_frame,
.capabilities = AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
};
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index 7ed5133cfa..7568dfc332 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -1209,6 +1209,7 @@ const AVCodec ff_vc1_decoder = {
.decode = vc1_decode_frame,
.flush = ff_mpeg_flush,
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
.pix_fmts = vc1_hwaccel_pixfmt_list_420,
.hw_configs = (const AVCodecHWConfigInternal *const []) {
#if CONFIG_VC1_DXVA2_HWACCEL
@@ -1246,6 +1247,7 @@ const AVCodec ff_wmv3_decoder = {
.decode = vc1_decode_frame,
.flush = ff_mpeg_flush,
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
.pix_fmts = vc1_hwaccel_pixfmt_list_420,
.hw_configs = (const AVCodecHWConfigInternal *const []) {
#if CONFIG_WMV3_DXVA2_HWACCEL
@@ -1283,6 +1285,7 @@ const AVCodec ff_wmv3image_decoder = {
.close = ff_vc1_decode_end,
.decode = vc1_decode_frame,
.capabilities = AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
.flush = vc1_sprite_flush,
.pix_fmts = (const enum AVPixelFormat[]) {
AV_PIX_FMT_YUV420P,
@@ -1302,6 +1305,7 @@ const AVCodec ff_vc1image_decoder = {
.close = ff_vc1_decode_end,
.decode = vc1_decode_frame,
.capabilities = AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
.flush = vc1_sprite_flush,
.pix_fmts = (const enum AVPixelFormat[]) {
AV_PIX_FMT_YUV420P,
diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c
index 7518088b6a..71c948df23 100644
--- a/libavcodec/wmv2dec.c
+++ b/libavcodec/wmv2dec.c
@@ -567,7 +567,7 @@ const AVCodec ff_wmv2_decoder = {
.close = wmv2_decode_end,
.decode = ff_h263_decode_frame,
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
- .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NONE },
};
--
2.32.0
More information about the ffmpeg-devel
mailing list