[FFmpeg-devel,v6,05/12] swscale: eliminate redundant SwsInternal accesses

Message ID 20241112095154.483778-6-ffmpeg@haasn.xyz
State New
Headers
Series swscale: introduce new, dynamic scaling API |

Checks

Context Check Description
yinshiyou/make_loongarch64 fail Make failed

Commit Message

Niklas Haas Nov. 12, 2024, 9:50 a.m. UTC
From: Niklas Haas <git@haasn.dev>

This is a purely cosmetic commit aimed at replacing accesses to
SwsInternal.opts by direct access to SwsContext wherever convenient.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
---
 libswscale/options.c              |   2 +-
 libswscale/swscale.c              |  93 ++++++------
 libswscale/utils.c                | 233 +++++++++++++++---------------
 tests/checkasm/sw_gbrp.c          |  16 +-
 tests/checkasm/sw_range_convert.c |  16 +-
 tests/checkasm/sw_rgb.c           |  29 ++--
 tests/checkasm/sw_scale.c         |  22 +--
 7 files changed, 203 insertions(+), 208 deletions(-)
  

Patch

diff --git a/libswscale/options.c b/libswscale/options.c
index 6248e5f4b5..5eef26de06 100644
--- a/libswscale/options.c
+++ b/libswscale/options.c
@@ -27,7 +27,7 @@  static const char *sws_context_to_name(void *ptr)
     return "swscaler";
 }
 
-#define OFFSET(x) offsetof(SwsInternal, opts.x)
+#define OFFSET(x) offsetof(SwsContext, x)
 #define DEFAULT 0
 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 
diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index 5b5a009f1b..45172dcea4 100644
--- a/libswscale/swscale.c
+++ b/libswscale/swscale.c
@@ -895,7 +895,7 @@  static int scale_cascaded(SwsInternal *c,
                           uint8_t * const dstSlice[], const int dstStride[],
                           int dstSliceY, int dstSliceH)
 {
-    const int dstH0 = sws_internal(c->cascaded_context[0])->opts.dst_h;
+    const int dstH0 = c->cascaded_context[0]->dst_h;
     int ret = scale_internal(c->cascaded_context[0],
                              srcSlice, srcStride, srcSliceY, srcSliceH,
                              c->cascaded_tmp[0], c->cascaded_tmpStride[0],
@@ -915,13 +915,13 @@  static int scale_internal(SwsContext *sws,
                           int dstSliceY, int dstSliceH)
 {
     SwsInternal *c = sws_internal(sws);
-    const int scale_dst = dstSliceY > 0 || dstSliceH < c->opts.dst_h;
+    const int scale_dst = dstSliceY > 0 || dstSliceH < sws->dst_h;
     const int frame_start = scale_dst || !c->sliceDir;
     int i, ret;
     const uint8_t *src2[4];
     uint8_t *dst2[4];
-    int macro_height_src = isBayer(c->opts.src_format) ? 2 : (1 << c->chrSrcVSubSample);
-    int macro_height_dst = isBayer(c->opts.dst_format) ? 2 : (1 << c->chrDstVSubSample);
+    int macro_height_src = isBayer(sws->src_format) ? 2 : (1 << c->chrSrcVSubSample);
+    int macro_height_dst = isBayer(sws->dst_format) ? 2 : (1 << c->chrDstVSubSample);
     // copy strides, so they can safely be modified
     int srcStride2[4];
     int dstStride2[4];
@@ -933,25 +933,25 @@  static int scale_internal(SwsContext *sws,
     }
 
     if ((srcSliceY  & (macro_height_src - 1)) ||
-        ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != c->opts.src_h) ||
-        srcSliceY + srcSliceH > c->opts.src_h ||
-        (isBayer(c->opts.src_format) && srcSliceH <= 1)) {
+        ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != sws->src_h) ||
+        srcSliceY + srcSliceH > sws->src_h ||
+        (isBayer(sws->src_format) && srcSliceH <= 1)) {
         av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", srcSliceY, srcSliceH);
         return AVERROR(EINVAL);
     }
 
     if ((dstSliceY  & (macro_height_dst - 1)) ||
-        ((dstSliceH & (macro_height_dst - 1)) && dstSliceY + dstSliceH != c->opts.dst_h) ||
-        dstSliceY + dstSliceH > c->opts.dst_h) {
+        ((dstSliceH & (macro_height_dst - 1)) && dstSliceY + dstSliceH != sws->dst_h) ||
+        dstSliceY + dstSliceH > sws->dst_h) {
         av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", dstSliceY, dstSliceH);
         return AVERROR(EINVAL);
     }
 
-    if (!check_image_pointers(srcSlice, c->opts.src_format, srcStride)) {
+    if (!check_image_pointers(srcSlice, sws->src_format, srcStride)) {
         av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
         return AVERROR(EINVAL);
     }
-    if (!check_image_pointers((const uint8_t* const*)dstSlice, c->opts.dst_format, dstStride)) {
+    if (!check_image_pointers((const uint8_t* const*)dstSlice, sws->dst_format, dstStride)) {
         av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
         return AVERROR(EINVAL);
     }
@@ -960,22 +960,19 @@  static int scale_internal(SwsContext *sws,
     if (srcSliceH == 0)
         return 0;
 
-    if (c->opts.gamma_flag && c->cascaded_context[0])
+    if (sws->gamma_flag && c->cascaded_context[0])
         return scale_gamma(c, srcSlice, srcStride, srcSliceY, srcSliceH,
                            dstSlice, dstStride, dstSliceY, dstSliceH);
 
-    if (c->cascaded_context[0] && srcSliceY == 0 &&
-        srcSliceH == sws_internal(c->cascaded_context[0])->opts.src_h)
-    {
+    if (c->cascaded_context[0] && srcSliceY == 0 && srcSliceH == c->cascaded_context[0]->src_h)
         return scale_cascaded(c, srcSlice, srcStride, srcSliceY, srcSliceH,
                               dstSlice, dstStride, dstSliceY, dstSliceH);
-    }
 
-    if (!srcSliceY && (c->opts.flags & SWS_BITEXACT) && c->opts.dither == SWS_DITHER_ED && c->dither_error[0])
+    if (!srcSliceY && (sws->flags & SWS_BITEXACT) && sws->dither == SWS_DITHER_ED && c->dither_error[0])
         for (i = 0; i < 4; i++)
-            memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (c->opts.dst_w+2));
+            memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (sws->dst_w+2));
 
-    if (usePal(c->opts.src_format))
+    if (usePal(sws->src_format))
         ff_update_palette(c, (const uint32_t *)srcSlice[1]);
 
     memcpy(src2,       srcSlice,  sizeof(src2));
@@ -984,7 +981,7 @@  static int scale_internal(SwsContext *sws,
     memcpy(dstStride2, dstStride, sizeof(dstStride2));
 
     if (frame_start && !scale_dst) {
-        if (srcSliceY != 0 && srcSliceY + srcSliceH != c->opts.src_h) {
+        if (srcSliceY != 0 && srcSliceY + srcSliceH != sws->src_h) {
             av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
             return AVERROR(EINVAL);
         }
@@ -993,7 +990,7 @@  static int scale_internal(SwsContext *sws,
     } else if (scale_dst)
         c->sliceDir = 1;
 
-    if (c->src0Alpha && !c->dst0Alpha && isALPHA(c->opts.dst_format)) {
+    if (c->src0Alpha && !c->dst0Alpha && isALPHA(sws->dst_format)) {
         uint8_t *base;
         int x,y;
 
@@ -1005,15 +1002,15 @@  static int scale_internal(SwsContext *sws,
         base = srcStride[0] < 0 ? c->rgb0_scratch - srcStride[0] * (srcSliceH-1) :
                                   c->rgb0_scratch;
         for (y=0; y<srcSliceH; y++){
-            memcpy(base + srcStride[0]*y, src2[0] + srcStride[0]*y, 4*c->opts.src_w);
-            for (x=c->src0Alpha-1; x<4*c->opts.src_w; x+=4) {
+            memcpy(base + srcStride[0]*y, src2[0] + srcStride[0]*y, 4*sws->src_w);
+            for (x=c->src0Alpha-1; x<4*sws->src_w; x+=4) {
                 base[ srcStride[0]*y + x] = 0xFF;
             }
         }
         src2[0] = base;
     }
 
-    if (c->srcXYZ && !(c->dstXYZ && c->opts.src_w==c->opts.dst_w && c->opts.src_h==c->opts.dst_h)) {
+    if (c->srcXYZ && !(c->dstXYZ && sws->src_w==sws->dst_w && sws->src_h==sws->dst_h)) {
         uint8_t *base;
 
         av_fast_malloc(&c->xyz_scratch, &c->xyz_scratch_allocated,
@@ -1024,7 +1021,7 @@  static int scale_internal(SwsContext *sws,
         base = srcStride[0] < 0 ? c->xyz_scratch - srcStride[0] * (srcSliceH-1) :
                                   c->xyz_scratch;
 
-        ff_xyz12Torgb48(c, base, srcStride[0], src2[0], srcStride[0], c->opts.src_w, srcSliceH);
+        ff_xyz12Torgb48(c, base, srcStride[0], src2[0], srcStride[0], sws->src_w, srcSliceH);
         src2[0] = base;
     }
 
@@ -1036,19 +1033,19 @@  static int scale_internal(SwsContext *sws,
         }
 
         src2[0] += (srcSliceH - 1) * srcStride[0];
-        if (!usePal(c->opts.src_format))
+        if (!usePal(sws->src_format))
             src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1];
         src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2];
         src2[3] += (srcSliceH - 1) * srcStride[3];
-        dst2[0] += ( c->opts.dst_h                         - 1) * dstStride[0];
-        dst2[1] += ((c->opts.dst_h >> c->chrDstVSubSample) - 1) * dstStride[1];
-        dst2[2] += ((c->opts.dst_h >> c->chrDstVSubSample) - 1) * dstStride[2];
-        dst2[3] += ( c->opts.dst_h                         - 1) * dstStride[3];
+        dst2[0] += ( sws->dst_h                         - 1) * dstStride[0];
+        dst2[1] += ((sws->dst_h >> c->chrDstVSubSample) - 1) * dstStride[1];
+        dst2[2] += ((sws->dst_h >> c->chrDstVSubSample) - 1) * dstStride[2];
+        dst2[3] += ( sws->dst_h                         - 1) * dstStride[3];
 
-        srcSliceY_internal = c->opts.src_h-srcSliceY-srcSliceH;
+        srcSliceY_internal = sws->src_h-srcSliceY-srcSliceH;
     }
-    reset_ptr(src2, c->opts.src_format);
-    reset_ptr((void*)dst2, c->opts.dst_format);
+    reset_ptr(src2, sws->src_format);
+    reset_ptr((void*)dst2, sws->dst_format);
 
     if (c->convert_unscaled) {
         int offset  = srcSliceY_internal;
@@ -1058,13 +1055,13 @@  static int scale_internal(SwsContext *sws,
         if (scale_dst) {
             av_assert0(offset == 0);
             for (i = 0; i < 4 && src2[i]; i++) {
-                if (!src2[i] || (i > 0 && usePal(c->opts.src_format)))
+                if (!src2[i] || (i > 0 && usePal(sws->src_format)))
                     break;
                 src2[i] += (dstSliceY >> ((i == 1 || i == 2) ? c->chrSrcVSubSample : 0)) * srcStride2[i];
             }
 
             for (i = 0; i < 4 && dst2[i]; i++) {
-                if (!dst2[i] || (i > 0 && usePal(c->opts.dst_format)))
+                if (!dst2[i] || (i > 0 && usePal(sws->dst_format)))
                     break;
                 dst2[i] -= (dstSliceY >> ((i == 1 || i == 2) ? c->chrDstVSubSample : 0)) * dstStride2[i];
             }
@@ -1081,7 +1078,7 @@  static int scale_internal(SwsContext *sws,
                          dst2, dstStride2, dstSliceY, dstSliceH);
     }
 
-    if (c->dstXYZ && !(c->srcXYZ && c->opts.src_w==c->opts.dst_w && c->opts.src_h==c->opts.dst_h)) {
+    if (c->dstXYZ && !(c->srcXYZ && sws->src_w==sws->dst_w && sws->src_h==sws->dst_h)) {
         uint8_t *dst;
 
         if (scale_dst) {
@@ -1091,16 +1088,16 @@  static int scale_internal(SwsContext *sws,
 
             av_assert0(dstY >= ret);
             av_assert0(ret >= 0);
-            av_assert0(c->opts.dst_h >= dstY);
+            av_assert0(sws->dst_h >= dstY);
             dst = dst2[0] + (dstY - ret) * dstStride2[0];
         }
 
         /* replace on the same data */
-        ff_rgb48Toxyz12(c, dst, dstStride2[0], dst, dstStride2[0], c->opts.dst_w, ret);
+        ff_rgb48Toxyz12(c, dst, dstStride2[0], dst, dstStride2[0], sws->dst_w, ret);
     }
 
     /* reset slice direction at end of frame */
-    if ((srcSliceY_internal + srcSliceH == c->opts.src_h) || scale_dst)
+    if ((srcSliceY_internal + srcSliceH == sws->src_h) || scale_dst)
         c->sliceDir = 0;
 
     return ret;
@@ -1124,9 +1121,9 @@  int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src)
         return ret;
 
     if (!dst->buf[0]) {
-        dst->width  = c->opts.dst_w;
-        dst->height = c->opts.dst_h;
-        dst->format = c->opts.dst_format;
+        dst->width  = sws->dst_w;
+        dst->height = sws->dst_h;
+        dst->format = sws->dst_format;
 
         ret = av_frame_get_buffer(dst, 0);
         if (ret < 0)
@@ -1177,10 +1174,10 @@  int sws_receive_slice(SwsContext *sws, unsigned int slice_start,
     /* wait until complete input has been received */
     if (!(c->src_ranges.nb_ranges == 1        &&
           c->src_ranges.ranges[0].start == 0 &&
-          c->src_ranges.ranges[0].len == c->opts.src_h))
+          c->src_ranges.ranges[0].len == sws->src_h))
         return AVERROR(EAGAIN);
 
-    if ((slice_start > 0 || slice_height < c->opts.dst_h) &&
+    if ((slice_start > 0 || slice_height < sws->dst_h) &&
         (slice_start % align || slice_height % align)) {
         av_log(c, AV_LOG_ERROR,
                "Incorrectly aligned output: %u/%u not multiples of %u\n",
@@ -1192,7 +1189,7 @@  int sws_receive_slice(SwsContext *sws, unsigned int slice_start,
         int nb_jobs = c->nb_slice_ctx;
         int ret = 0;
 
-        if (sws_internal(c->slice_ctx[0])->opts.dither == SWS_DITHER_ED)
+        if (c->slice_ctx[0]->dither == SWS_DITHER_ED)
             nb_jobs = 1;
 
         c->dst_slice_start  = slice_start;
@@ -1218,7 +1215,7 @@  int sws_receive_slice(SwsContext *sws, unsigned int slice_start,
     }
 
     return scale_internal(sws, (const uint8_t * const *)c->frame_src->data,
-                          c->frame_src->linesize, 0, c->opts.src_h,
+                          c->frame_src->linesize, 0, sws->src_h,
                           dst, c->frame_dst->linesize, slice_start, slice_height);
 }
 
@@ -1256,7 +1253,7 @@  int attribute_align_arg sws_scale(SwsContext *sws,
     }
 
     return scale_internal(sws, srcSlice, srcStride, srcSliceY, srcSliceH,
-                          dst, dstStride, 0, c->opts.dst_h);
+                          dst, dstStride, 0, sws->dst_h);
 }
 
 void ff_sws_slice_worker(void *priv, int jobnr, int threadnr,
@@ -1284,7 +1281,7 @@  void ff_sws_slice_worker(void *priv, int jobnr, int threadnr,
         }
 
         err = scale_internal(sws, (const uint8_t * const *)parent->frame_src->data,
-                             parent->frame_src->linesize, 0, c->opts.src_h,
+                             parent->frame_src->linesize, 0, sws->src_h,
                              dst, parent->frame_dst->linesize,
                              parent->dst_slice_start + slice_start, slice_end - slice_start);
     }
diff --git a/libswscale/utils.c b/libswscale/utils.c
index ce9807d401..a01138d11b 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -1026,12 +1026,13 @@  static int handle_xyz(enum AVPixelFormat *format)
     }
 }
 
-static void handle_formats(SwsInternal *c)
+static void handle_formats(SwsContext *sws)
 {
-    c->src0Alpha |= handle_0alpha(&c->opts.src_format);
-    c->dst0Alpha |= handle_0alpha(&c->opts.dst_format);
-    c->srcXYZ    |= handle_xyz(&c->opts.src_format);
-    c->dstXYZ    |= handle_xyz(&c->opts.dst_format);
+    SwsInternal *c = sws_internal(sws);
+    c->src0Alpha |= handle_0alpha(&sws->src_format);
+    c->dst0Alpha |= handle_0alpha(&sws->dst_format);
+    c->srcXYZ    |= handle_xyz(&sws->src_format);
+    c->dstXYZ    |= handle_xyz(&sws->dst_format);
     if (c->srcXYZ || c->dstXYZ)
         fill_xyztables(c);
 }
@@ -1063,17 +1064,17 @@  int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4],
         return parent_ret;
     }
 
-    handle_formats(c);
-    desc_dst = av_pix_fmt_desc_get(c->opts.dst_format);
-    desc_src = av_pix_fmt_desc_get(c->opts.src_format);
+    handle_formats(sws);
+    desc_dst = av_pix_fmt_desc_get(sws->dst_format);
+    desc_src = av_pix_fmt_desc_get(sws->src_format);
 
-    if(range_override_needed(c->opts.dst_format))
+    if(range_override_needed(sws->dst_format))
         dstRange = 0;
-    if(range_override_needed(c->opts.src_format))
+    if(range_override_needed(sws->src_format))
         srcRange = 0;
 
-    if (c->opts.src_range != srcRange ||
-        c->opts.dst_range != dstRange ||
+    if (sws->src_range != srcRange ||
+        sws->dst_range != dstRange ||
         c->brightness != brightness ||
         c->contrast   != contrast ||
         c->saturation != saturation ||
@@ -1090,8 +1091,8 @@  int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4],
     c->brightness = brightness;
     c->contrast   = contrast;
     c->saturation = saturation;
-    c->opts.src_range   = srcRange;
-    c->opts.dst_range   = dstRange;
+    sws->src_range = srcRange;
+    sws->dst_range = dstRange;
 
     if (need_reinit)
         ff_sws_init_range_convert(c);
@@ -1105,27 +1106,27 @@  int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4],
     if (!need_reinit)
         return 0;
 
-    if ((isYUV(c->opts.dst_format) || isGray(c->opts.dst_format)) && (isYUV(c->opts.src_format) || isGray(c->opts.src_format))) {
+    if ((isYUV(sws->dst_format) || isGray(sws->dst_format)) && (isYUV(sws->src_format) || isGray(sws->src_format))) {
         if (!c->cascaded_context[0] &&
             memcmp(c->dstColorspaceTable, c->srcColorspaceTable, sizeof(int) * 4) &&
-            c->opts.src_w && c->opts.src_h && c->opts.dst_w && c->opts.dst_h) {
+            sws->src_w && sws->src_h && sws->dst_w && sws->dst_h) {
             enum AVPixelFormat tmp_format;
             int tmp_width, tmp_height;
-            int srcW = c->opts.src_w;
-            int srcH = c->opts.src_h;
-            int dstW = c->opts.dst_w;
-            int dstH = c->opts.dst_h;
+            int srcW = sws->src_w;
+            int srcH = sws->src_h;
+            int dstW = sws->dst_w;
+            int dstH = sws->dst_h;
             int ret;
             av_log(c, AV_LOG_VERBOSE, "YUV color matrix differs for YUV->YUV, using intermediate RGB to convert\n");
 
-            if (isNBPS(c->opts.dst_format) || is16BPS(c->opts.dst_format)) {
-                if (isALPHA(c->opts.src_format) && isALPHA(c->opts.dst_format)) {
+            if (isNBPS(sws->dst_format) || is16BPS(sws->dst_format)) {
+                if (isALPHA(sws->src_format) && isALPHA(sws->dst_format)) {
                     tmp_format = AV_PIX_FMT_BGRA64;
                 } else {
                     tmp_format = AV_PIX_FMT_BGR48;
                 }
             } else {
-                if (isALPHA(c->opts.src_format) && isALPHA(c->opts.dst_format)) {
+                if (isALPHA(sws->src_format) && isALPHA(sws->dst_format)) {
                     tmp_format = AV_PIX_FMT_BGRA;
                 } else {
                     tmp_format = AV_PIX_FMT_BGR24;
@@ -1145,14 +1146,13 @@  int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4],
             if (ret < 0)
                 return ret;
 
-            c->cascaded_context[0] = alloc_set_opts(srcW, srcH, c->opts.src_format,
+            c->cascaded_context[0] = alloc_set_opts(srcW, srcH, sws->src_format,
                                                     tmp_width, tmp_height, tmp_format,
-                                                    c->opts.flags,
-                                                    c->opts.scaler_params);
+                                                    sws->flags, sws->scaler_params);
             if (!c->cascaded_context[0])
                 return -1;
 
-            sws_internal(c->cascaded_context[0])->opts.alpha_blend = c->opts.alpha_blend;
+            c->cascaded_context[0]->alpha_blend = sws->alpha_blend;
             ret = sws_init_context(c->cascaded_context[0], NULL , NULL);
             if (ret < 0)
                 return ret;
@@ -1162,13 +1162,12 @@  int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4],
                                      brightness, contrast, saturation);
 
             c->cascaded_context[1] = alloc_set_opts(tmp_width, tmp_height, tmp_format,
-                                                    dstW, dstH, c->opts.dst_format,
-                                                    c->opts.flags,
-                                                    c->opts.scaler_params);
+                                                    dstW, dstH, sws->dst_format,
+                                                    sws->flags, sws->scaler_params);
             if (!c->cascaded_context[1])
                 return -1;
-            sws_internal(c->cascaded_context[1])->opts.src_range = srcRange;
-            sws_internal(c->cascaded_context[1])->opts.dst_range = dstRange;
+            c->cascaded_context[1]->src_range = srcRange;
+            c->cascaded_context[1]->dst_range = dstRange;
             ret = sws_init_context(c->cascaded_context[1], NULL , NULL);
             if (ret < 0)
                 return ret;
@@ -1183,7 +1182,7 @@  int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4],
         return 0;
     }
 
-    if (!isYUV(c->opts.dst_format) && !isGray(c->opts.dst_format)) {
+    if (!isYUV(sws->dst_format) && !isGray(sws->dst_format)) {
         ff_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness,
                                  contrast, saturation);
         // FIXME factorize
@@ -1215,8 +1214,8 @@  int sws_getColorspaceDetails(SwsContext *sws, int **inv_table,
 
     *inv_table  = c->srcColorspaceTable;
     *table      = c->dstColorspaceTable;
-    *srcRange   = range_override_needed(c->opts.src_format) ? 1 : c->opts.src_range;
-    *dstRange   = range_override_needed(c->opts.dst_format) ? 1 : c->opts.dst_range;
+    *srcRange   = range_override_needed(sws->src_format) ? 1 : sws->src_range;
+    *dstRange   = range_override_needed(sws->dst_format) ? 1 : sws->dst_range;
     *brightness = c->brightness;
     *contrast   = c->contrast;
     *saturation = c->saturation;
@@ -1321,10 +1320,10 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
     int unscaled;
     SwsInternal *c        = sws_internal(sws);
     SwsFilter dummyFilter = { NULL, NULL, NULL, NULL };
-    int srcW              = c->opts.src_w;
-    int srcH              = c->opts.src_h;
-    int dstW              = c->opts.dst_w;
-    int dstH              = c->opts.dst_h;
+    int srcW              = sws->src_w;
+    int srcH              = sws->src_h;
+    int dstW              = sws->dst_w;
+    int dstH              = sws->dst_h;
     int dst_stride        = FFALIGN(dstW * sizeof(int16_t) + 66, 16);
     int flags, cpu_flags;
     enum AVPixelFormat srcFormat, dstFormat;
@@ -1335,25 +1334,25 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
     static const float float_mult = 1.0f / 255.0f;
 
     cpu_flags = av_get_cpu_flags();
-    flags     = c->opts.flags;
+    flags     = sws->flags;
     emms_c();
 
     unscaled = (srcW == dstW && srcH == dstH);
 
     if (!c->contrast && !c->saturation && !c->dstFormatBpp)
-        sws_setColorspaceDetails(sws, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], c->opts.src_range,
+        sws_setColorspaceDetails(sws, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], sws->src_range,
                                  ff_yuv2rgb_coeffs[SWS_CS_DEFAULT],
-                                 c->opts.dst_range, 0, 1 << 16, 1 << 16);
+                                 sws->dst_range, 0, 1 << 16, 1 << 16);
 
-    handle_formats(c);
-    srcFormat = c->opts.src_format;
-    dstFormat = c->opts.dst_format;
+    handle_formats(sws);
+    srcFormat = sws->src_format;
+    dstFormat = sws->dst_format;
     desc_src = av_pix_fmt_desc_get(srcFormat);
     desc_dst = av_pix_fmt_desc_get(dstFormat);
 
     // If the source has no alpha then disable alpha blendaway
     if (c->src0Alpha)
-        c->opts.alpha_blend = SWS_ALPHA_BLEND_NONE;
+        sws->alpha_blend = SWS_ALPHA_BLEND_NONE;
 
     if (!(unscaled && sws_isSupportedEndiannessConversion(srcFormat) &&
           av_pix_fmt_swap_endianness(srcFormat) == dstFormat)) {
@@ -1390,7 +1389,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
             flags |= SWS_BICUBIC;
         else
             flags |= SWS_BICUBIC;
-        c->opts.flags = flags;
+        sws->flags = flags;
     } else if (i & (i - 1)) {
         av_log(c, AV_LOG_ERROR,
                "Exactly one scaler algorithm must be chosen, got %X\n", i);
@@ -1407,7 +1406,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
     if (flags & SWS_FAST_BILINEAR) {
         if (srcW < 8 || dstW < 8) {
             flags ^= SWS_FAST_BILINEAR | SWS_BILINEAR;
-            c->opts.flags = flags;
+            sws->flags = flags;
         }
     }
 
@@ -1440,46 +1439,46 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
         if (dstW&1) {
             av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to odd output size\n");
             flags |= SWS_FULL_CHR_H_INT;
-            c->opts.flags = flags;
+            sws->flags = flags;
         }
 
         if (   c->chrSrcHSubSample == 0
             && c->chrSrcVSubSample == 0
-            && c->opts.dither != SWS_DITHER_BAYER //SWS_FULL_CHR_H_INT is currently not supported with SWS_DITHER_BAYER
-            && !(c->opts.flags & SWS_FAST_BILINEAR)
+            && sws->dither != SWS_DITHER_BAYER //SWS_FULL_CHR_H_INT is currently not supported with SWS_DITHER_BAYER
+            && !(sws->flags & SWS_FAST_BILINEAR)
         ) {
             av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to input having non subsampled chroma\n");
             flags |= SWS_FULL_CHR_H_INT;
-            c->opts.flags = flags;
+            sws->flags = flags;
         }
     }
 
-    if (c->opts.dither == SWS_DITHER_AUTO) {
+    if (sws->dither == SWS_DITHER_AUTO) {
         if (flags & SWS_ERROR_DIFFUSION)
-            c->opts.dither = SWS_DITHER_ED;
+            sws->dither = SWS_DITHER_ED;
     }
 
     if(dstFormat == AV_PIX_FMT_BGR4_BYTE ||
        dstFormat == AV_PIX_FMT_RGB4_BYTE ||
        dstFormat == AV_PIX_FMT_BGR8 ||
        dstFormat == AV_PIX_FMT_RGB8) {
-        if (c->opts.dither == SWS_DITHER_AUTO)
-            c->opts.dither = (flags & SWS_FULL_CHR_H_INT) ? SWS_DITHER_ED : SWS_DITHER_BAYER;
+        if (sws->dither == SWS_DITHER_AUTO)
+            sws->dither = (flags & SWS_FULL_CHR_H_INT) ? SWS_DITHER_ED : SWS_DITHER_BAYER;
         if (!(flags & SWS_FULL_CHR_H_INT)) {
-            if (c->opts.dither == SWS_DITHER_ED || c->opts.dither == SWS_DITHER_A_DITHER || c->opts.dither == SWS_DITHER_X_DITHER || c->opts.dither == SWS_DITHER_NONE) {
+            if (sws->dither == SWS_DITHER_ED || sws->dither == SWS_DITHER_A_DITHER || sws->dither == SWS_DITHER_X_DITHER || sws->dither == SWS_DITHER_NONE) {
                 av_log(c, AV_LOG_DEBUG,
                     "Desired dithering only supported in full chroma interpolation for destination format '%s'\n",
                     av_get_pix_fmt_name(dstFormat));
                 flags   |= SWS_FULL_CHR_H_INT;
-                c->opts.flags = flags;
+                sws->flags = flags;
             }
         }
         if (flags & SWS_FULL_CHR_H_INT) {
-            if (c->opts.dither == SWS_DITHER_BAYER) {
+            if (sws->dither == SWS_DITHER_BAYER) {
                 av_log(c, AV_LOG_DEBUG,
                     "Ordered dither is not supported in full chroma interpolation for destination format '%s'\n",
                     av_get_pix_fmt_name(dstFormat));
-                c->opts.dither = SWS_DITHER_ED;
+                sws->dither = SWS_DITHER_ED;
             }
         }
     }
@@ -1489,7 +1488,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
                    "%s output is not supported with half chroma resolution, switching to full\n",
                    av_get_pix_fmt_name(dstFormat));
             flags   |= SWS_FULL_CHR_H_INT;
-            c->opts.flags = flags;
+            sws->flags = flags;
         }
     }
 
@@ -1523,7 +1522,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
                "full chroma interpolation for destination format '%s' not yet implemented\n",
                av_get_pix_fmt_name(dstFormat));
         flags   &= ~SWS_FULL_CHR_H_INT;
-        c->opts.flags = flags;
+        sws->flags = flags;
     }
     if (isAnyRGB(dstFormat) && !(flags & SWS_FULL_CHR_H_INT))
         c->chrDstHSubSample = 1;
@@ -1585,7 +1584,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
                 av_log(c, AV_LOG_INFO,
                        "output width is not a multiple of 32 -> no MMXEXT scaler\n");
         }
-        if (usesHFilter || isNBPS(c->opts.src_format) || is16BPS(c->opts.src_format) || isAnyRGB(c->opts.src_format))
+        if (usesHFilter || isNBPS(sws->src_format) || is16BPS(sws->src_format) || isAnyRGB(sws->src_format))
             c->canMMXEXTBeUsed = 0;
     } else
         c->canMMXEXTBeUsed = 0;
@@ -1616,8 +1615,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
     c->gamma_value = 2.2;
     tmpFmt = AV_PIX_FMT_RGBA64LE;
 
-
-    if (!unscaled && c->opts.gamma_flag && (srcFormat != tmpFmt || dstFormat != tmpFmt)) {
+    if (!unscaled && sws->gamma_flag && (srcFormat != tmpFmt || dstFormat != tmpFmt)) {
         SwsInternal *c2;
         c->cascaded_context[0] = NULL;
 
@@ -1629,7 +1627,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
         c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat,
                                                 srcW, srcH, tmpFmt,
                                                 flags, NULL, NULL,
-                                                c->opts.scaler_params);
+                                                sws->scaler_params);
         if (!c->cascaded_context[0]) {
             return AVERROR(ENOMEM);
         }
@@ -1637,7 +1635,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
         c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFmt,
                                                 dstW, dstH, tmpFmt,
                                                 flags, srcFilter, dstFilter,
-                                                c->opts.scaler_params);
+                                                sws->scaler_params);
 
         if (!c->cascaded_context[1])
             return AVERROR(ENOMEM);
@@ -1669,7 +1667,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
             c->cascaded_context[2] = sws_getContext(dstW, dstH, tmpFmt,
                                                     dstW, dstH, dstFormat,
                                                     flags, NULL, NULL,
-                                                    c->opts.scaler_params);
+                                                    sws->scaler_params);
             if (!c->cascaded_context[2])
                 return AVERROR(ENOMEM);
         }
@@ -1690,14 +1688,14 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
             c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat,
                                                     srcW, srcH, tmpFormat,
                                                     flags, srcFilter, NULL,
-                                                    c->opts.scaler_params);
+                                                    sws->scaler_params);
             if (!c->cascaded_context[0])
                 return AVERROR(ENOMEM);
 
             c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFormat,
                                                     dstW, dstH, dstFormat,
                                                     flags, NULL, dstFilter,
