diff options
Diffstat (limited to 'libswscale/utils.c')
-rw-r--r-- | libswscale/utils.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/libswscale/utils.c b/libswscale/utils.c index 235a846809..25051ead72 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -49,6 +49,7 @@ #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/slicethread.h" #include "libavutil/thread.h" #include "libavutil/aarch64/cpu.h" #include "libavutil/ppc/cpu.h" @@ -871,6 +872,18 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], const AVPixFmtDescriptor *desc_src; int need_reinit = 0; + if (c->nb_slice_ctx) { + for (int i = 0; i < c->nb_slice_ctx; i++) { + int ret = sws_setColorspaceDetails(c->slice_ctx[i], inv_table, + srcRange, table, dstRange, + brightness, contrast, saturation); + if (ret < 0) + return ret; + } + + return 0; + } + handle_formats(c); desc_dst = av_pix_fmt_desc_get(c->dstFormat); desc_src = av_pix_fmt_desc_get(c->srcFormat); @@ -1005,6 +1018,12 @@ int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table, if (!c ) return -1; + if (c->nb_slice_ctx) { + return sws_getColorspaceDetails(c->slice_ctx[0], inv_table, srcRange, + table, dstRange, brightness, contrast, + saturation); + } + *inv_table = c->srcColorspaceTable; *table = c->dstColorspaceTable; *srcRange = range_override_needed(c->srcFormat) ? 1 : c->srcRange; @@ -1170,6 +1189,58 @@ static enum AVPixelFormat alphaless_fmt(enum AVPixelFormat fmt) } } +static int context_init_threaded(SwsContext *c, + SwsFilter *src_filter, SwsFilter *dst_filter) +{ + int ret; + + ret = avpriv_slicethread_create(&c->slicethread, (void*)c, + ff_sws_slice_worker, NULL, c->nb_threads); + if (ret == AVERROR(ENOSYS)) { + c->nb_threads = 1; + return 0; + } else if (ret < 0) + return ret; + + c->nb_threads = ret; + + c->slice_ctx = av_mallocz_array(c->nb_threads, sizeof(*c->slice_ctx)); + c->slice_err = av_mallocz_array(c->nb_threads, sizeof(*c->slice_err)); + if (!c->slice_ctx || !c->slice_err) + return AVERROR(ENOMEM); + + for (int i = 0; i < c->nb_threads; i++) { + c->slice_ctx[i] = sws_alloc_context(); + if (!c->slice_ctx[i]) + return AVERROR(ENOMEM); + + ret = av_opt_copy((void*)c->slice_ctx[i], (void*)c); + if (ret < 0) + return ret; + + c->slice_ctx[i]->nb_threads = 1; + + ret = sws_init_context(c->slice_ctx[i], src_filter, dst_filter); + if (ret < 0) + return ret; + + c->nb_slice_ctx++; + + if (c->slice_ctx[i]->dither == SWS_DITHER_ED) { + av_log(c, AV_LOG_VERBOSE, + "Error-diffusion dither is in use, scaling will be single-threaded."); + break; + } + } + + c->frame_src = av_frame_alloc(); + c->frame_dst = av_frame_alloc(); + if (!c->frame_src || !c->frame_dst) + return AVERROR(ENOMEM); + + return 0; +} + av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter) { @@ -1192,6 +1263,13 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, static const float float_mult = 1.0f / 255.0f; static AVOnce rgb2rgb_once = AV_ONCE_INIT; + if (c->nb_threads != 1) { + ret = context_init_threaded(c, srcFilter, dstFilter); + if (ret < 0 || c->nb_threads > 1) + return ret; + // threading disabled in this build, init as single-threaded + } + cpu_flags = av_get_cpu_flags(); flags = c->flags; emms_c(); @@ -2254,6 +2332,13 @@ void sws_freeContext(SwsContext *c) if (!c) return; + for (i = 0; i < c->nb_slice_ctx; i++) + sws_freeContext(c->slice_ctx[i]); + av_freep(&c->slice_ctx); + av_freep(&c->slice_err); + + avpriv_slicethread_free(&c->slicethread); + for (i = 0; i < 4; i++) av_freep(&c->dither_error[i]); |