|
|
|
@ -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]); |
|
|
|
|
|
|
|
|
|