-                                                    c->opts.scaler_params);
+                                                    sws->scaler_params);
             if (!c->cascaded_context[1])
                 return AVERROR(ENOMEM);
             return 0;
@@ -1720,11 +1718,11 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
     if (CONFIG_SWSCALE_ALPHA && isALPHA(srcFormat) && !isALPHA(dstFormat)) {
         enum AVPixelFormat tmpFormat = alphaless_fmt(srcFormat);
 
-        if (tmpFormat != AV_PIX_FMT_NONE && c->opts.alpha_blend != SWS_ALPHA_BLEND_NONE) {
+        if (tmpFormat != AV_PIX_FMT_NONE && sws->alpha_blend != SWS_ALPHA_BLEND_NONE) {
             if (!unscaled ||
                 dstFormat != tmpFormat ||
                 usesHFilter || usesVFilter ||
-                c->opts.src_range != c->opts.dst_range
+                sws->src_range != sws->dst_range
             ) {
                 c->cascaded_mainindex = 1;
                 ret = av_image_alloc(c->cascaded_tmp[0], c->cascaded_tmpStride[0],
@@ -1734,22 +1732,22 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
 
                 c->cascaded_context[0] = alloc_set_opts(srcW, srcH, srcFormat,
                                                         srcW, srcH, tmpFormat,
-                                                        flags, c->opts.scaler_params);
+                                                        flags, sws->scaler_params);
                 if (!c->cascaded_context[0])
                     return AVERROR(EINVAL);
-                sws_internal(c->cascaded_context[0])->opts.alpha_blend = c->opts.alpha_blend;
+                c->cascaded_context[0]->alpha_blend = sws->alpha_blend;
                 ret = sws_init_context(c->cascaded_context[0], NULL , NULL);
                 if (ret < 0)
                     return ret;
 
                 c->cascaded_context[1] = alloc_set_opts(srcW, srcH, tmpFormat,
                                                         dstW, dstH, dstFormat,
-                                                        flags, c->opts.scaler_params);
+                                                        flags, sws->scaler_params);
                 if (!c->cascaded_context[1])
                     return AVERROR(EINVAL);
 
-                sws_internal(c->cascaded_context[1])->opts.src_range = c->opts.src_range;
-                sws_internal(c->cascaded_context[1])->opts.dst_range = c->opts.dst_range;
+                c->cascaded_context[1]->src_range = sws->src_range;
+                c->cascaded_context[1]->dst_range = sws->dst_range;
                 ret = sws_init_context(c->cascaded_context[1], srcFilter , dstFilter);
                 if (ret < 0)
                     return ret;
@@ -1761,9 +1759,9 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
 
     /* alpha blend special case, note this has been split via cascaded contexts if its scaled */
     if (unscaled && !usesHFilter && !usesVFilter &&
-        c->opts.alpha_blend != SWS_ALPHA_BLEND_NONE &&
+        sws->alpha_blend != SWS_ALPHA_BLEND_NONE &&
         isALPHA(srcFormat) &&
-        (c->opts.src_range == c->opts.dst_range || isAnyRGB(dstFormat)) &&
+        (sws->src_range == sws->dst_range || isAnyRGB(dstFormat)) &&
         alphaless_fmt(srcFormat) == dstFormat
     ) {
         c->convert_unscaled = ff_sws_alphablendaway;
@@ -1777,7 +1775,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
 
     /* unscaled special cases */
     if (unscaled && !usesHFilter && !usesVFilter &&
-        (c->opts.src_range == c->opts.dst_range || isAnyRGB(dstFormat) ||
+        (sws->src_range == sws->dst_range || isAnyRGB(dstFormat) ||
          isFloat(srcFormat) || isFloat(dstFormat) || isBayer(srcFormat))){
 
         ff_get_unscaled_swscale(c);
@@ -1873,7 +1871,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
                            srcW, dstW, filterAlign, 1 << 14,
                            (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
                            cpu_flags, srcFilter->lumH, dstFilter->lumH,
-                           c->opts.scaler_params,
+                           sws->scaler_params,
                            get_local_pos(c, 0, 0, 0),
                            get_local_pos(c, 0, 0, 0))) < 0)
                 goto fail;
@@ -1884,9 +1882,9 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
                            c->chrSrcW, c->chrDstW, filterAlign, 1 << 14,
                            (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
                            cpu_flags, srcFilter->chrH, dstFilter->chrH,
-                           c->opts.scaler_params,
-                           get_local_pos(c, c->chrSrcHSubSample, c->opts.src_h_chr_pos, 0),
-                           get_local_pos(c, c->chrDstHSubSample, c->opts.dst_h_chr_pos, 0))) < 0)
+                           sws->scaler_params,
+                           get_local_pos(c, c->chrSrcHSubSample, sws->src_h_chr_pos, 0),
+                           get_local_pos(c, c->chrDstHSubSample, sws->dst_h_chr_pos, 0))) < 0)
                 goto fail;
             if (ff_shuffle_filter_coefficients(c, c->hChrFilterPos, c->hChrFilterSize, c->hChrFilter, c->chrDstW) < 0)
                 goto nomem;
@@ -1903,7 +1901,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
                        c->lumYInc, srcH, dstH, filterAlign, (1 << 12),
                        (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
                        cpu_flags, srcFilter->lumV, dstFilter->lumV,
-                       c->opts.scaler_params,
+                       sws->scaler_params,
                        get_local_pos(c, 0, 0, 1),
                        get_local_pos(c, 0, 0, 1))) < 0)
             goto fail;
@@ -1912,18 +1910,18 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
                        filterAlign, (1 << 12),
                        (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
                        cpu_flags, srcFilter->chrV, dstFilter->chrV,
-                       c->opts.scaler_params,
-                       get_local_pos(c, c->chrSrcVSubSample, c->opts.src_v_chr_pos, 1),
-                       get_local_pos(c, c->chrDstVSubSample, c->opts.dst_v_chr_pos, 1))) < 0)
+                       sws->scaler_params,
+                       get_local_pos(c, c->chrSrcVSubSample, sws->src_v_chr_pos, 1),
+                       get_local_pos(c, c->chrDstVSubSample, sws->dst_v_chr_pos, 1))) < 0)
 
             goto fail;
 
 #if HAVE_ALTIVEC
-        if (!FF_ALLOC_TYPED_ARRAY(c->vYCoeffsBank, c->vLumFilterSize * c->opts.dst_h) ||
+        if (!FF_ALLOC_TYPED_ARRAY(c->vYCoeffsBank, c->vLumFilterSize * sws->dst_h) ||
             !FF_ALLOC_TYPED_ARRAY(c->vCCoeffsBank, c->vChrFilterSize * c->chrDstH))
             goto nomem;
 
-        for (i = 0; i < c->vLumFilterSize * c->opts.dst_h; i++) {
+        for (i = 0; i < c->vLumFilterSize * sws->dst_h; i++) {
             int j;
             short *p = (short *)&c->vYCoeffsBank[i];
             for (j = 0; j < 8; j++)
@@ -1940,10 +1938,10 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
     }
 
     for (i = 0; i < 4; i++)
-        if (!FF_ALLOCZ_TYPED_ARRAY(c->dither_error[i], c->opts.dst_w + 3))
+        if (!FF_ALLOCZ_TYPED_ARRAY(c->dither_error[i], sws->dst_w + 3))
             goto nomem;
 
-    c->needAlpha = (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format) && isALPHA(c->opts.dst_format)) ? 1 : 0;
+    c->needAlpha = (CONFIG_SWSCALE_ALPHA && isALPHA(sws->src_format) && isALPHA(sws->dst_format)) ? 1 : 0;
 
     // 64 / c->scalingBpp is the same as 16 / sizeof(scaling_intermediate)
     c->uv_off   = (dst_stride>>1) + 64 / (c->dstBpc &~ 7);
@@ -1985,7 +1983,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
         av_log(c, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);
         av_log(c, AV_LOG_DEBUG,
                "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
-               c->opts.src_w, c->opts.src_h, c->opts.dst_w, c->opts.dst_h, c->lumXInc, c->lumYInc);
+               sws->src_w, sws->src_h, sws->dst_w, sws->dst_h, c->lumXInc, c->lumYInc);
         av_log(c, AV_LOG_DEBUG,
                "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
                c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH,
@@ -2017,14 +2015,14 @@  fail: // FIXME replace things by appropriate error codes
         c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat,
                                                 tmpW, tmpH, tmpFormat,
                                                 flags, srcFilter, NULL,
-                                                c->opts.scaler_params);
+                                                sws->scaler_params);
         if (!c->cascaded_context[0])
             return AVERROR(ENOMEM);
 
         c->cascaded_context[1] = sws_getContext(tmpW, tmpH, tmpFormat,
                                                 dstW, dstH, dstFormat,
                                                 flags, NULL, dstFilter,
-                                                c->opts.scaler_params);
+                                                sws->scaler_params);
         if (!c->cascaded_context[1])
             return AVERROR(ENOMEM);
         return 0;
@@ -2039,41 +2037,38 @@  static int context_init_threaded(SwsContext *sws,
     int ret;
 
     ret = avpriv_slicethread_create(&c->slicethread, (void*) sws,
-                                    ff_sws_slice_worker, NULL, c->opts.threads);
+                                    ff_sws_slice_worker, NULL, sws->threads);
     if (ret == AVERROR(ENOSYS)) {
-        c->opts.threads = 1;
+        sws->threads = 1;
         return 0;
     } else if (ret < 0)
         return ret;
 
-    c->opts.threads = ret;
+    sws->threads = ret;
 
-    c->slice_ctx = av_calloc(c->opts.threads, sizeof(*c->slice_ctx));
-    c->slice_err = av_calloc(c->opts.threads, sizeof(*c->slice_err));
+    c->slice_ctx = av_calloc(sws->threads, sizeof(*c->slice_ctx));
+    c->slice_err = av_calloc(sws->threads, sizeof(*c->slice_err));
     if (!c->slice_ctx || !c->slice_err)
         return AVERROR(ENOMEM);
 
-    for (int i = 0; i < c->opts.threads; i++) {
-        SwsInternal *c2;
-        c->slice_ctx[i] = sws_alloc_context();
-        if (!c->slice_ctx[i])
+    for (int i = 0; i < sws->threads; i++) {
+        SwsContext *slice;
+        slice = c->slice_ctx[i] = sws_alloc_context();
+        if (!slice)
             return AVERROR(ENOMEM);
-        c2 = sws_internal(c->slice_ctx[i]);
-
+        sws_internal(slice)->parent = sws;
         c->nb_slice_ctx++;
-        c2->parent = sws;
 
-        ret = av_opt_copy((void*)c->slice_ctx[i], (void*)c);
+        ret = av_opt_copy(slice, sws);
         if (ret < 0)
             return ret;
+        slice->threads = 1;
 
-        c2->opts.threads = 1;
-
-        ret = sws_init_single_context(c->slice_ctx[i], src_filter, dst_filter);
+        ret = sws_init_single_context(slice, src_filter, dst_filter);
         if (ret < 0)
             return ret;
 
-        if (c2->opts.dither == SWS_DITHER_ED) {
+        if (slice->dither == SWS_DITHER_ED) {
             av_log(c, AV_LOG_VERBOSE,
                    "Error-diffusion dither is in use, scaling will be single-threaded.");
             break;
@@ -2099,17 +2094,17 @@  av_cold int sws_init_context(SwsContext *sws, SwsFilter *srcFilter,
     if (ff_thread_once(&rgb2rgb_once, ff_sws_rgb2rgb_init) != 0)
         return AVERROR_UNKNOWN;
 
-    src_format = c->opts.src_format;
-    dst_format = c->opts.dst_format;
-    c->opts.src_range |= handle_jpeg(&c->opts.src_format);
-    c->opts.dst_range |= handle_jpeg(&c->opts.dst_format);
+    src_format = sws->src_format;
+    dst_format = sws->dst_format;
+    sws->src_range |= handle_jpeg(&sws->src_format);
+    sws->dst_range |= handle_jpeg(&sws->dst_format);
 
-    if (src_format != c->opts.src_format || dst_format != c->opts.dst_format)
+    if (src_format != sws->src_format || dst_format != sws->dst_format)
         av_log(c, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n");
 
-    if (c->opts.threads != 1) {
+    if (sws->threads != 1) {
         ret = context_init_threaded(sws, srcFilter, dstFilter);
-        if (ret < 0 || c->opts.threads > 1)
+        if (ret < 0 || sws->threads > 1)
             return ret;
         // threading disabled in this build, init as single-threaded
     }
diff --git a/tests/checkasm/sw_gbrp.c b/tests/checkasm/sw_gbrp.c
index b8ac7fdd1c..4fcb87cd5f 100644
--- a/tests/checkasm/sw_gbrp.c
+++ b/tests/checkasm/sw_gbrp.c
@@ -135,13 +135,13 @@  static void check_output_yuv2gbrp(void)
         fail();
 
     c = sws_internal(sws);
-    c->opts.flags |= SWS_FULL_CHR_H_INT;
+    sws->flags |= SWS_FULL_CHR_H_INT;
 
     for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) {
         for (fsi = 0; fsi < FILTER_SIZES; fsi++) {
             for (isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++ ) {
                 desc = av_pix_fmt_desc_get(planar_fmts[fmi]);
-                c->opts.dst_format = planar_fmts[fmi];
+                sws->dst_format = planar_fmts[fmi];
 
                 dstW = input_sizes[isi];
                 luma_filter_size = filter_sizes[fsi];
@@ -229,8 +229,8 @@  static void check_input_planar_rgb_to_y(void)
     for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) {
         for (isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++ ) {
             desc = av_pix_fmt_desc_get(planar_fmts[fmi]);
-            c->opts.src_format = planar_fmts[fmi];
-            c->opts.dst_format = AV_PIX_FMT_YUVA444P16;
+            sws->src_format = planar_fmts[fmi];
+            sws->dst_format = AV_PIX_FMT_YUVA444P16;
             byte_size = 2;
             dstW = input_sizes[isi];
 
@@ -300,8 +300,8 @@  static void check_input_planar_rgb_to_uv(void)
     for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) {
         for (isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++ ) {
             desc = av_pix_fmt_desc_get(planar_fmts[fmi]);
-            c->opts.src_format = planar_fmts[fmi];
-            c->opts.dst_format = AV_PIX_FMT_YUVA444P16;
+            sws->src_format = planar_fmts[fmi];
+            sws->dst_format = AV_PIX_FMT_YUVA444P16;
             byte_size = 2;
             dstW = input_sizes[isi];
 
@@ -373,8 +373,8 @@  static void check_input_planar_rgb_to_a(void)
             if (!(desc->flags & AV_PIX_FMT_FLAG_ALPHA))
                 continue;
 
-            c->opts.src_format = planar_fmts[fmi];
-            c->opts.dst_format = AV_PIX_FMT_YUVA444P16;
+            sws->src_format = planar_fmts[fmi];
+            sws->dst_format = AV_PIX_FMT_YUVA444P16;
             byte_size = 2;
             dstW = input_sizes[isi];
 
diff --git a/tests/checkasm/sw_range_convert.c b/tests/checkasm/sw_range_convert.c
index f17050f524..bf14209987 100644
--- a/tests/checkasm/sw_range_convert.c
+++ b/tests/checkasm/sw_range_convert.c
@@ -73,16 +73,16 @@  static void check_lumConvertRange(int from)
         fail();
 
     c = sws_internal(sws);
-    c->opts.src_range = from;
-    c->opts.dst_range = !from;
+    sws->src_range = from;
+    sws->dst_range = !from;
 
     for (int pfi = 0; pfi < FF_ARRAY_ELEMS(pixel_formats); pfi++) {
         enum AVPixelFormat pix_fmt = pixel_formats[pfi];
         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
         int bit_depth = desc->comp[0].depth;
         int sample_size = bit_depth == 16 ? sizeof(int32_t) : sizeof(int16_t);
-        c->opts.src_format = pix_fmt;
-        c->opts.dst_format = pix_fmt;
+        sws->src_format = pix_fmt;
+        sws->dst_format = pix_fmt;
         c->dstBpc = bit_depth;
         ff_sws_init_scale(c);
         for (int dstWi = 0; dstWi < FF_ARRAY_ELEMS(input_sizes); dstWi++) {
@@ -123,16 +123,16 @@  static void check_chrConvertRange(int from)
         fail();
 
     c = sws_internal(sws);
-    c->opts.src_range = from;
-    c->opts.dst_range = !from;
+    sws->src_range = from;
+    sws->dst_range = !from;
 
     for (int pfi = 0; pfi < FF_ARRAY_ELEMS(pixel_formats); pfi++) {
         enum AVPixelFormat pix_fmt = pixel_formats[pfi];
         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
         int bit_depth = desc->comp[0].depth;
         int sample_size = bit_depth == 16 ? sizeof(int32_t) : sizeof(int16_t);
-        c->opts.src_format = pix_fmt;
-        c->opts.dst_format = pix_fmt;
+        sws->src_format = pix_fmt;
+        sws->dst_format = pix_fmt;
         c->dstBpc = bit_depth;
         ff_sws_init_scale(c);
         for (int dstWi = 0; dstWi < FF_ARRAY_ELEMS(input_sizes); dstWi++) {
diff --git a/tests/checkasm/sw_rgb.c b/tests/checkasm/sw_rgb.c
index 65f8404d3f..05370c1e41 100644
--- a/tests/checkasm/sw_rgb.c
+++ b/tests/checkasm/sw_rgb.c
@@ -127,9 +127,10 @@  static int cmp_off_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int a
     return 0;
 }
 
-static void check_rgb24toyv12(SwsInternal *ctx)
+static void check_rgb24toyv12(SwsContext *sws)
 {
     static const int input_sizes[] = {16, 128, 512, MAX_LINE_SIZE, -MAX_LINE_SIZE};
+    SwsInternal *ctx = sws_internal(sws);
 
     LOCAL_ALIGNED_32(uint8_t, src, [BUFSIZE * 3]);
     LOCAL_ALIGNED_32(uint8_t, buf_y_0, [BUFSIZE]);
@@ -353,8 +354,10 @@  static const enum AVPixelFormat rgb_formats[] = {
         AV_PIX_FMT_ARGB,
 };
 
-static void check_rgb_to_y(SwsInternal *ctx)
+static void check_rgb_to_y(SwsContext *sws)
 {
+    SwsInternal *ctx = sws_internal(sws);
+
     LOCAL_ALIGNED_16(uint8_t, src24,  [MAX_LINE_SIZE * 3]);
     LOCAL_ALIGNED_16(uint8_t, src32,  [MAX_LINE_SIZE * 4]);
     LOCAL_ALIGNED_32(uint8_t, dst0_y, [MAX_LINE_SIZE * 2]);
@@ -370,7 +373,7 @@  static void check_rgb_to_y(SwsInternal *ctx)
     for (int i = 0; i < FF_ARRAY_ELEMS(rgb_formats); i++) {
         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(rgb_formats[i]);
 
-        ctx->opts.src_format = rgb_formats[i];
+        sws->src_format = rgb_formats[i];
         ff_sws_init_scale(ctx);
 
         for (int j = 0; j < FF_ARRAY_ELEMS(input_sizes); j++) {
@@ -389,15 +392,17 @@  static void check_rgb_to_y(SwsInternal *ctx)
 
                 if (desc->nb_components == 3 ||
                     // only bench native endian formats
-                    (ctx->opts.src_format == AV_PIX_FMT_RGB32 || ctx->opts.src_format == AV_PIX_FMT_RGB32_1))
+                    (sws->src_format == AV_PIX_FMT_RGB32 || sws->src_format == AV_PIX_FMT_RGB32_1))
                     bench_new(dst1_y, src, NULL, NULL, w, ctx->input_rgb2yuv_table, NULL);
             }
         }
     }
 }
 
-static void check_rgb_to_uv(SwsInternal *ctx)
+static void check_rgb_to_uv(SwsContext *sws)
 {
+    SwsInternal *ctx = sws_internal(sws);
+
     LOCAL_ALIGNED_16(uint8_t, src24,  [MAX_LINE_SIZE * 3]);
     LOCAL_ALIGNED_16(uint8_t, src32,  [MAX_LINE_SIZE * 4]);
     LOCAL_ALIGNED_16(uint8_t, dst0_u, [MAX_LINE_SIZE * 2]);
@@ -417,8 +422,8 @@  static void check_rgb_to_uv(SwsInternal *ctx)
         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(src_fmt);
 
         ctx->chrSrcHSubSample = (i % 2) ? 0 : 1;
-        ctx->opts.src_format = src_fmt;
-        ctx->opts.dst_format = ctx->chrSrcHSubSample ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV444P;
+        sws->src_format = src_fmt;
+        sws->dst_format = ctx->chrSrcHSubSample ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV444P;
         ff_sws_init_scale(ctx);
 
         for (int j = 0; j < FF_ARRAY_ELEMS(input_sizes); j++) {
@@ -441,7 +446,7 @@  static void check_rgb_to_uv(SwsInternal *ctx)
 
                 if (desc->nb_components == 3 ||
                     // only bench native endian formats
-                    (ctx->opts.src_format == AV_PIX_FMT_RGB32 || ctx->opts.src_format == AV_PIX_FMT_RGB32_1))
+                    (sws->src_format == AV_PIX_FMT_RGB32 || sws->src_format == AV_PIX_FMT_RGB32_1))
                     bench_new(dst1_u, dst1_v, NULL, src, src, w, ctx->input_rgb2yuv_table, NULL);
             }
         }
@@ -451,7 +456,6 @@  static void check_rgb_to_uv(SwsInternal *ctx)
 void checkasm_check_sw_rgb(void)
 {
     SwsContext *sws;
-    SwsInternal *c;
 
     ff_sws_rgb2rgb_init();
 
@@ -485,14 +489,13 @@  void checkasm_check_sw_rgb(void)
     if (!sws)
         fail();
 
-    c = sws_internal(sws);
-    check_rgb_to_y(c);
+    check_rgb_to_y(sws);
     report("rgb_to_y");
 
-    check_rgb_to_uv(c);
+    check_rgb_to_uv(sws);
     report("rgb_to_uv");
 
-    check_rgb24toyv12(c);
+    check_rgb24toyv12(sws);
     report("rgb24toyv12");
 
     sws_freeContext(sws);
diff --git a/tests/checkasm/sw_scale.c b/tests/checkasm/sw_scale.c
index 82e2b1d5ce..350f2b73d4 100644
--- a/tests/checkasm/sw_scale.c
+++ b/tests/checkasm/sw_scale.c
@@ -123,12 +123,12 @@  static void check_yuv2yuv1(int accurate)
     randomize_buffers((uint8_t*)dither, 8);
     randomize_buffers((uint8_t*)src_pixels, LARGEST_INPUT_SIZE * sizeof(int16_t));
     sws = sws_alloc_context();
-    c = sws_internal(sws);
     if (accurate)
-        c->opts.flags |= SWS_ACCURATE_RND;
+        sws->flags |= SWS_ACCURATE_RND;
     if (sws_init_context(sws, NULL, NULL) < 0)
         fail();
 
+    c = sws_internal(sws);
     ff_sws_init_scale(c);
     for (isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); ++isi) {
         dstW = input_sizes[isi];
@@ -190,12 +190,12 @@  static void check_yuv2yuvX(int accurate)
     memset(dither, d_val, LARGEST_INPUT_SIZE);
     randomize_buffers((uint8_t*)src_pixels, LARGEST_FILTER * LARGEST_INPUT_SIZE * sizeof(int16_t));
     sws = sws_alloc_context();
-    c = sws_internal(sws);
     if (accurate)
-        c->opts.flags |= SWS_ACCURATE_RND;
+        sws->flags |= SWS_ACCURATE_RND;
     if (sws_init_context(sws, NULL, NULL) < 0)
         fail();
 
+    c = sws_internal(sws);
     ff_sws_init_scale(c);
     for(isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); ++isi){
         dstW = input_sizes[isi];
@@ -341,20 +341,20 @@  static void check_hscale(void)
 
                     filter[SRC_PIXELS * width + i] = rnd();
                 }
-                c->opts.dst_w = c->chrDstW = input_sizes[dstWi];
+                sws->dst_w = c->chrDstW = input_sizes[dstWi];
                 ff_sws_init_scale(c);
                 memcpy(filterAvx2, filter, sizeof(uint16_t) * (SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH));
-                ff_shuffle_filter_coefficients(c, filterPosAvx, width, filterAvx2, c->opts.dst_w);
+                ff_shuffle_filter_coefficients(c, filterPosAvx, width, filterAvx2, sws->dst_w);
 
-                if (check_func(c->hcScale, "hscale_%d_to_%d__fs_%d_dstW_%d", c->srcBpc, c->dstBpc + 1, width, c->opts.dst_w)) {
+                if (check_func(c->hcScale, "hscale_%d_to_%d__fs_%d_dstW_%d", c->srcBpc, c->dstBpc + 1, width, sws->dst_w)) {
                     memset(dst0, 0, SRC_PIXELS * sizeof(dst0[0]));
                     memset(dst1, 0, SRC_PIXELS * sizeof(dst1[0]));
 
-                    call_ref(NULL, dst0, c->opts.dst_w, src, filter, filterPos, width);
-                    call_new(NULL, dst1, c->opts.dst_w, src, filterAvx2, filterPosAvx, width);
-                    if (memcmp(dst0, dst1, c->opts.dst_w * sizeof(dst0[0])))
+                    call_ref(NULL, dst0, sws->dst_w, src, filter, filterPos, width);
+                    call_new(NULL, dst1, sws->dst_w, src, filterAvx2, filterPosAvx, width);
+                    if (memcmp(dst0, dst1, sws->dst_w * sizeof(dst0[0])))
                         fail();
-                    bench_new(NULL, dst0, c->opts.dst_w, src, filter, filterPosAvx, width);
+                    bench_new(NULL, dst0, sws->dst_w, src, filter, filterPosAvx, width);
                 }
             }
         }