diff mbox series

[FFmpeg-devel,v3,11/18] swscale: expose SwsContext publicly

Message ID 20241020200851.1414766-12-ffmpeg@haasn.xyz
State New
Headers show
Series major refactor and new scaling API | expand

Commit Message

Niklas Haas Oct. 20, 2024, 8:05 p.m. UTC
From: Niklas Haas <git@haasn.dev>

This commit does the ardous work of splitting the options out of SwsInternal.
To avoid having to change leaf functions too much in one commit, we simply
leave behind a pointer to the main context, and replace all references to
the corresponding options by a simple search-and-replace.

Only the functions inside swscale.c and utils.c are modified in nontrivial
ways, since they retain the SwsContext public signature.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
---
 libswscale/aarch64/swscale.c                  |  30 +-
 libswscale/aarch64/swscale_unscaled.c         |  34 +-
 libswscale/alphablend.c                       |  16 +-
 libswscale/arm/swscale_unscaled.c             |  24 +-
 libswscale/input.c                            |   2 +-
 libswscale/loongarch/input_lasx.c             |   2 +-
 libswscale/loongarch/input_lsx.c              |   2 +-
 libswscale/loongarch/output_lasx.c            |  10 +-
 libswscale/loongarch/output_lsx.c             |  10 +-
 libswscale/loongarch/swscale_init_loongarch.c |  32 +-
 libswscale/loongarch/swscale_lasx.c           |   8 +-
 libswscale/loongarch/swscale_lsx.c            |   8 +-
 libswscale/loongarch/yuv2rgb_lasx.c           |   8 +-
 libswscale/loongarch/yuv2rgb_lsx.c            |  12 +-
 libswscale/options.c                          |  31 +-
 libswscale/output.c                           |  24 +-
 libswscale/ppc/swscale_altivec.c              |   6 +-
 libswscale/ppc/swscale_vsx.c                  |  18 +-
 libswscale/ppc/yuv2rgb_altivec.c              |  36 +-
 libswscale/ppc/yuv2yuv_altivec.c              |  14 +-
 libswscale/riscv/swscale.c                    |   6 +-
 libswscale/slice.c                            |  22 +-
 libswscale/swscale.c                          | 187 ++++----
 libswscale/swscale.h                          |  98 ++++-
 libswscale/swscale_internal.h                 |  48 +-
 libswscale/swscale_unscaled.c                 | 310 ++++++-------
 libswscale/utils.c                            | 414 +++++++++---------
 libswscale/vscale.c                           |  12 +-
 libswscale/x86/output.asm                     |   2 +-
 libswscale/x86/swscale.c                      |  60 +--
 libswscale/x86/swscale_template.c             |  20 +-
 libswscale/x86/yuv2rgb.c                      |  14 +-
 libswscale/yuv2rgb.c                          |  84 ++--
 tests/checkasm/sw_gbrp.c                      |  16 +-
 tests/checkasm/sw_range_convert.c             |  16 +-
 tests/checkasm/sw_rgb.c                       |  28 +-
 tests/checkasm/sw_scale.c                     |  22 +-
 37 files changed, 867 insertions(+), 819 deletions(-)

Comments

Michael Niedermayer Oct. 23, 2024, 2:30 p.m. UTC | #1
On Sun, Oct 20, 2024 at 10:05:20PM +0200, Niklas Haas wrote:
> From: Niklas Haas <git@haasn.dev>
> 
> This commit does the ardous work of splitting the options out of SwsInternal.
> To avoid having to change leaf functions too much in one commit, we simply
> leave behind a pointer to the main context, and replace all references to
> the corresponding options by a simple search-and-replace.
> 
> Only the functions inside swscale.c and utils.c are modified in nontrivial
> ways, since they retain the SwsContext public signature.
> 
> Sponsored-by: Sovereign Tech Fund
> Signed-off-by: Niklas Haas <git@haasn.dev>
> ---
>  libswscale/aarch64/swscale.c                  |  30 +-
>  libswscale/aarch64/swscale_unscaled.c         |  34 +-
>  libswscale/alphablend.c                       |  16 +-
>  libswscale/arm/swscale_unscaled.c             |  24 +-
>  libswscale/input.c                            |   2 +-
>  libswscale/loongarch/input_lasx.c             |   2 +-
>  libswscale/loongarch/input_lsx.c              |   2 +-
>  libswscale/loongarch/output_lasx.c            |  10 +-
>  libswscale/loongarch/output_lsx.c             |  10 +-
>  libswscale/loongarch/swscale_init_loongarch.c |  32 +-
>  libswscale/loongarch/swscale_lasx.c           |   8 +-
>  libswscale/loongarch/swscale_lsx.c            |   8 +-
>  libswscale/loongarch/yuv2rgb_lasx.c           |   8 +-
>  libswscale/loongarch/yuv2rgb_lsx.c            |  12 +-
>  libswscale/options.c                          |  31 +-
>  libswscale/output.c                           |  24 +-
>  libswscale/ppc/swscale_altivec.c              |   6 +-
>  libswscale/ppc/swscale_vsx.c                  |  18 +-
>  libswscale/ppc/yuv2rgb_altivec.c              |  36 +-
>  libswscale/ppc/yuv2yuv_altivec.c              |  14 +-
>  libswscale/riscv/swscale.c                    |   6 +-
>  libswscale/slice.c                            |  22 +-
>  libswscale/swscale.c                          | 187 ++++----
>  libswscale/swscale.h                          |  98 ++++-
>  libswscale/swscale_internal.h                 |  48 +-
>  libswscale/swscale_unscaled.c                 | 310 ++++++-------
>  libswscale/utils.c                            | 414 +++++++++---------
>  libswscale/vscale.c                           |  12 +-
>  libswscale/x86/output.asm                     |   2 +-
>  libswscale/x86/swscale.c                      |  60 +--
>  libswscale/x86/swscale_template.c             |  20 +-
>  libswscale/x86/yuv2rgb.c                      |  14 +-
>  libswscale/yuv2rgb.c                          |  84 ++--
>  tests/checkasm/sw_gbrp.c                      |  16 +-
>  tests/checkasm/sw_range_convert.c             |  16 +-
>  tests/checkasm/sw_rgb.c                       |  28 +-
>  tests/checkasm/sw_scale.c                     |  22 +-
>  37 files changed, 867 insertions(+), 819 deletions(-)

on ubuntu x86-64

CC	libswscale/alphablend.o
In file included from ./libavutil/internal.h:39,
                 from ./libavutil/common.h:50,
                 from ./libavutil/avutil.h:301,
                 from libswscale/swscale.h:33,
                 from libswscale/swscale_internal.h:28,
                 from libswscale/alphablend.c:21:
libswscale/swscale_internal.h:677:1: error: static assertion failed: "yuv2rgb_y_offset must be updated in x86 asm"
  677 | static_assert(offsetof(SwsInternal, yuv2rgb_y_offset) == 40332,
      | ^~~~~~~~~~~~~
make: *** [ffbuild/common.mak:81: libswscale/alphablend.o] Error 1

[...]
Anton Khirnov Oct. 24, 2024, 9:14 a.m. UTC | #2
Quoting Niklas Haas (2024-10-20 22:05:20)
> +/**
> + * Main external API structure. New fields can be added to the end with
> + * minor version bumps. Removal, reordering and changes to existing fields
> + * require a major version bump. sizeof(SwsContext) is not part of the ABI.
> + */
> +typedef struct SwsContext {
> +    const AVClass *av_class;
> +
> +    /**
> +     * Private context used for internal data.
> +     */
> +    struct SwsInternal *internal;

Why is this visible in the public context?
Niklas Haas Oct. 24, 2024, 9:28 a.m. UTC | #3
On Thu, 24 Oct 2024 11:14:32 +0200 Anton Khirnov <anton@khirnov.net> wrote:
> Quoting Niklas Haas (2024-10-20 22:05:20)
> > +/**
> > + * Main external API structure. New fields can be added to the end with
> > + * minor version bumps. Removal, reordering and changes to existing fields
> > + * require a major version bump. sizeof(SwsContext) is not part of the ABI.
> > + */
> > +typedef struct SwsContext {
> > +    const AVClass *av_class;
> > +
> > +    /**
> > +     * Private context used for internal data.
> > +     */
> > +    struct SwsInternal *internal;
>
> Why is this visible in the public context?

I was following the precedent established by AVCodecContext.

If you prefer, I could instead allocate SwsInternal as a superset of
SwsContext. That would actually make a lot of the code changes a bit cleaner
to implement, and avoids some pointer dereferencing.
Anton Khirnov Oct. 24, 2024, 10:01 a.m. UTC | #4
Quoting Niklas Haas (2024-10-24 11:28:16)
> On Thu, 24 Oct 2024 11:14:32 +0200 Anton Khirnov <anton@khirnov.net> wrote:
> > Quoting Niklas Haas (2024-10-20 22:05:20)
> > > +/**
> > > + * Main external API structure. New fields can be added to the end with
> > > + * minor version bumps. Removal, reordering and changes to existing fields
> > > + * require a major version bump. sizeof(SwsContext) is not part of the ABI.
> > > + */
> > > +typedef struct SwsContext {
> > > +    const AVClass *av_class;
> > > +
> > > +    /**
> > > +     * Private context used for internal data.
> > > +     */
> > > +    struct SwsInternal *internal;
> >
> > Why is this visible in the public context?
> 
> I was following the precedent established by AVCodecContext.

That's historical and we are gradually moving away from it, especially
in new code. See e.g. fed02825081bd6441f865c9cfcf50e384b2392f5.

> If you prefer, I could instead allocate SwsInternal as a superset of
> SwsContext. That would actually make a lot of the code changes a bit cleaner
> to implement, and avoids some pointer dereferencing.

I think that would be preferable.
diff mbox series

Patch

diff --git a/libswscale/aarch64/swscale.c b/libswscale/aarch64/swscale.c
index 4c31b78ed8..60a189c142 100644
--- a/libswscale/aarch64/swscale.c
+++ b/libswscale/aarch64/swscale.c
@@ -45,11 +45,11 @@  static void ff_hscale16to15_4_neon(SwsInternal *c, int16_t *_dst, int dstW,
                       const uint8_t *_src, const int16_t *filter,
                       const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int sh              = desc->comp[0].depth - 1;
 
     if (sh<15) {
-        sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
+        sh = isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
     } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
         sh = 16 - 1;
     }
@@ -61,11 +61,11 @@  static void ff_hscale16to15_X8_neon(SwsInternal *c, int16_t *_dst, int dstW,
                       const uint8_t *_src, const int16_t *filter,
                       const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int sh              = desc->comp[0].depth - 1;
 
     if (sh<15) {
-        sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
+        sh = isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
     } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
         sh = 16 - 1;
     }
@@ -77,11 +77,11 @@  static void ff_hscale16to15_X4_neon(SwsInternal *c, int16_t *_dst, int dstW,
                       const uint8_t *_src, const int16_t *filter,
                       const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int sh              = desc->comp[0].depth - 1;
 
     if (sh<15) {
-        sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
+        sh = isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
     } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
         sh = 16 - 1;
     }
@@ -92,11 +92,11 @@  static void ff_hscale16to19_4_neon(SwsInternal *c, int16_t *_dst, int dstW,
                            const uint8_t *_src, const int16_t *filter,
                            const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int bits            = desc->comp[0].depth - 1;
     int sh              = bits - 4;
 
-    if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
+    if ((isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
         sh = 9;
     } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
         sh = 16 - 1 - 4;
@@ -110,11 +110,11 @@  static void ff_hscale16to19_X8_neon(SwsInternal *c, int16_t *_dst, int dstW,
                            const uint8_t *_src, const int16_t *filter,
                            const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int bits            = desc->comp[0].depth - 1;
     int sh              = bits - 4;
 
-    if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
+    if ((isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
         sh = 9;
     } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
         sh = 16 - 1 - 4;
@@ -128,11 +128,11 @@  static void ff_hscale16to19_X4_neon(SwsInternal *c, int16_t *_dst, int dstW,
                            const uint8_t *_src, const int16_t *filter,
                            const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int bits            = desc->comp[0].depth - 1;
     int sh              = bits - 4;
 
-    if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
+    if ((isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
         sh = 9;
     } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
         sh = 16 - 1 - 4;
@@ -225,9 +225,9 @@  void ff_chrRangeToJpeg_neon(int16_t *dstU, int16_t *dstV, int width);
 
 av_cold void ff_sws_init_range_convert_aarch64(SwsInternal *c)
 {
-    if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
+    if (c->sws->src_range != c->sws->dst_range && !isAnyRGB(c->sws->dst_format)) {
         if (c->dstBpc <= 14) {
-            if (c->srcRange) {
+            if (c->sws->src_range) {
                 c->lumConvertRange = ff_lumRangeFromJpeg_neon;
                 c->chrConvertRange = ff_chrRangeFromJpeg_neon;
             } else {
@@ -249,7 +249,7 @@  av_cold void ff_sws_init_swscale_aarch64(SwsInternal *c)
         if (c->dstBpc == 8) {
             c->yuv2planeX = ff_yuv2planeX_8_neon;
         }
-        switch (c->srcFormat) {
+        switch (c->sws->src_format) {
         case AV_PIX_FMT_ABGR:
             c->lumToYV12 = ff_abgr32ToY_neon;
             if (c->chrSrcHSubSample)
diff --git a/libswscale/aarch64/swscale_unscaled.c b/libswscale/aarch64/swscale_unscaled.c
index 4f54120445..29f08f7ca9 100644
--- a/libswscale/aarch64/swscale_unscaled.c
+++ b/libswscale/aarch64/swscale_unscaled.c
@@ -43,7 +43,7 @@  static int ifmt##_to_##ofmt##_neon_wrapper(SwsInternal *c, const uint8_t *const
                                            const int dstStride[]) {                         \
     const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE };                                   \
                                                                                             \
-    return ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH,                                 \
+    return ff_##ifmt##_to_##ofmt##_neon(c->sws->src_w, srcSliceH,                           \
                                         dst[0] + srcSliceY * dstStride[0], dstStride[0],    \
                                         src[0], srcStride[0],                               \
                                         src[1], srcStride[1],                               \
@@ -71,7 +71,7 @@  static int ifmt##_to_##ofmt##_neon_wrapper(SwsInternal *c, const uint8_t *const
                                            const int dstStride[]) {                         \
     const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE };                                   \
                                                                                             \
-    return ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH,                                 \
+    return ff_##ifmt##_to_##ofmt##_neon(c->sws->src_w, srcSliceH,                           \
                                         dst[0] + srcSliceY * dstStride[0], dstStride[0],    \
                                         src[0], srcStride[0],                               \
                                         src[1], srcStride[1],                               \
@@ -108,7 +108,7 @@  static int ifmt##_to_##ofmt##_neon_wrapper(SwsInternal *c, const uint8_t *const
                                            const int dstStride[]) {                         \
     const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE };                                   \
                                                                                             \
-    return ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH,                                 \
+    return ff_##ifmt##_to_##ofmt##_neon(c->sws->src_w, srcSliceH,                           \
                                         dst[0] + srcSliceY * dstStride[0], dstStride[0],    \
                                         src[0], srcStride[0], src[1], srcStride[1],         \
                                         yuv2rgb_table,                                      \
@@ -133,7 +133,7 @@  static int ifmt##_to_##ofmt##_neon_wrapper(SwsInternal *c, const uint8_t *const
                                            const int dstStride[]) {                         \
     const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE };                                   \
                                                                                             \
-    return ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH,                                 \
+    return ff_##ifmt##_to_##ofmt##_neon(c->sws->src_w, srcSliceH,                           \
                                         dst[0] + srcSliceY * dstStride[0], dstStride[0],    \
                                         src[0], srcStride[0], src[1], srcStride[1],         \
                                         yuv2rgb_table,                                      \
@@ -155,15 +155,17 @@  static int nv24_to_yuv420p_neon_wrapper(SwsInternal *c, const uint8_t *const src
     uint8_t *dst1 = dst[1] + dstStride[1] * srcSliceY / 2;
     uint8_t *dst2 = dst[2] + dstStride[2] * srcSliceY / 2;
 
-    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
+    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->sws->src_w,
                  dst[0], dstStride[0]);
 
-    if (c->srcFormat == AV_PIX_FMT_NV24)
+    if (c->sws->src_format == AV_PIX_FMT_NV24)
         ff_nv24_to_yuv420p_chroma_neon(dst1, dstStride[1], dst2, dstStride[2],
-                                       src[1], srcStride[1], c->srcW / 2, srcSliceH);
+                                       src[1], srcStride[1], c->sws->src_w / 2,
+                                       srcSliceH);
     else
         ff_nv24_to_yuv420p_chroma_neon(dst2, dstStride[2], dst1, dstStride[1],
-                                       src[1], srcStride[1], c->srcW / 2, srcSliceH);
+                                       src[1], srcStride[1], c->sws->src_w / 2,
+                                       srcSliceH);
 
     return srcSliceH;
 }
@@ -183,10 +185,10 @@  DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv21)
  * assembly might be writing as much as 4*15=60 extra bytes at the end of the
  * line, which won't fit the 32-bytes buffer alignment. */
 #define SET_FF_NVX_TO_RGBX_FUNC(ifmt, IFMT, ofmt, OFMT, accurate_rnd) do {                  \
-    if (c->srcFormat == AV_PIX_FMT_##IFMT                                                   \
-        && c->dstFormat == AV_PIX_FMT_##OFMT                                                \
-        && !(c->srcH & 1)                                                                   \
-        && !(c->srcW & 15)                                                                  \
+    if (c->sws->src_format == AV_PIX_FMT_##IFMT                                             \
+        && c->sws->dst_format == AV_PIX_FMT_##OFMT                                          \
+        && !(c->sws->src_h & 1)                                                             \
+        && !(c->sws->src_w & 15)                                                            \
         && !accurate_rnd)                                                                   \
         c->convert_unscaled = ifmt##_to_##ofmt##_neon_wrapper;                              \
 } while (0)
@@ -200,16 +202,16 @@  DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv21)
 } while (0)
 
 static void get_unscaled_swscale_neon(SwsInternal *c) {
-    int accurate_rnd = c->flags & SWS_ACCURATE_RND;
+    int accurate_rnd = c->sws->flags & SWS_ACCURATE_RND;
 
     SET_FF_NVX_TO_ALL_RGBX_FUNC(nv12, NV12, accurate_rnd);
     SET_FF_NVX_TO_ALL_RGBX_FUNC(nv21, NV21, accurate_rnd);
     SET_FF_NVX_TO_ALL_RGBX_FUNC(yuv420p, YUV420P, accurate_rnd);
     SET_FF_NVX_TO_ALL_RGBX_FUNC(yuv422p, YUV422P, accurate_rnd);
 
-    if (c->dstFormat == AV_PIX_FMT_YUV420P &&
-        (c->srcFormat == AV_PIX_FMT_NV24 || c->srcFormat == AV_PIX_FMT_NV42) &&
-        !(c->srcH & 1) && !(c->srcW & 15) && !accurate_rnd)
+    if (c->sws->dst_format == AV_PIX_FMT_YUV420P &&
+        (c->sws->src_format == AV_PIX_FMT_NV24 || c->sws->src_format == AV_PIX_FMT_NV42) &&
+        !(c->sws->src_h & 1) && !(c->sws->src_w & 15) && !accurate_rnd)
         c->convert_unscaled = nv24_to_yuv420p_neon_wrapper;
 }
 
diff --git a/libswscale/alphablend.c b/libswscale/alphablend.c
index 4ee23d3aee..db3bd7f17f 100644
--- a/libswscale/alphablend.c
+++ b/libswscale/alphablend.c
@@ -24,10 +24,10 @@  int ff_sws_alphablendaway(SwsInternal *c, const uint8_t *const src[],
                           const int srcStride[], int srcSliceY, int srcSliceH,
                           uint8_t *const dst[], const int dstStride[])
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int nb_components = desc->nb_components;
     int plane, x, ysrc;
-    int plane_count = isGray(c->srcFormat) ? 1 : 3;
+    int plane_count = isGray(c->sws->src_format) ? 1 : 3;
     int sixteen_bits = desc->comp[0].depth >= 9;
     unsigned off    = 1<<(desc->comp[0].depth - 1);
     unsigned shift  = desc->comp[0].depth;
@@ -36,7 +36,7 @@  int ff_sws_alphablendaway(SwsInternal *c, const uint8_t *const src[],
 
     for (plane = 0; plane < plane_count; plane++) {
         int a = 0, b = 0;
-        if (c->alphablend == SWS_ALPHA_BLEND_CHECKERBOARD) {
+        if (c->sws->alpha_blend == SWS_ALPHA_BLEND_CHECKERBOARD) {
             a = (1<<(desc->comp[0].depth - 1))/2;
             b = 3*(1<<(desc->comp[0].depth-1))/2;
         }
@@ -47,7 +47,7 @@  int ff_sws_alphablendaway(SwsInternal *c, const uint8_t *const src[],
     av_assert0(plane_count == nb_components - 1);
     if (desc->flags & AV_PIX_FMT_FLAG_PLANAR) {
         for (plane = 0; plane < plane_count; plane++) {
-            int w = plane ? c->chrSrcW : c->srcW;
+            int w = plane ? c->chrSrcW : c->sws->src_w;
             int x_subsample = plane ? desc->log2_chroma_w: 0;
             int y_subsample = plane ? desc->log2_chroma_h: 0;
             for (ysrc = 0; ysrc < AV_CEIL_RSHIFT(srcSliceH, y_subsample); ysrc++) {
@@ -60,7 +60,7 @@  int ff_sws_alphablendaway(SwsInternal *c, const uint8_t *const src[],
                         const uint16_t *s = (const uint16_t *)(src[plane      ] +  srcStride[plane      ] * ysrc);
                         const uint16_t *a = (const uint16_t *)(src[plane_count] + (srcStride[plane_count] * ysrc << y_subsample));
                               uint16_t *d = (      uint16_t *)(dst[plane      ] +  dstStride[plane      ] * y);
-                        if ((!isBE(c->srcFormat)) == !HAVE_BIGENDIAN) {
+                        if ((!isBE(c->sws->src_format)) == !HAVE_BIGENDIAN) {
                             for (x = 0; x < w; x++) {
                                 if (y_subsample) {
                                     alpha = (a[2*x]              + a[2*x + 1] + 2 +
@@ -101,7 +101,7 @@  int ff_sws_alphablendaway(SwsInternal *c, const uint8_t *const src[],
                     const uint16_t *s = (const uint16_t *)(src[plane      ] + srcStride[plane      ] * ysrc);
                     const uint16_t *a = (const uint16_t *)(src[plane_count] + srcStride[plane_count] * ysrc);
                           uint16_t *d = (      uint16_t *)(dst[plane      ] + dstStride[plane      ] * y);
-                    if ((!isBE(c->srcFormat)) == !HAVE_BIGENDIAN) {
+                    if ((!isBE(c->sws->src_format)) == !HAVE_BIGENDIAN) {
                         for (x = 0; x < w; x++) {
                             unsigned u = s[x]*a[x] + target_table[((x^y)>>5)&1][plane]*(max-a[x]) + off;
                             d[x] = av_clip((u + (u >> shift)) >> shift, 0, max);
@@ -127,14 +127,14 @@  int ff_sws_alphablendaway(SwsInternal *c, const uint8_t *const src[],
         }
     } else {
         int alpha_pos = desc->comp[plane_count].offset;
-        int w = c->srcW;
+        int w = c->sws->src_w;
         for (ysrc = 0; ysrc < srcSliceH; ysrc++) {
             int y = ysrc + srcSliceY;
             if (sixteen_bits) {
                 const uint16_t *s = (const uint16_t *)(src[0] + srcStride[0] * ysrc + 2*!alpha_pos);
                 const uint16_t *a = (const uint16_t *)(src[0] + srcStride[0] * ysrc +    alpha_pos);
                       uint16_t *d = (      uint16_t *)(dst[0] + dstStride[0] * y);
-                if ((!isBE(c->srcFormat)) == !HAVE_BIGENDIAN) {
+                if ((!isBE(c->sws->src_format)) == !HAVE_BIGENDIAN) {
                     for (x = 0; x < w; x++) {
                         for (plane = 0; plane < plane_count; plane++) {
                             int x_index = (plane_count + 1) * x;
diff --git a/libswscale/arm/swscale_unscaled.c b/libswscale/arm/swscale_unscaled.c
index 14685dbc50..8b23bc01eb 100644
--- a/libswscale/arm/swscale_unscaled.c
+++ b/libswscale/arm/swscale_unscaled.c
@@ -41,7 +41,7 @@  static int rgbx_to_nv12_neon_32_wrapper(SwsInternal *context, const uint8_t *con
     rgbx_to_nv12_neon_32(src[0] + srcSliceY * srcStride[0],
             dst[0] + srcSliceY * dstStride[0],
             dst[1] + (srcSliceY / 2) * dstStride[1],
-            context->srcW, srcSliceH,
+            context->opts.src_w, srcSliceH,
             dstStride[0], dstStride[1], srcStride[0],
             context->input_rgb2yuv_table);
 
@@ -55,7 +55,7 @@  static int rgbx_to_nv12_neon_16_wrapper(SwsInternal *context, const uint8_t *con
     rgbx_to_nv12_neon_16(src[0] + srcSliceY * srcStride[0],
             dst[0] + srcSliceY * dstStride[0],
             dst[1] + (srcSliceY / 2) * dstStride[1],
-            context->srcW, srcSliceH,
+            context->opts.src_w, srcSliceH,
             dstStride[0], dstStride[1], srcStride[0],
             context->input_rgb2yuv_table);
 
@@ -84,7 +84,7 @@  static int ifmt##_to_##ofmt##_neon_wrapper(SwsInternal *c, const uint8_t *const
                                            const int dstStride[]) {                         \
     const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE };                                   \
                                                                                             \
-    ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH,                                        \
+    ff_##ifmt##_to_##ofmt##_neon(c->sws->src_w, srcSliceH,                                  \
                                  dst[0] + srcSliceY * dstStride[0], dstStride[0],           \
                                  src[0], srcStride[0],                                      \
                                  src[1], srcStride[1],                                      \
@@ -120,7 +120,7 @@  static int ifmt##_to_##ofmt##_neon_wrapper(SwsInternal *c, const uint8_t *const
                                            const int dstStride[]) {                         \
     const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE };                                   \
                                                                                             \
-    ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH,                                        \
+    ff_##ifmt##_to_##ofmt##_neon(c->sws->src_w, srcSliceH,                                  \
                                  dst[0] + srcSliceY * dstStride[0], dstStride[0],           \
                                  src[0], srcStride[0], src[1], srcStride[1],                \
                                  yuv2rgb_table,                                             \
@@ -144,10 +144,10 @@  DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv21)
  * assembly might be writing as much as 4*15=60 extra bytes at the end of the
  * line, which won't fit the 32-bytes buffer alignment. */
 #define SET_FF_NVX_TO_RGBX_FUNC(ifmt, IFMT, ofmt, OFMT, accurate_rnd) do {                  \
-    if (c->srcFormat == AV_PIX_FMT_##IFMT                                                   \
-        && c->dstFormat == AV_PIX_FMT_##OFMT                                                \
-        && !(c->srcH & 1)                                                                   \
-        && !(c->srcW & 15)                                                                  \
+    if (c->sws->src_format == AV_PIX_FMT_##IFMT                                             \
+        && c->sws->dst_format == AV_PIX_FMT_##OFMT                                          \
+        && !(c->sws->src_h & 1)                                                             \
+        && !(c->sws->src_w & 15)                                                            \
         && !accurate_rnd) {                                                                 \
         c->convert_unscaled = ifmt##_to_##ofmt##_neon_wrapper;                              \
     }                                                                                       \
@@ -161,10 +161,10 @@  DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv21)
 } while (0)
 
 static void get_unscaled_swscale_neon(SwsInternal *c) {
-    int accurate_rnd = c->flags & SWS_ACCURATE_RND;
-    if (c->srcFormat == AV_PIX_FMT_RGBA
-            && c->dstFormat == AV_PIX_FMT_NV12
-            && (c->srcW >= 16)) {
+    int accurate_rnd = c->sws->flags & SWS_ACCURATE_RND;
+    if (c->sws->src_format == AV_PIX_FMT_RGBA
+            && c->sws->dst_format == AV_PIX_FMT_NV12
+            && (c->sws->src_w >= 16)) {
         c->convert_unscaled = accurate_rnd ? rgbx_to_nv12_neon_32_wrapper
                                            : rgbx_to_nv12_neon_16_wrapper;
     }
diff --git a/libswscale/input.c b/libswscale/input.c
index a733ef35f8..f90239a2b2 100644
--- a/libswscale/input.c
+++ b/libswscale/input.c
@@ -1546,7 +1546,7 @@  av_cold void ff_sws_init_input_funcs(SwsInternal *c,
                                      planarX_YV12_fn *readAlpPlanar,
                                      planarX2_YV12_fn *readChrPlanar)
 {
-    enum AVPixelFormat srcFormat = c->srcFormat;
+    enum AVPixelFormat srcFormat = c->sws->src_format;
 
     *chrToYV12 = NULL;
     switch (srcFormat) {
diff --git a/libswscale/loongarch/input_lasx.c b/libswscale/loongarch/input_lasx.c
index b682179c6e..2057f898e9 100644
--- a/libswscale/loongarch/input_lasx.c
+++ b/libswscale/loongarch/input_lasx.c
@@ -203,7 +203,7 @@  void planar_rgb_to_y_lasx(uint8_t *_dst, const uint8_t *src[4], int width,
 
 av_cold void ff_sws_init_input_lasx(SwsInternal *c)
 {
-    enum AVPixelFormat srcFormat = c->srcFormat;
+    enum AVPixelFormat srcFormat = c->sws->src_format;
 
     switch (srcFormat) {
     case AV_PIX_FMT_YUYV422:
diff --git a/libswscale/loongarch/input_lsx.c b/libswscale/loongarch/input_lsx.c
index 2bc7577961..164fa94d46 100644
--- a/libswscale/loongarch/input_lsx.c
+++ b/libswscale/loongarch/input_lsx.c
@@ -23,7 +23,7 @@ 
 
 av_cold void ff_sws_init_input_lsx(SwsInternal *c)
 {
-    enum AVPixelFormat srcFormat = c->srcFormat;
+    enum AVPixelFormat srcFormat = c->sws->src_format;
 
     switch (srcFormat) {
     case AV_PIX_FMT_YUYV422:
diff --git a/libswscale/loongarch/output_lasx.c b/libswscale/loongarch/output_lasx.c
index 4e5ad3d802..59e4e4f21a 100644
--- a/libswscale/loongarch/output_lasx.c
+++ b/libswscale/loongarch/output_lasx.c
@@ -888,7 +888,7 @@  static av_always_inline void yuv2rgb_write_full(SwsInternal *c,
     {
         int r,g,b;
 
-        switch (c->dither) {
+        switch (c->sws->dither) {
         default:
         case SWS_DITHER_AUTO:
         case SWS_DITHER_ED:
@@ -1784,7 +1784,7 @@  av_cold void ff_sws_init_output_lasx(SwsInternal *c,
                                      yuv2packedX_fn *yuv2packedX,
                                      yuv2anyX_fn *yuv2anyX)
 {
-    enum AVPixelFormat dstFormat = c->dstFormat;
+    enum AVPixelFormat dstFormat = c->sws->dst_format;
 
     /* Add initialization once optimized */
     if (isSemiPlanarYUV(dstFormat) && isDataInHighBits(dstFormat)) {
@@ -1797,8 +1797,8 @@  av_cold void ff_sws_init_output_lasx(SwsInternal *c,
         *yuv2planeX = yuv2planeX_8_lasx;
     }
 
-    if(c->flags & SWS_FULL_CHR_H_INT) {
-        switch (c->dstFormat) {
+    if(c->sws->flags & SWS_FULL_CHR_H_INT) {
+        switch (c->sws->dst_format) {
         case AV_PIX_FMT_RGBA:
 #if CONFIG_SMALL
             c->yuv2packedX = yuv2rgba32_full_X_lasx;
@@ -1911,7 +1911,7 @@  av_cold void ff_sws_init_output_lasx(SwsInternal *c,
             break;
     }
     } else {
-        switch (c->dstFormat) {
+        switch (c->sws->dst_format) {
         case AV_PIX_FMT_RGB32:
         case AV_PIX_FMT_BGR32:
 #if CONFIG_SMALL
diff --git a/libswscale/loongarch/output_lsx.c b/libswscale/loongarch/output_lsx.c
index 29fe30758a..536b9b841c 100644
--- a/libswscale/loongarch/output_lsx.c
+++ b/libswscale/loongarch/output_lsx.c
@@ -838,7 +838,7 @@  static av_always_inline void yuv2rgb_write_full(SwsInternal *c,
     {
         int r,g,b;
 
-        switch (c->dither) {
+        switch (c->sws->dither) {
         default:
         case SWS_DITHER_AUTO:
         case SWS_DITHER_ED:
@@ -1633,7 +1633,7 @@  av_cold void ff_sws_init_output_lsx(SwsInternal *c,
                                     yuv2packedX_fn *yuv2packedX,
                                     yuv2anyX_fn *yuv2anyX)
 {
-    enum AVPixelFormat dstFormat = c->dstFormat;
+    enum AVPixelFormat dstFormat = c->sws->dst_format;
 
     /* Add initialization once optimized */
     if (isSemiPlanarYUV(dstFormat) && isDataInHighBits(dstFormat)) {
@@ -1646,8 +1646,8 @@  av_cold void ff_sws_init_output_lsx(SwsInternal *c,
         *yuv2planeX = yuv2planeX_8_lsx;
     }
 
-    if(c->flags & SWS_FULL_CHR_H_INT) {
-        switch (c->dstFormat) {
+    if(c->sws->flags & SWS_FULL_CHR_H_INT) {
+        switch (c->sws->dst_format) {
         case AV_PIX_FMT_RGBA:
 #if CONFIG_SMALL
             c->yuv2packedX = yuv2rgba32_full_X_lsx;
@@ -1760,7 +1760,7 @@  av_cold void ff_sws_init_output_lsx(SwsInternal *c,
             break;
     }
     } else {
-        switch (c->dstFormat) {
+        switch (c->sws->dst_format) {
         case AV_PIX_FMT_RGB32:
         case AV_PIX_FMT_BGR32:
 #if CONFIG_SMALL
diff --git a/libswscale/loongarch/swscale_init_loongarch.c b/libswscale/loongarch/swscale_init_loongarch.c
index 7cc92be216..455a9c7f0c 100644
--- a/libswscale/loongarch/swscale_init_loongarch.c
+++ b/libswscale/loongarch/swscale_init_loongarch.c
@@ -29,9 +29,9 @@  av_cold void ff_sws_init_range_convert_loongarch(SwsInternal *c)
     int cpu_flags = av_get_cpu_flags();
 
     if (have_lsx(cpu_flags)) {
-        if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
+        if (c->sws->src_range != c->sws->dst_range && !isAnyRGB(c->sws->dst_format)) {
             if (c->dstBpc <= 14) {
-                if (c->srcRange) {
+                if (c->sws->src_range) {
                     c->lumConvertRange = lumRangeFromJpeg_lsx;
                     c->chrConvertRange = chrRangeFromJpeg_lsx;
                 } else {
@@ -43,9 +43,9 @@  av_cold void ff_sws_init_range_convert_loongarch(SwsInternal *c)
     }
 #if HAVE_LASX
     if (have_lasx(cpu_flags)) {
-        if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
+        if (c->sws->src_range != c->sws->dst_range && !isAnyRGB(c->sws->dst_format)) {
             if (c->dstBpc <= 14) {
-                if (c->srcRange) {
+                if (c->sws->src_range) {
                     c->lumConvertRange = lumRangeFromJpeg_lasx;
                     c->chrConvertRange = chrRangeFromJpeg_lasx;
                 } else {
@@ -112,29 +112,29 @@  av_cold SwsFunc ff_yuv2rgb_init_loongarch(SwsInternal *c)
     int cpu_flags = av_get_cpu_flags();
 #if HAVE_LASX
     if (have_lasx(cpu_flags)) {
-        if (c->srcFormat == AV_PIX_FMT_YUV420P) {
-            switch (c->dstFormat) {
+        if (c->sws->src_format == AV_PIX_FMT_YUV420P) {
+            switch (c->sws->dst_format) {
                 case AV_PIX_FMT_RGB24:
                     return yuv420_rgb24_lasx;
                 case AV_PIX_FMT_BGR24:
                     return yuv420_bgr24_lasx;
                 case AV_PIX_FMT_RGBA:
-                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) {
+                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format)) {
                         break;
                     } else
                         return yuv420_rgba32_lasx;
                 case AV_PIX_FMT_ARGB:
-                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) {
+                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format)) {
                         break;
                     } else
                         return yuv420_argb32_lasx;
                 case AV_PIX_FMT_BGRA:
-                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) {
+                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format)) {
                         break;
                     } else
                         return yuv420_bgra32_lasx;
                 case AV_PIX_FMT_ABGR:
-                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) {
+                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format)) {
                         break;
                     } else
                         return yuv420_abgr32_lasx;
@@ -143,29 +143,29 @@  av_cold SwsFunc ff_yuv2rgb_init_loongarch(SwsInternal *c)
     }
 #endif // #if HAVE_LASX
     if (have_lsx(cpu_flags)) {
-        if (c->srcFormat == AV_PIX_FMT_YUV420P) {
-            switch (c->dstFormat) {
+        if (c->sws->src_format == AV_PIX_FMT_YUV420P) {
+            switch (c->sws->dst_format) {
                 case AV_PIX_FMT_RGB24:
                     return yuv420_rgb24_lsx;
                 case AV_PIX_FMT_BGR24:
                     return yuv420_bgr24_lsx;
                 case AV_PIX_FMT_RGBA:
-                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) {
+                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format)) {
                         break;
                     } else
                         return yuv420_rgba32_lsx;
                 case AV_PIX_FMT_ARGB:
-                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) {
+                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format)) {
                         break;
                     } else
                         return yuv420_argb32_lsx;
                 case AV_PIX_FMT_BGRA:
-                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) {
+                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format)) {
                         break;
                     } else
                         return yuv420_bgra32_lsx;
                 case AV_PIX_FMT_ABGR:
-                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) {
+                    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format)) {
                         break;
                     } else
                         return yuv420_abgr32_lsx;
diff --git a/libswscale/loongarch/swscale_lasx.c b/libswscale/loongarch/swscale_lasx.c
index 79fa4c64b0..8ad0966d4f 100644
--- a/libswscale/loongarch/swscale_lasx.c
+++ b/libswscale/loongarch/swscale_lasx.c
@@ -677,7 +677,7 @@  void ff_hscale_16_to_15_lasx(SwsInternal *c, int16_t *dst, int dstW,
                              const uint8_t *_src, const int16_t *filter,
                              const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int i;
     const uint16_t *src = (const uint16_t *) _src;
     int sh              = desc->comp[0].depth - 1;
@@ -688,7 +688,7 @@  void ff_hscale_16_to_15_lasx(SwsInternal *c, int16_t *dst, int dstW,
     __m256i zero = __lasx_xvldi(0);
 
     if (sh < 15) {
-        sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 :
+        sh = isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8 ? 13 :
                       (desc->comp[0].depth - 1);
     } else if (desc->flags && AV_PIX_FMT_FLAG_FLOAT) {
         sh = 15;
@@ -824,7 +824,7 @@  void ff_hscale_16_to_19_lasx(SwsInternal *c, int16_t *_dst, int dstW,
                              const uint8_t *_src, const int16_t *filter,
                              const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int i;
     int32_t *dst        = (int32_t *) _dst;
     const uint16_t *src = (const uint16_t *) _src;
@@ -835,7 +835,7 @@  void ff_hscale_16_to_19_lasx(SwsInternal *c, int16_t *_dst, int dstW,
     __m256i shift;
     __m256i zero = __lasx_xvldi(0);
 
-    if ((isAnyRGB(c->srcFormat) || c->srcFormat == AV_PIX_FMT_PAL8)
+    if ((isAnyRGB(c->sws->src_format) || c->sws->src_format == AV_PIX_FMT_PAL8)
          && desc->comp[0].depth<16) {
         sh = 9;
     } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) {
diff --git a/libswscale/loongarch/swscale_lsx.c b/libswscale/loongarch/swscale_lsx.c
index dbdaf18de6..c611810a6d 100644
--- a/libswscale/loongarch/swscale_lsx.c
+++ b/libswscale/loongarch/swscale_lsx.c
@@ -27,11 +27,11 @@  void ff_hscale_16_to_15_lsx(SwsInternal *c, int16_t *_dst, int dstW,
                             const uint8_t *_src, const int16_t *filter,
                             const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int sh              = desc->comp[0].depth - 1;
 
     if (sh < 15) {
-        sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 :
+        sh = isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8 ? 13 :
                       (desc->comp[0].depth - 1);
     } else if (desc->flags && AV_PIX_FMT_FLAG_FLOAT) {
         sh = 15;
@@ -43,11 +43,11 @@  void ff_hscale_16_to_19_lsx(SwsInternal *c, int16_t *_dst, int dstW,
                             const uint8_t *_src, const int16_t *filter,
                             const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int bits            = desc->comp[0].depth - 1;
     int sh              = bits - 4;
 
-    if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
+    if ((isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
 
         sh = 9;
     } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
diff --git a/libswscale/loongarch/yuv2rgb_lasx.c b/libswscale/loongarch/yuv2rgb_lasx.c
index 1b36d617b5..11d79ac71c 100644
--- a/libswscale/loongarch/yuv2rgb_lasx.c
+++ b/libswscale/loongarch/yuv2rgb_lasx.c
@@ -173,11 +173,11 @@ 
     __m256i shuf3 = {0x1E0F0E1C0D0C1A0B, 0x0101010101010101,                        \
                      0x1E0F0E1C0D0C1A0B, 0x0101010101010101};                       \
     YUV2RGB_LOAD_COE                                                                \
-    y      = (c->dstW + 7) & ~7;                                                    \
+    y      = (c->sws->dst_w + 7) & ~7;                                              \
     h_size = y >> 4;                                                                \
     res    = y & 15;                                                                \
                                                                                     \
-    vshift = c->srcFormat != AV_PIX_FMT_YUV422P;                                    \
+    vshift = c->sws->src_format != AV_PIX_FMT_YUV422P;                              \
     for (y = 0; y < srcSliceH; y += 2) {                                            \
         dst_type *image1    = (dst_type *)(dst[0] + (y + srcSliceY) * dstStride[0]);\
         dst_type *image2    = (dst_type *)(image1 +                   dstStride[0]);\
@@ -199,11 +199,11 @@ 
     __m256i a = __lasx_xvldi(0xFF);                                                 \
                                                                                     \
     YUV2RGB_LOAD_COE                                                                \
-    y      = (c->dstW + 7) & ~7;                                                    \
+    y      = (c->sws->dst_w + 7) & ~7;                                              \
     h_size = y >> 4;                                                                \
     res    = y & 15;                                                                \
                                                                                     \
-    vshift = c->srcFormat != AV_PIX_FMT_YUV422P;                                    \
+    vshift = c->sws->src_format != AV_PIX_FMT_YUV422P;                              \
     for (y = 0; y < srcSliceH; y += 2) {                                            \
         int yd = y + srcSliceY;                                                     \
         dst_type av_unused *r, *g, *b;                                              \
diff --git a/libswscale/loongarch/yuv2rgb_lsx.c b/libswscale/loongarch/yuv2rgb_lsx.c
index f2f424265f..a12159d555 100644
--- a/libswscale/loongarch/yuv2rgb_lsx.c
+++ b/libswscale/loongarch/yuv2rgb_lsx.c
@@ -128,9 +128,9 @@ 
                                                                                     \
     YUV2RGB_LOAD_COE                                                                \
                                                                                     \
-    h_size = c->dstW >> 4;                                                          \
-    res = (c->dstW & 15) >> 1;                                                      \
-    vshift = c->srcFormat != AV_PIX_FMT_YUV422P;                                    \
+    h_size = c->sws->dst_w >> 4;                                                    \
+    res = (c->sws->dst_w & 15) >> 1;                                                \
+    vshift = c->sws->src_format != AV_PIX_FMT_YUV422P;                              \
     for (y = 0; y < srcSliceH; y += 2) {                                            \
         dst_type av_unused *r, *g, *b;                                              \
         dst_type *image1    = (dst_type *)(dst[0] + (y + srcSliceY) * dstStride[0]);\
@@ -156,9 +156,9 @@ 
                                                                                     \
     YUV2RGB_LOAD_COE                                                                \
                                                                                     \
-    h_size = c->dstW >> 4;                                                          \
-    res = (c->dstW & 15) >> 1;                                                      \
-    vshift = c->srcFormat != AV_PIX_FMT_YUV422P;                                    \
+    h_size = c->sws->dst_w >> 4;                                                    \
+    res = (c->sws->dst_w & 15) >> 1;                                                \
+    vshift = c->sws->src_format != AV_PIX_FMT_YUV422P;                              \
     for (y = 0; y < srcSliceH; y += 2) {                                            \
         int yd = y + srcSliceY;                                                     \
         dst_type av_unused *r, *g, *b;                                              \
diff --git a/libswscale/options.c b/libswscale/options.c
index e64e289cf3..4ce7d8a36a 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, x)
+#define OFFSET(x) offsetof(SwsContext, x)
 #define DEFAULT 0
 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 
@@ -51,18 +51,18 @@  static const AVOption swscale_options[] = {
         { "bitexact",        "bit-exact mode",                0,  AV_OPT_TYPE_CONST, { .i64 = SWS_BITEXACT       }, .flags = VE, .unit = "sws_flags" },
         { "error_diffusion", "error diffusion dither",        0,  AV_OPT_TYPE_CONST, { .i64 = SWS_ERROR_DIFFUSION}, .flags = VE, .unit = "sws_flags" },
 
-    { "param0",              "scaler param 0", OFFSET(param[0]),  AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT  }, INT_MIN, INT_MAX, VE },
-    { "param1",              "scaler param 1", OFFSET(param[1]),  AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT  }, INT_MIN, INT_MAX, VE },
+    { "param0",          "scaler param 0", OFFSET(scaler_params[0]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT  }, INT_MIN, INT_MAX, VE },
+    { "param1",          "scaler param 1", OFFSET(scaler_params[1]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT  }, INT_MIN, INT_MAX, VE },
 
-    { "srcw",            "source width",                  OFFSET(srcW),      AV_OPT_TYPE_INT,    { .i64 = 16                 }, 1,       INT_MAX, VE },
-    { "srch",            "source height",                 OFFSET(srcH),      AV_OPT_TYPE_INT,    { .i64 = 16                 }, 1,       INT_MAX, VE },
-    { "dstw",            "destination width",             OFFSET(dstW),      AV_OPT_TYPE_INT,    { .i64 = 16                 }, 1,       INT_MAX, VE },
-    { "dsth",            "destination height",            OFFSET(dstH),      AV_OPT_TYPE_INT,    { .i64 = 16                 }, 1,       INT_MAX, VE },
-    { "src_format",      "source format",                 OFFSET(srcFormat), AV_OPT_TYPE_PIXEL_FMT,{ .i64 = DEFAULT          }, 0,       INT_MAX, VE },
-    { "dst_format",      "destination format",            OFFSET(dstFormat), AV_OPT_TYPE_PIXEL_FMT,{ .i64 = DEFAULT          }, 0,       INT_MAX, VE },
-    { "src_range",       "source is full range",          OFFSET(srcRange),  AV_OPT_TYPE_BOOL,   { .i64 = DEFAULT            }, 0,       1,       VE },
-    { "dst_range",       "destination is full range",     OFFSET(dstRange),  AV_OPT_TYPE_BOOL,   { .i64 = DEFAULT            }, 0,       1,       VE },
-    { "gamma",           "gamma correct scaling",         OFFSET(gamma_flag),AV_OPT_TYPE_BOOL,   { .i64  = 0                 }, 0,       1,       VE },
+    { "srcw",            "source width",                  OFFSET(src_w),      AV_OPT_TYPE_INT,       { .i64 = 16      }, 1, INT_MAX, VE },
+    { "srch",            "source height",                 OFFSET(src_h),      AV_OPT_TYPE_INT,       { .i64 = 16      }, 1, INT_MAX, VE },
+    { "dstw",            "destination width",             OFFSET(dst_w),      AV_OPT_TYPE_INT,       { .i64 = 16      }, 1, INT_MAX, VE },
+    { "dsth",            "destination height",            OFFSET(dst_h),      AV_OPT_TYPE_INT,       { .i64 = 16      }, 1, INT_MAX, VE },
+    { "src_format",      "source format",                 OFFSET(src_format), AV_OPT_TYPE_PIXEL_FMT, { .i64 = DEFAULT }, 0, INT_MAX, VE },
+    { "dst_format",      "destination format",            OFFSET(dst_format), AV_OPT_TYPE_PIXEL_FMT, { .i64 = DEFAULT }, 0, INT_MAX, VE },
+    { "src_range",       "source is full range",          OFFSET(src_range),  AV_OPT_TYPE_BOOL,      { .i64 = DEFAULT }, 0, 1,       VE },
+    { "dst_range",       "destination is full range",     OFFSET(dst_range),  AV_OPT_TYPE_BOOL,      { .i64 = DEFAULT }, 0, 1,       VE },
+    { "gamma",           "gamma correct scaling",         OFFSET(gamma_flag), AV_OPT_TYPE_BOOL,      { .i64  = 0      }, 0, 1,       VE },
 
     { "src_v_chr_pos",   "source vertical chroma position in luma grid/256"  ,      OFFSET(src_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513 }, -513, 1024, VE },
     { "src_h_chr_pos",   "source horizontal chroma position in luma grid/256",      OFFSET(src_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513 }, -513, 1024, VE },
@@ -76,13 +76,13 @@  static const AVOption swscale_options[] = {
         { "a_dither",    "arithmetic addition dither",    0,                 AV_OPT_TYPE_CONST,  { .i64  = SWS_DITHER_A_DITHER }, .flags = VE, .unit = "sws_dither" },
         { "x_dither",    "arithmetic xor dither",         0,                 AV_OPT_TYPE_CONST,  { .i64  = SWS_DITHER_X_DITHER }, .flags = VE, .unit = "sws_dither" },
 
-    { "alphablend",          "mode for alpha -> non alpha",   OFFSET(alphablend),  AV_OPT_TYPE_INT,    { .i64  = SWS_ALPHA_BLEND_NONE},         .flags = VE, .unit = "alphablend", .max = SWS_ALPHA_BLEND_NB - 1 },
+    { "alphablend",          "mode for alpha -> non alpha",   OFFSET(alpha_blend), AV_OPT_TYPE_INT,    { .i64  = SWS_ALPHA_BLEND_NONE},         .flags = VE, .unit = "alphablend", .max = SWS_ALPHA_BLEND_NB - 1 },
         { "none",            "ignore alpha",                  0,                   AV_OPT_TYPE_CONST,  { .i64  = SWS_ALPHA_BLEND_NONE},         .flags = VE, .unit = "alphablend" },
         { "uniform_color",   "blend onto a uniform color",    0,                   AV_OPT_TYPE_CONST,  { .i64  = SWS_ALPHA_BLEND_UNIFORM},      .flags = VE, .unit = "alphablend" },
         { "checkerboard",    "blend onto a checkerboard",     0,                   AV_OPT_TYPE_CONST,  { .i64  = SWS_ALPHA_BLEND_CHECKERBOARD}, .flags = VE, .unit = "alphablend" },
 
-    { "threads",         "number of threads",             OFFSET(nb_threads),   AV_OPT_TYPE_INT, {.i64 = 1 }, 0, INT_MAX, VE, .unit = "threads" },
-        { "auto",        "automatic selection",           0,                  AV_OPT_TYPE_CONST, {.i64 = 0 },    .flags = VE, .unit = "threads" },
+    { "threads",         "number of threads",             OFFSET(threads),   AV_OPT_TYPE_INT,   {.i64 = 1 }, .flags = VE, .unit = "threads", .max = INT_MAX },
+        { "auto",        "automatic selection",           0,                 AV_OPT_TYPE_CONST, {.i64 = 0 }, .flags = VE, .unit = "threads" },
 
     { NULL }
 };
@@ -91,7 +91,6 @@  const AVClass ff_sws_context_class = {
     .class_name = "SWScaler",
     .item_name  = sws_context_to_name,
     .option     = swscale_options,
-    .parent_log_context_offset = OFFSET(parent),
     .category   = AV_CLASS_CATEGORY_SWSCALER,
     .version    = LIBAVUTIL_VERSION_INT,
 };
diff --git a/libswscale/output.c b/libswscale/output.c
index 56f16dfd34..cb1adefdee 100644
--- a/libswscale/output.c
+++ b/libswscale/output.c
@@ -624,7 +624,7 @@  yuv2mono_X_c_template(SwsInternal *c, const int16_t *lumFilter,
             Y1 = av_clip_uint8(Y1);
             Y2 = av_clip_uint8(Y2);
         }
-        if (c->dither == SWS_DITHER_ED) {
+        if (c->sws->dither == SWS_DITHER_ED) {
             Y1 += (7*err + 1*c->dither_error[0][i] + 5*c->dither_error[0][i+1] + 3*c->dither_error[0][i+2] + 8 - 256)>>4;
             c->dither_error[0][i] = err;
             acc = 2*acc + (Y1 >= 128);
@@ -662,7 +662,7 @@  yuv2mono_2_c_template(SwsInternal *c, const int16_t *buf[2],
     int i;
     av_assert2(yalpha  <= 4096U);
 
-    if (c->dither == SWS_DITHER_ED) {
+    if (c->sws->dither == SWS_DITHER_ED) {
         int err = 0;
         int acc = 0;
         for (i = 0; i < dstW; i +=2) {
@@ -719,7 +719,7 @@  yuv2mono_1_c_template(SwsInternal *c, const int16_t *buf0,
     const uint8_t * const d128 = ff_dither_8x8_220[y & 7];
     int i;
 
-    if (c->dither == SWS_DITHER_ED) {
+    if (c->sws->dither == SWS_DITHER_ED) {
         int err = 0;
         int acc = 0;
         for (i = 0; i < dstW; i +=2) {
@@ -1976,7 +1976,7 @@  static av_always_inline void yuv2rgb_write_full(SwsInternal *c,
     {
         int r,g,b;
 
-        switch (c->dither) {
+        switch (c->sws->dither) {
         case SWS_DITHER_NONE:
             if (isrgb8) {
                 r = av_clip_uintp2(R >> 27, 3);
@@ -2249,7 +2249,7 @@  yuv2gbrp_full_X_c(SwsInternal *c, const int16_t *lumFilter,
                   const int16_t **alpSrc, uint8_t **dest,
                   int dstW, int y)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->dst_format);
     int i;
     int hasAlpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) && alpSrc;
     uint16_t **dest16 = (uint16_t**)dest;
@@ -2312,7 +2312,7 @@  yuv2gbrp_full_X_c(SwsInternal *c, const int16_t *lumFilter,
                 dest[3][i] = A >> 19;
         }
     }
-    if (SH != 22 && (!isBE(c->dstFormat)) != (!HAVE_BIGENDIAN)) {
+    if (SH != 22 && (!isBE(c->sws->dst_format)) != (!HAVE_BIGENDIAN)) {
         for (i = 0; i < dstW; i++) {
             dest16[0][i] = av_bswap16(dest16[0][i]);
             dest16[1][i] = av_bswap16(dest16[1][i]);
@@ -2331,7 +2331,7 @@  yuv2gbrp16_full_X_c(SwsInternal *c, const int16_t *lumFilter,
                     const int16_t **alpSrcx, uint8_t **dest,
                     int dstW, int y)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->dst_format);
     int i;
     int hasAlpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) && alpSrcx;
     uint16_t **dest16 = (uint16_t**)dest;
@@ -2384,7 +2384,7 @@  yuv2gbrp16_full_X_c(SwsInternal *c, const int16_t *lumFilter,
         if (hasAlpha)
             dest16[3][i] = av_clip_uintp2(A, 30) >> 14;
     }
-    if ((!isBE(c->dstFormat)) != (!HAVE_BIGENDIAN)) {
+    if ((!isBE(c->sws->dst_format)) != (!HAVE_BIGENDIAN)) {
         for (i = 0; i < dstW; i++) {
             dest16[0][i] = av_bswap16(dest16[0][i]);
             dest16[1][i] = av_bswap16(dest16[1][i]);
@@ -2403,7 +2403,7 @@  yuv2gbrpf32_full_X_c(SwsInternal *c, const int16_t *lumFilter,
                     const int16_t **alpSrcx, uint8_t **dest,
                     int dstW, int y)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->dst_format);
     int i;
     int hasAlpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) && alpSrcx;
     uint32_t **dest32 = (uint32_t**)dest;
@@ -2460,7 +2460,7 @@  yuv2gbrpf32_full_X_c(SwsInternal *c, const int16_t *lumFilter,
         if (hasAlpha)
             dest32[3][i] = av_float2int(float_mult * (float)(av_clip_uintp2(A, 30) >> 14));
     }
-    if ((!isBE(c->dstFormat)) != (!HAVE_BIGENDIAN)) {
+    if ((!isBE(c->sws->dst_format)) != (!HAVE_BIGENDIAN)) {
         for (i = 0; i < dstW; i++) {
             dest32[0][i] = av_bswap32(dest32[0][i]);
             dest32[1][i] = av_bswap32(dest32[1][i]);
@@ -3113,7 +3113,7 @@  av_cold void ff_sws_init_output_funcs(SwsInternal *c,
                                       yuv2packedX_fn *yuv2packedX,
                                       yuv2anyX_fn *yuv2anyX)
 {
-    enum AVPixelFormat dstFormat = c->dstFormat;
+    enum AVPixelFormat dstFormat = c->sws->dst_format;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
 
     if (isSemiPlanarYUV(dstFormat) && isDataInHighBits(dstFormat)) {
@@ -3161,7 +3161,7 @@  av_cold void ff_sws_init_output_funcs(SwsInternal *c,
             *yuv2nv12cX = yuv2nv12cX_c;
     }
 
-    if(c->flags & SWS_FULL_CHR_H_INT) {
+    if(c->sws->flags & SWS_FULL_CHR_H_INT) {
         switch (dstFormat) {
             case AV_PIX_FMT_RGBA:
 #if CONFIG_SMALL
diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c
index 836aaab1f8..fb03b17be9 100644
--- a/libswscale/ppc/swscale_altivec.c
+++ b/libswscale/ppc/swscale_altivec.c
@@ -232,7 +232,7 @@  yuv2plane1_float(yuv2plane1_float_bswap_altivec, uint32_t, BE)
 av_cold void ff_sws_init_swscale_ppc(SwsInternal *c)
 {
 #if HAVE_ALTIVEC
-    enum AVPixelFormat dstFormat = c->dstFormat;
+    enum AVPixelFormat dstFormat = c->sws->dst_format;
 
     if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC))
         return;
@@ -256,8 +256,8 @@  av_cold void ff_sws_init_swscale_ppc(SwsInternal *c)
 
     /* The following list of supported dstFormat values should
      * match what's found in the body of ff_yuv2packedX_altivec() */
-    if (!(c->flags & (SWS_BITEXACT | SWS_FULL_CHR_H_INT)) && !c->needAlpha) {
-        switch (c->dstFormat) {
+    if (!(c->sws->flags & (SWS_BITEXACT | SWS_FULL_CHR_H_INT)) && !c->needAlpha) {
+        switch (c->sws->dst_format) {
         case AV_PIX_FMT_ABGR:
             c->yuv2packedX = ff_yuv2abgr_X_altivec;
             break;
diff --git a/libswscale/ppc/swscale_vsx.c b/libswscale/ppc/swscale_vsx.c
index f83bb96ec9..2d18e1ebcf 100644
--- a/libswscale/ppc/swscale_vsx.c
+++ b/libswscale/ppc/swscale_vsx.c
@@ -1862,7 +1862,7 @@  static void hScale16To19_vsx(SwsInternal *c, int16_t *_dst, int dstW,
                              const uint8_t *_src, const int16_t *filter,
                              const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int i, j;
     int32_t *dst        = (int32_t *) _dst;
     const uint16_t *src = (const uint16_t *) _src;
@@ -1891,7 +1891,7 @@  static void hScale16To19_vsx(SwsInternal *c, int16_t *_dst, int dstW,
     };
     const vec_u8 vunused = vunusedtab[filterSize % 8];
 
-    if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
+    if ((isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
         sh = 9;
     } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
         sh = 16 - 1 - 4;
@@ -1940,7 +1940,7 @@  static void hScale16To15_vsx(SwsInternal *c, int16_t *dst, int dstW,
                              const uint8_t *_src, const int16_t *filter,
                              const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int i, j;
     const uint16_t *src = (const uint16_t *) _src;
     int sh              = desc->comp[0].depth - 1;
@@ -1968,7 +1968,7 @@  static void hScale16To15_vsx(SwsInternal *c, int16_t *dst, int dstW,
     const vec_u8 vunused = vunusedtab[filterSize % 8];
 
     if (sh<15) {
-        sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
+        sh = isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
     } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
         sh = 16 - 1;
     }
@@ -2019,7 +2019,7 @@  static void hScale16To15_vsx(SwsInternal *c, int16_t *dst, int dstW,
 av_cold void ff_sws_init_swscale_vsx(SwsInternal *c)
 {
 #if HAVE_VSX
-    enum AVPixelFormat dstFormat = c->dstFormat;
+    enum AVPixelFormat dstFormat = c->sws->dst_format;
     const int cpu_flags = av_get_cpu_flags();
     const unsigned char power8 = HAVE_POWER8 && cpu_flags & AV_CPU_FLAG_POWER8;
 
@@ -2030,7 +2030,7 @@  av_cold void ff_sws_init_swscale_vsx(SwsInternal *c)
     if (c->srcBpc == 8) {
         if (c->dstBpc <= 14) {
             c->hyScale = c->hcScale = hScale_real_vsx;
-            if (c->flags & SWS_FAST_BILINEAR && c->dstW >= c->srcW && c->chrDstW >= c->chrSrcW) {
+            if (c->sws->flags & SWS_FAST_BILINEAR && c->sws->dst_w >= c->sws->src_w && c->chrDstW >= c->chrSrcW) {
                 c->hyscale_fast = hyscale_fast_vsx;
                 c->hcscale_fast = hcscale_fast_vsx;
             }
@@ -2048,7 +2048,7 @@  av_cold void ff_sws_init_swscale_vsx(SwsInternal *c)
     }
 #endif
 
-    if (!(c->flags & (SWS_BITEXACT | SWS_FULL_CHR_H_INT)) && !c->needAlpha) {
+    if (!(c->sws->flags & (SWS_BITEXACT | SWS_FULL_CHR_H_INT)) && !c->needAlpha) {
         switch (c->dstBpc) {
         case 8:
             c->yuv2plane1 = yuv2plane1_8_vsx;
@@ -2082,11 +2082,11 @@  av_cold void ff_sws_init_swscale_vsx(SwsInternal *c)
         }
     }
 
-    if (c->flags & SWS_BITEXACT)
+    if (c->sws->flags & SWS_BITEXACT)
         return;
 
 #if !HAVE_BIGENDIAN
-    if (c->flags & SWS_FULL_CHR_H_INT) {
+    if (c->sws->flags & SWS_FULL_CHR_H_INT) {
         switch (dstFormat) {
             case AV_PIX_FMT_RGB24:
                 if (power8) {
diff --git a/libswscale/ppc/yuv2rgb_altivec.c b/libswscale/ppc/yuv2rgb_altivec.c
index 9db305f43f..e03382aac6 100644
--- a/libswscale/ppc/yuv2rgb_altivec.c
+++ b/libswscale/ppc/yuv2rgb_altivec.c
@@ -299,7 +299,7 @@  static int altivec_ ## name(SwsInternal *c, const unsigned char *const *in,   \
                             const int *instrides, int srcSliceY, int srcSliceH,   \
                             unsigned char *const *oplanes, const int *outstrides) \
 {                                                                             \
-    int w = c->srcW;                                                          \
+    int w = c->sws->src_w;                                                    \
     int h = srcSliceH;                                                        \
     int i, j;                                                                 \
     int instrides_scl[3];                                                     \
@@ -475,7 +475,7 @@  static int altivec_uyvy_rgb32(SwsInternal *c, const unsigned char *const *in,
                               const int *instrides, int srcSliceY, int srcSliceH,
                               unsigned char *const *oplanes, const int *outstrides)
 {
-    int w = c->srcW;
+    int w = c->sws->src_w;
     int h = srcSliceH;
     int i, j;
     vector unsigned char uyvy;
@@ -545,46 +545,46 @@  av_cold SwsFunc ff_yuv2rgb_init_ppc(SwsInternal *c)
      * boom with X11 bad match.
      *
      */
-    if ((c->srcW & 0xf) != 0)
+    if ((c->sws->src_w & 0xf) != 0)
         return NULL;
 
-    switch (c->srcFormat) {
+    switch (c->sws->src_format) {
     case AV_PIX_FMT_YUV410P:
     case AV_PIX_FMT_YUV420P:
     /*case IMGFMT_CLPL:        ??? */
     case AV_PIX_FMT_GRAY8:
     case AV_PIX_FMT_NV12:
     case AV_PIX_FMT_NV21:
-        if ((c->srcH & 0x1) != 0)
+        if ((c->sws->src_h & 0x1) != 0)
             return NULL;
 
-        switch (c->dstFormat) {
+        switch (c->sws->dst_format) {
         case AV_PIX_FMT_RGB24:
-            av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space RGB24\n");
+            av_log(c->sws, AV_LOG_WARNING, "ALTIVEC: Color Space RGB24\n");
             return altivec_yuv2_rgb24;
         case AV_PIX_FMT_BGR24:
-            av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space BGR24\n");
+            av_log(c->sws, AV_LOG_WARNING, "ALTIVEC: Color Space BGR24\n");
             return altivec_yuv2_bgr24;
         case AV_PIX_FMT_ARGB:
-            av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space ARGB\n");
+            av_log(c->sws, AV_LOG_WARNING, "ALTIVEC: Color Space ARGB\n");
             return altivec_yuv2_argb;
         case AV_PIX_FMT_ABGR:
-            av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space ABGR\n");
+            av_log(c->sws, AV_LOG_WARNING, "ALTIVEC: Color Space ABGR\n");
             return altivec_yuv2_abgr;
         case AV_PIX_FMT_RGBA:
-            av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space RGBA\n");
+            av_log(c->sws, AV_LOG_WARNING, "ALTIVEC: Color Space RGBA\n");
             return altivec_yuv2_rgba;
         case AV_PIX_FMT_BGRA:
-            av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space BGRA\n");
+            av_log(c->sws, AV_LOG_WARNING, "ALTIVEC: Color Space BGRA\n");
             return altivec_yuv2_bgra;
         default: return NULL;
         }
         break;
 
     case AV_PIX_FMT_UYVY422:
-        switch (c->dstFormat) {
+        switch (c->sws->dst_format) {
         case AV_PIX_FMT_BGR32:
-            av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space UYVY -> RGB32\n");
+            av_log(c->sws, AV_LOG_WARNING, "ALTIVEC: Color Space UYVY -> RGB32\n");
             return altivec_uyvy_rgb32;
         default: return NULL;
         }
@@ -740,9 +740,9 @@  static av_always_inline void yuv2packedX_altivec(SwsInternal *c,
              * instead. */
             static int printed_error_message;
             if (!printed_error_message) {
-                av_log(c, AV_LOG_ERROR,
+                av_log(c->sws, AV_LOG_ERROR,
                        "altivec_yuv2packedX doesn't support %s output\n",
-                       av_get_pix_fmt_name(c->dstFormat));
+                       av_get_pix_fmt_name(c->sws->dst_format));
                 printed_error_message = 1;
             }
             return;
@@ -828,9 +828,9 @@  static av_always_inline void yuv2packedX_altivec(SwsInternal *c,
             break;
         default:
             /* Unreachable, I think. */
-            av_log(c, AV_LOG_ERROR,
+            av_log(c->sws, AV_LOG_ERROR,
                    "altivec_yuv2packedX doesn't support %s output\n",
-                   av_get_pix_fmt_name(c->dstFormat));
+                   av_get_pix_fmt_name(c->sws->dst_format));
             return;
         }
 
diff --git a/libswscale/ppc/yuv2yuv_altivec.c b/libswscale/ppc/yuv2yuv_altivec.c
index 0ae5223760..906531fe8f 100644
--- a/libswscale/ppc/yuv2yuv_altivec.c
+++ b/libswscale/ppc/yuv2yuv_altivec.c
@@ -37,12 +37,12 @@  static int yv12toyuy2_unscaled_altivec(SwsInternal *c, const uint8_t *const src[
                                        const int dstStride_a[])
 {
     uint8_t *dst = dstParam[0] + dstStride_a[0] * srcSliceY;
-    // yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH,
+    // yv12toyuy2(src[0], src[1], src[2], dst, c->sws->src_w, srcSliceH,
     //            srcStride[0], srcStride[1], dstStride[0]);
     const uint8_t *ysrc   = src[0];
     const uint8_t *usrc   = src[1];
     const uint8_t *vsrc   = src[2];
-    const int width       = c->srcW;
+    const int width       = c->sws->src_w;
     const int height      = srcSliceH;
     const int lumStride   = srcStride[0];
     const int chromStride = srcStride[1];
@@ -113,12 +113,12 @@  static int yv12touyvy_unscaled_altivec(SwsInternal *c, const uint8_t *const src[
                                        const int dstStride_a[])
 {
     uint8_t *dst = dstParam[0] + dstStride_a[0] * srcSliceY;
-    // yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH,
+    // yv12toyuy2(src[0], src[1], src[2], dst, c->sws->src_w, srcSliceH,
     //            srcStride[0], srcStride[1], dstStride[0]);
     const uint8_t *ysrc              = src[0];
     const uint8_t *usrc              = src[1];
     const uint8_t *vsrc              = src[2];
-    const int width                  = c->srcW;
+    const int width                  = c->sws->src_w;
     const int height                 = srcSliceH;
     const int lumStride              = srcStride[0];
     const int chromStride            = srcStride[1];
@@ -190,9 +190,9 @@  av_cold void ff_get_unscaled_swscale_ppc(SwsInternal *c)
     if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC))
         return;
 
-    if (!(c->srcW & 15) && !(c->flags & SWS_BITEXACT) &&
-        c->srcFormat == AV_PIX_FMT_YUV420P) {
-        enum AVPixelFormat dstFormat = c->dstFormat;
+    if (!(c->sws->src_w & 15) && !(c->sws->flags & SWS_BITEXACT) &&
+        c->sws->src_format == AV_PIX_FMT_YUV420P) {
+        enum AVPixelFormat dstFormat = c->sws->dst_format;
 
         // unscaled YV12 -> packed YUV, we want speed
         if (dstFormat == AV_PIX_FMT_YUYV422)
diff --git a/libswscale/riscv/swscale.c b/libswscale/riscv/swscale.c
index 8ed9ce969e..7e44a85bcf 100644
--- a/libswscale/riscv/swscale.c
+++ b/libswscale/riscv/swscale.c
@@ -37,10 +37,10 @@  av_cold static void ff_sws_init_range_convert_riscv(SwsInternal *c, int flags)
         { ff_range_lum_from_jpeg_16_rvv, ff_range_chr_from_jpeg_16_rvv },
     };
 
-    if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat) &&
+    if (c->sws->src_range != c->sws->dst_range && !isAnyRGB(c->sws->dst_format) &&
         c->dstBpc <= 14 &&
         (flags & AV_CPU_FLAG_RVV_I32) && (flags & AV_CPU_FLAG_RVB)) {
-        bool from = c->srcRange != 0;
+        bool from = c->sws->src_range != 0;
 
         c->lumConvertRange = convs[from].lum;
         c->chrConvertRange = convs[from].chr;
@@ -71,7 +71,7 @@  av_cold void ff_sws_init_swscale_riscv(SwsInternal *c)
 
 #if HAVE_RVV
     if ((flags & AV_CPU_FLAG_RVV_I32) && (flags & AV_CPU_FLAG_RVB)) {
-        switch (c->srcFormat) {
+        switch (c->sws->src_format) {
             case AV_PIX_FMT_ABGR:
                 c->lumToYV12 = ff_abgr32ToY_rvv;
                 if (c->chrSrcHSubSample)
diff --git a/libswscale/slice.c b/libswscale/slice.c
index f13a839f98..b2fde00d0d 100644
--- a/libswscale/slice.c
+++ b/libswscale/slice.c
@@ -221,7 +221,7 @@  static void fill_ones(SwsSlice *s, int n, int bpc)
 static void get_min_buffer_size(SwsInternal *c, int *out_lum_size, int *out_chr_size)
 {
     int lumY;
-    int dstH = c->dstH;
+    int dstH = c->sws->dst_h;
     int chrDstH = c->chrDstH;
     int *lumFilterPos = c->vLumFilterPos;
     int *chrFilterPos = c->vChrFilterPos;
@@ -253,14 +253,14 @@  int ff_init_filters(SwsInternal * c)
     int index;
     int num_ydesc;
     int num_cdesc;
-    int num_vdesc = isPlanarYUV(c->dstFormat) && !isGray(c->dstFormat) ? 2 : 1;
+    int num_vdesc = isPlanarYUV(c->sws->dst_format) && !isGray(c->sws->dst_format) ? 2 : 1;
     int need_lum_conv = c->lumToYV12 || c->readLumPlanar || c->alpToYV12 || c->readAlpPlanar;
     int need_chr_conv = c->chrToYV12 || c->readChrPlanar;
     int need_gamma = c->is_internal_gamma;
     int srcIdx, dstIdx;
-    int dst_stride = FFALIGN(c->dstW * sizeof(int16_t) + 66, 16);
+    int dst_stride = FFALIGN(c->sws->dst_w * sizeof(int16_t) + 66, 16);
 
-    uint32_t * pal = usePal(c->srcFormat) ? c->pal_yuv : (uint32_t*)c->input_rgb2yuv_table;
+    uint32_t * pal = usePal(c->sws->src_format) ? c->pal_yuv : (uint32_t*)c->input_rgb2yuv_table;
     int res = 0;
 
     int lumBufSize;
@@ -284,7 +284,7 @@  int ff_init_filters(SwsInternal * c)
     c->descIndex[0] = num_ydesc + (need_gamma ? 1 : 0);
     c->descIndex[1] = num_ydesc + num_cdesc + (need_gamma ? 1 : 0);
 
-    if (isFloat16(c->srcFormat)) {
+    if (isFloat16(c->sws->src_format)) {
         c->h2f_tables = av_malloc(sizeof(*c->h2f_tables));
         if (!c->h2f_tables)
             return AVERROR(ENOMEM);
@@ -301,25 +301,25 @@  int ff_init_filters(SwsInternal * c)
         goto cleanup;
     }
 
-    res = alloc_slice(&c->slice[0], c->srcFormat, c->srcH, c->chrSrcH, c->chrSrcHSubSample, c->chrSrcVSubSample, 0);
+    res = alloc_slice(&c->slice[0], c->sws->src_format, c->sws->src_h, c->chrSrcH, c->chrSrcHSubSample, c->chrSrcVSubSample, 0);
     if (res < 0) goto cleanup;
     for (i = 1; i < c->numSlice-2; ++i) {
-        res = alloc_slice(&c->slice[i], c->srcFormat, lumBufSize, chrBufSize, c->chrSrcHSubSample, c->chrSrcVSubSample, 0);
+        res = alloc_slice(&c->slice[i], c->sws->src_format, lumBufSize, chrBufSize, c->chrSrcHSubSample, c->chrSrcVSubSample, 0);
         if (res < 0) goto cleanup;
-        res = alloc_lines(&c->slice[i], FFALIGN(c->srcW*2+78, 16), c->srcW);
+        res = alloc_lines(&c->slice[i], FFALIGN(c->sws->src_w*2+78, 16), c->sws->src_w);
         if (res < 0) goto cleanup;
     }
     // horizontal scaler output
-    res = alloc_slice(&c->slice[i], c->srcFormat, lumBufSize, chrBufSize, c->chrDstHSubSample, c->chrDstVSubSample, 1);
+    res = alloc_slice(&c->slice[i], c->sws->src_format, lumBufSize, chrBufSize, c->chrDstHSubSample, c->chrDstVSubSample, 1);
     if (res < 0) goto cleanup;
-    res = alloc_lines(&c->slice[i], dst_stride, c->dstW);
+    res = alloc_lines(&c->slice[i], dst_stride, c->sws->dst_w);
     if (res < 0) goto cleanup;
 
     fill_ones(&c->slice[i], dst_stride>>1, c->dstBpc);
 
     // vertical scaler output
     ++i;
-    res = alloc_slice(&c->slice[i], c->dstFormat, c->dstH, c->chrDstH, c->chrDstHSubSample, c->chrDstVSubSample, 0);
+    res = alloc_slice(&c->slice[i], c->sws->dst_format, c->sws->dst_h, c->chrDstH, c->chrDstHSubSample, c->chrDstVSubSample, 0);
     if (res < 0) goto cleanup;
 
     index = 0;
diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index e0a9e0279f..bb4faaa708 100644
--- a/libswscale/swscale.c
+++ b/libswscale/swscale.c
@@ -66,14 +66,14 @@  static void hScale16To19_c(SwsInternal *c, int16_t *_dst, int dstW,
                            const uint8_t *_src, const int16_t *filter,
                            const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int i;
     int32_t *dst        = (int32_t *) _dst;
     const uint16_t *src = (const uint16_t *) _src;
     int bits            = desc->comp[0].depth - 1;
     int sh              = bits - 4;
 
-    if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
+    if ((isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
         sh = 9;
     } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
         sh = 16 - 1 - 4;
@@ -96,13 +96,13 @@  static void hScale16To15_c(SwsInternal *c, int16_t *dst, int dstW,
                            const uint8_t *_src, const int16_t *filter,
                            const int32_t *filterPos, int filterSize)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
     int i;
     const uint16_t *src = (const uint16_t *) _src;
     int sh              = desc->comp[0].depth - 1;
 
     if (sh<15) {
-        sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
+        sh = isAnyRGB(c->sws->src_format) || c->sws->src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
     } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
         sh = 16 - 1;
     }
@@ -231,21 +231,21 @@  static void lumRangeFromJpeg16_c(int16_t *_dst, int width)
 #define DEBUG_SWSCALE_BUFFERS 0
 #define DEBUG_BUFFERS(...)                      \
     if (DEBUG_SWSCALE_BUFFERS)                  \
-        av_log(c, AV_LOG_DEBUG, __VA_ARGS__)
+        av_log(c->sws, AV_LOG_DEBUG, __VA_ARGS__)
 
 int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
                int srcSliceY, int srcSliceH, uint8_t *const dst[],
                const int dstStride[], int dstSliceY, int dstSliceH)
 {
-    const int scale_dst = dstSliceY > 0 || dstSliceH < c->dstH;
+    const int scale_dst = dstSliceY > 0 || dstSliceH < c->sws->dst_h;
 
     /* load a few things into local vars to make the code more readable?
      * and faster */
-    const int dstW                   = c->dstW;
-    int dstH                         = c->dstH;
+    const int dstW                   = c->sws->dst_w;
+    int dstH                         = c->sws->dst_h;
 
-    const enum AVPixelFormat dstFormat = c->dstFormat;
-    const int flags                  = c->flags;
+    const enum AVPixelFormat dstFormat = c->sws->dst_format;
+    const int flags                  = c->sws->flags;
     int32_t *vLumFilterPos           = c->vLumFilterPos;
     int32_t *vChrFilterPos           = c->vChrFilterPos;
 
@@ -261,8 +261,8 @@  int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[]
     yuv2anyX_fn yuv2anyX             = c->yuv2anyX;
     const int chrSrcSliceY           =                srcSliceY >> c->chrSrcVSubSample;
     const int chrSrcSliceH           = AV_CEIL_RSHIFT(srcSliceH,   c->chrSrcVSubSample);
-    int should_dither                = isNBPS(c->srcFormat) ||
-                                       is16BPS(c->srcFormat);
+    int should_dither                = isNBPS(c->sws->src_format) ||
+                                       is16BPS(c->sws->src_format);
     int lastDstY;
 
     /* vars which will change and which we need to store back in the context */
@@ -289,7 +289,7 @@  int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[]
     const uint8_t *src2[4];
     int srcStride2[4];
 
-    if (isPacked(c->srcFormat)) {
+    if (isPacked(c->sws->src_format)) {
         src2[0] =
         src2[1] =
         src2[2] =
@@ -321,7 +321,7 @@  int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[]
         SwsInternal *const ctx = c->parent ? sws_internal(c->parent) : c;
         if (flags & SWS_PRINT_INFO &&
             !atomic_exchange_explicit(&ctx->stride_unaligned_warned, 1, memory_order_relaxed)) {
-            av_log(c, AV_LOG_WARNING,
+            av_log(c->sws, AV_LOG_WARNING,
                    "Warning: dstStride is not aligned!\n"
                    "         ->cannot do aligned memory accesses anymore\n");
         }
@@ -337,7 +337,7 @@  int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[]
         int cpu_flags = av_get_cpu_flags();
         if (flags & SWS_PRINT_INFO && HAVE_MMXEXT && (cpu_flags & AV_CPU_FLAG_SSE2) &&
             !atomic_exchange_explicit(&ctx->stride_unaligned_warned,1, memory_order_relaxed)) {
-            av_log(c, AV_LOG_WARNING, "Warning: data is not aligned! This can lead to a speed loss\n");
+            av_log(c->sws, AV_LOG_WARNING, "Warning: data is not aligned! This can lead to a speed loss\n");
         }
     }
 #endif
@@ -364,10 +364,10 @@  int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[]
     ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
                    yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, c->use_mmx_vfilter);
 
-    ff_init_slice_from_src(src_slice, (uint8_t**)src2, srcStride2, c->srcW,
+    ff_init_slice_from_src(src_slice, (uint8_t**)src2, srcStride2, c->sws->src_w,
             srcSliceY, srcSliceH, chrSrcSliceY, chrSrcSliceH, 1);
 
-    ff_init_slice_from_src(vout_slice, (uint8_t**)dst, dstStride, c->dstW,
+    ff_init_slice_from_src(vout_slice, (uint8_t**)dst, dstStride, c->sws->dst_w,
             dstY, dstSliceH, dstY >> c->chrDstVSubSample,
             AV_CEIL_RSHIFT(dstSliceH, c->chrDstVSubSample), scale_dst);
     if (srcSliceY == 0) {
@@ -389,13 +389,13 @@  int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[]
 
         // First line needed as input
         const int firstLumSrcY  = FFMAX(1 - vLumFilterSize, vLumFilterPos[dstY]);
-        const int firstLumSrcY2 = FFMAX(1 - vLumFilterSize, vLumFilterPos[FFMIN(dstY | ((1 << c->chrDstVSubSample) - 1), c->dstH - 1)]);
+        const int firstLumSrcY2 = FFMAX(1 - vLumFilterSize, vLumFilterPos[FFMIN(dstY | ((1 << c->chrDstVSubSample) - 1), c->sws->dst_h - 1)]);
         // First line needed as input
         const int firstChrSrcY  = FFMAX(1 - vChrFilterSize, vChrFilterPos[chrDstY]);
 
         // Last line needed as input
-        int lastLumSrcY  = FFMIN(c->srcH,    firstLumSrcY  + vLumFilterSize) - 1;
-        int lastLumSrcY2 = FFMIN(c->srcH,    firstLumSrcY2 + vLumFilterSize) - 1;
+        int lastLumSrcY  = FFMIN(c->sws->src_h,    firstLumSrcY  + vLumFilterSize) - 1;
+        int lastLumSrcY2 = FFMIN(c->sws->src_h,    firstLumSrcY2 + vLumFilterSize) - 1;
         int lastChrSrcY  = FFMIN(c->chrSrcH, firstChrSrcY  + vChrFilterSize) - 1;
         int enough_lines;
 
@@ -488,13 +488,13 @@  int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[]
 
 #if HAVE_MMX_INLINE
         ff_updateMMXDitherTables(c, dstY);
-        c->dstW_mmx = c->dstW;
+        c->dstW_mmx = c->sws->dst_w;
 #endif
         if (should_dither) {
             c->chrDither8 = ff_dither_8x8_128[chrDstY & 7];
             c->lumDither8 = ff_dither_8x8_128[dstY    & 7];
         }
-        if (dstY >= c->dstH - 2) {
+        if (dstY >= c->sws->dst_h - 2) {
             /* hmm looks like we can't use MMX here without overwriting
              * this array's tail */
             ff_sws_init_output_funcs(c, &yuv2plane1, &yuv2planeX, &yuv2nv12cX,
@@ -544,9 +544,9 @@  av_cold void ff_sws_init_range_convert(SwsInternal *c)
 {
     c->lumConvertRange = NULL;
     c->chrConvertRange = NULL;
-    if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
+    if (c->sws->src_range != c->sws->dst_range && !isAnyRGB(c->sws->dst_format)) {
         if (c->dstBpc <= 14) {
-            if (c->srcRange) {
+            if (c->sws->src_range) {
                 c->lumConvertRange = lumRangeFromJpeg_c;
                 c->chrConvertRange = chrRangeFromJpeg_c;
             } else {
@@ -554,7 +554,7 @@  av_cold void ff_sws_init_range_convert(SwsInternal *c)
                 c->chrConvertRange = chrRangeToJpeg_c;
             }
         } else {
-            if (c->srcRange) {
+            if (c->sws->src_range) {
                 c->lumConvertRange = lumRangeFromJpeg16_c;
                 c->chrConvertRange = chrRangeFromJpeg16_c;
             } else {
@@ -567,7 +567,7 @@  av_cold void ff_sws_init_range_convert(SwsInternal *c)
 
 static av_cold void sws_init_swscale(SwsInternal *c)
 {
-    enum AVPixelFormat srcFormat = c->srcFormat;
+    enum AVPixelFormat srcFormat = c->sws->src_format;
 
     ff_sws_init_output_funcs(c, &c->yuv2plane1, &c->yuv2planeX,
                              &c->yuv2nv12cX, &c->yuv2packed1,
@@ -579,7 +579,7 @@  static av_cold void sws_init_swscale(SwsInternal *c)
     if (c->srcBpc == 8) {
         if (c->dstBpc <= 14) {
             c->hyScale = c->hcScale = hScale8To15_c;
-            if (c->flags & SWS_FAST_BILINEAR) {
+            if (c->sws->flags & SWS_FAST_BILINEAR) {
                 c->hyscale_fast = ff_hyscale_fast_c;
                 c->hcscale_fast = ff_hcscale_fast_c;
             }
@@ -593,7 +593,7 @@  static av_cold void sws_init_swscale(SwsInternal *c)
 
     ff_sws_init_range_convert(c);
 
-    if (!(isGray(srcFormat) || isGray(c->dstFormat) ||
+    if (!(isGray(srcFormat) || isGray(c->sws->dst_format) ||
           srcFormat == AV_PIX_FMT_MONOBLACK || srcFormat == AV_PIX_FMT_MONOWHITE))
         c->needs_hcscale = 1;
 }
@@ -649,7 +649,7 @@  static int check_image_pointers(const uint8_t * const data[4], enum AVPixelForma
 void ff_xyz12Torgb48(const SwsInternal *c, uint8_t *dst, int dst_stride,
                      const uint8_t *src, int src_stride, int w, int h)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->src_format);
 
     for (int yp = 0; yp < h; yp++) {
         const uint16_t *src16 = (const uint16_t *) src;
@@ -708,7 +708,7 @@  void ff_xyz12Torgb48(const SwsInternal *c, uint8_t *dst, int dst_stride,
 void ff_rgb48Toxyz12(const SwsInternal *c, uint8_t *dst, int dst_stride,
                      const uint8_t *src, int src_stride, int w, int h)
 {
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->sws->dst_format);
 
     for (int yp = 0; yp < h; yp++) {
         uint16_t *src16 = (uint16_t *) src;
@@ -768,28 +768,28 @@  void ff_update_palette(SwsInternal *c, const uint32_t *pal)
 {
     for (int i = 0; i < 256; i++) {
         int r, g, b, y, u, v, a = 0xff;
-        if (c->srcFormat == AV_PIX_FMT_PAL8) {
+        if (c->sws->src_format == AV_PIX_FMT_PAL8) {
             uint32_t p = pal[i];
             a = (p >> 24) & 0xFF;
             r = (p >> 16) & 0xFF;
             g = (p >>  8) & 0xFF;
             b =  p        & 0xFF;
-        } else if (c->srcFormat == AV_PIX_FMT_RGB8) {
+        } else if (c->sws->src_format == AV_PIX_FMT_RGB8) {
             r = ( i >> 5     ) * 36;
             g = ((i >> 2) & 7) * 36;
             b = ( i       & 3) * 85;
-        } else if (c->srcFormat == AV_PIX_FMT_BGR8) {
+        } else if (c->sws->src_format == AV_PIX_FMT_BGR8) {
             b = ( i >> 6     ) * 85;
             g = ((i >> 3) & 7) * 36;
             r = ( i       & 7) * 36;
-        } else if (c->srcFormat == AV_PIX_FMT_RGB4_BYTE) {
+        } else if (c->sws->src_format == AV_PIX_FMT_RGB4_BYTE) {
             r = ( i >> 3     ) * 255;
             g = ((i >> 1) & 3) * 85;
             b = ( i       & 1) * 255;
-        } else if (c->srcFormat == AV_PIX_FMT_GRAY8 || c->srcFormat == AV_PIX_FMT_GRAY8A) {
+        } else if (c->sws->src_format == AV_PIX_FMT_GRAY8 || c->sws->src_format == AV_PIX_FMT_GRAY8A) {
             r = g = b = i;
         } else {
-            av_assert1(c->srcFormat == AV_PIX_FMT_BGR4_BYTE);
+            av_assert1(c->sws->src_format == AV_PIX_FMT_BGR4_BYTE);
             b = ( i >> 3     ) * 255;
             g = ((i >> 1) & 3) * 85;
             r = ( i       & 1) * 255;
@@ -810,7 +810,7 @@  void ff_update_palette(SwsInternal *c, const uint32_t *pal)
         v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
         c->pal_yuv[i]= y + (u<<8) + (v<<16) + ((unsigned)a<<24);
 
-        switch (c->dstFormat) {
+        switch (c->sws->dst_format) {
         case AV_PIX_FMT_BGR32:
 #if !HAVE_BIGENDIAN
         case AV_PIX_FMT_RGB24:
@@ -853,7 +853,7 @@  static int scale_gamma(SwsInternal *c,
 {
     int ret = scale_internal(c->cascaded_context[0],
                              srcSlice, srcStride, srcSliceY, srcSliceH,
-                             c->cascaded_tmp[0], c->cascaded_tmpStride[0], 0, c->srcH);
+                             c->cascaded_tmp[0], c->cascaded_tmpStride[0], 0, c->sws->src_h);
 
     if (ret < 0)
         return ret;
@@ -861,7 +861,7 @@  static int scale_gamma(SwsInternal *c,
     if (c->cascaded_context[2])
         ret = scale_internal(c->cascaded_context[1], (const uint8_t * const *)c->cascaded_tmp[0],
                              c->cascaded_tmpStride[0], srcSliceY, srcSliceH,
-                             c->cascaded_tmp[1], c->cascaded_tmpStride[1], 0, c->dstH);
+                             c->cascaded_tmp[1], c->cascaded_tmpStride[1], 0, c->sws->dst_h);
     else
         ret = scale_internal(c->cascaded_context[1], (const uint8_t * const *)c->cascaded_tmp[0],
                              c->cascaded_tmpStride[0], srcSliceY, srcSliceH,
@@ -885,7 +885,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])->dstH;
+    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],
@@ -905,44 +905,44 @@  static int scale_internal(SwsContext *sws,
                           int dstSliceY, int dstSliceH)
 {
     SwsInternal *c = sws_internal(sws);
-    const int scale_dst = dstSliceY > 0 || dstSliceH < c->dstH;
+    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->srcFormat) ? 2 : (1 << c->chrSrcVSubSample);
-    int macro_height_dst = isBayer(c->dstFormat) ? 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];
     int srcSliceY_internal = srcSliceY;
 
     if (!srcStride || !dstStride || !dstSlice || !srcSlice) {
-        av_log(c, AV_LOG_ERROR, "One of the input parameters to sws_scale() is NULL, please check the calling code\n");
+        av_log(sws, AV_LOG_ERROR, "One of the input parameters to sws_scale() is NULL, please check the calling code\n");
         return AVERROR(EINVAL);
     }
 
     if ((srcSliceY  & (macro_height_src - 1)) ||
-        ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != c->srcH) ||
-        srcSliceY + srcSliceH > c->srcH ||
-        (isBayer(c->srcFormat) && srcSliceH <= 1)) {
-        av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", srcSliceY, srcSliceH);
+        ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != sws->src_h) ||
+        srcSliceY + srcSliceH > sws->src_h ||
+        (isBayer(sws->src_format) && srcSliceH <= 1)) {
+        av_log(sws, 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->dstH) ||
-        dstSliceY + dstSliceH > c->dstH) {
-        av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", dstSliceY, dstSliceH);
+        ((dstSliceH & (macro_height_dst - 1)) && dstSliceY + dstSliceH != sws->dst_h) ||
+        dstSliceY + dstSliceH > sws->dst_h) {
+        av_log(sws, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", dstSliceY, dstSliceH);
         return AVERROR(EINVAL);
     }
 
-    if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) {
-        av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
+    if (!check_image_pointers(srcSlice, sws->src_format, srcStride)) {
+        av_log(sws, AV_LOG_ERROR, "bad src image pointers\n");
         return AVERROR(EINVAL);
     }
-    if (!check_image_pointers((const uint8_t* const*)dstSlice, c->dstFormat, dstStride)) {
-        av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
+    if (!check_image_pointers((const uint8_t* const*)dstSlice, sws->dst_format, dstStride)) {
+        av_log(sws, AV_LOG_ERROR, "bad dst image pointers\n");
         return AVERROR(EINVAL);
     }
 
@@ -950,22 +950,19 @@  static int scale_internal(SwsContext *sws,
     if (srcSliceH == 0)
         return 0;
 
-    if (c->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])->srcH)
-    {
+    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->flags & SWS_BITEXACT) && c->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->dstW+2));
+            memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (sws->dst_w+2));
 
-    if (usePal(c->srcFormat))
+    if (usePal(sws->src_format))
         ff_update_palette(c, (const uint32_t *)srcSlice[1]);
 
     memcpy(src2,       srcSlice,  sizeof(src2));
@@ -974,8 +971,8 @@  static int scale_internal(SwsContext *sws,
     memcpy(dstStride2, dstStride, sizeof(dstStride2));
 
     if (frame_start && !scale_dst) {
-        if (srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
-            av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
+        if (srcSliceY != 0 && srcSliceY + srcSliceH != sws->src_h) {
+            av_log(sws, AV_LOG_ERROR, "Slices start in the middle!\n");
             return AVERROR(EINVAL);
         }
 
@@ -983,7 +980,7 @@  static int scale_internal(SwsContext *sws,
     } else if (scale_dst)
         c->sliceDir = 1;
 
-    if (c->src0Alpha && !c->dst0Alpha && isALPHA(c->dstFormat)) {
+    if (c->src0Alpha && !c->dst0Alpha && isALPHA(sws->dst_format)) {
         uint8_t *base;
         int x,y;
 
@@ -995,15 +992,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->srcW);
-            for (x=c->src0Alpha-1; x<4*c->srcW; 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->srcW==c->dstW && c->srcH==c->dstH)) {
+    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,
@@ -1014,7 +1011,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->srcW, srcSliceH);
+        ff_xyz12Torgb48(c, base, srcStride[0], src2[0], srcStride[0], sws->src_w, srcSliceH);
         src2[0] = base;
     }
 
@@ -1026,19 +1023,19 @@  static int scale_internal(SwsContext *sws,
         }
 
         src2[0] += (srcSliceH - 1) * srcStride[0];
-        if (!usePal(c->srcFormat))
+        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->dstH                         - 1) * dstStride[0];
-        dst2[1] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[1];
-        dst2[2] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[2];
-        dst2[3] += ( c->dstH                         - 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->srcH-srcSliceY-srcSliceH;
+        srcSliceY_internal = sws->src_h-srcSliceY-srcSliceH;
     }
-    reset_ptr(src2, c->srcFormat);
-    reset_ptr((void*)dst2, c->dstFormat);
+    reset_ptr(src2, sws->src_format);
+    reset_ptr((void*)dst2, sws->dst_format);
 
     if (c->convert_unscaled) {
         int offset  = srcSliceY_internal;
@@ -1048,13 +1045,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->srcFormat)))
+                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->dstFormat)))
+                if (!dst2[i] || (i > 0 && usePal(sws->dst_format)))
                     break;
                 dst2[i] -= (dstSliceY >> ((i == 1 || i == 2) ? c->chrDstVSubSample : 0)) * dstStride2[i];
             }
@@ -1071,7 +1068,7 @@  static int scale_internal(SwsContext *sws,
                          dst2, dstStride2, dstSliceY, dstSliceH);
     }
 
-    if (c->dstXYZ && !(c->srcXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) {
+    if (c->dstXYZ && !(c->srcXYZ && sws->src_w==sws->dst_w && sws->src_h==sws->dst_h)) {
         uint8_t *dst;
 
         if (scale_dst) {
@@ -1081,16 +1078,16 @@  static int scale_internal(SwsContext *sws,
 
             av_assert0(dstY >= ret);
             av_assert0(ret >= 0);
-            av_assert0(c->dstH >= 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->dstW, 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->srcH) || scale_dst)
+    if ((srcSliceY_internal + srcSliceH == sws->src_h) || scale_dst)
         c->sliceDir = 0;
 
     return ret;
@@ -1114,9 +1111,9 @@  int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src)
         return ret;
 
     if (!dst->buf[0]) {
-        dst->width  = c->dstW;
-        dst->height = c->dstH;
-        dst->format = c->dstFormat;
+        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)
@@ -1167,12 +1164,12 @@  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->srcH))
+          c->src_ranges.ranges[0].len == sws->src_h))
         return AVERROR(EAGAIN);
 
-    if ((slice_start > 0 || slice_height < c->dstH) &&
+    if ((slice_start > 0 || slice_height < sws->dst_h) &&
         (slice_start % align || slice_height % align)) {
-        av_log(c, AV_LOG_ERROR,
+        av_log(sws, AV_LOG_ERROR,
                "Incorrectly aligned output: %u/%u not multiples of %u\n",
                slice_start, slice_height, align);
         return AVERROR(EINVAL);
@@ -1182,7 +1179,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])->dither == SWS_DITHER_ED)
+        if (c->slice_ctx[0]->dither == SWS_DITHER_ED)
             nb_jobs = 1;
 
         c->dst_slice_start  = slice_start;
@@ -1208,7 +1205,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->srcH,
+                          c->frame_src->linesize, 0, sws->src_h,
                           dst, c->frame_dst->linesize, slice_start, slice_height);
 }
 
@@ -1246,13 +1243,13 @@  int attribute_align_arg sws_scale(SwsContext *sws,
     }
 
     return scale_internal(sws, srcSlice, srcStride, srcSliceY, srcSliceH,
-                          dst, dstStride, 0, c->dstH);
+                          dst, dstStride, 0, sws->dst_h);
 }
 
 void ff_sws_slice_worker(void *priv, int jobnr, int threadnr,
                          int nb_jobs, int nb_threads)
 {
-    SwsInternal *parent = priv;
+    SwsInternal *parent = sws_internal(priv);
     SwsContext     *sws = parent->slice_ctx[threadnr];
     SwsInternal      *c = sws_internal(sws);
 
@@ -1274,7 +1271,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->srcH,
+                             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/swscale.h b/libswscale/swscale.h
index f544387769..0718469a73 100644
--- a/libswscale/swscale.h
+++ b/libswscale/swscale.h
@@ -42,8 +42,6 @@ 
 #include "version.h"
 #endif
 
-typedef struct SwsContext SwsContext;
-
 /**
  * @defgroup libsws libswscale
  * Color conversion and scaling library.
@@ -65,17 +63,103 @@  const char *swscale_configuration(void);
 const char *swscale_license(void);
 
 /**
- * Get the AVClass for swsContext. It can be used in combination with
+ * Get the AVClass for SwsContext. It can be used in combination with
  * AV_OPT_SEARCH_FAKE_OBJ for examining options.
  *
  * @see av_opt_find().
  */
 const AVClass *sws_get_class(void);
 
-/**
- * Allocate an empty SwsContext. This must be filled and passed to
- * sws_init_context(). For filling see AVOptions, options.c and
- * sws_setColorspaceDetails().
+/******************************
+ * Flags and quality settings *
+ ******************************/
+
+typedef enum SwsDither {
+    SWS_DITHER_NONE = 0, /* disable dithering */
+    SWS_DITHER_AUTO,     /* auto-select from preset */
+    SWS_DITHER_BAYER,    /* ordered dither matrix */
+    SWS_DITHER_ED,       /* error diffusion */
+    SWS_DITHER_A_DITHER, /* arithmetic addition */
+    SWS_DITHER_X_DITHER, /* arithmetic xor */
+    SWS_DITHER_NB,       /* not part of the ABI */
+} SwsDither;
+
+typedef enum SwsAlphaBlend {
+    SWS_ALPHA_BLEND_NONE = 0,
+    SWS_ALPHA_BLEND_UNIFORM,
+    SWS_ALPHA_BLEND_CHECKERBOARD,
+    SWS_ALPHA_BLEND_NB,  /* not part of the ABI */
+} SwsAlphaBlend;
+
+/***********************************
+ * Context creation and management *
+ ***********************************/
+
+/**
+ * Main external API structure. New fields can be added to the end with
+ * minor version bumps. Removal, reordering and changes to existing fields
+ * require a major version bump. sizeof(SwsContext) is not part of the ABI.
+ */
+typedef struct SwsContext {
+    const AVClass *av_class;
+
+    /**
+     * Private context used for internal data.
+     */
+    struct SwsInternal *internal;
+
+    /**
+     * Private data of the user, can be used to carry app specific stuff.
+     */
+    void *opaque;
+
+    /**
+     * Bitmask of SWS_*.
+     */
+    unsigned flags;
+
+    /**
+     * Extra parameters for fine-tuning certain scalers.
+     */
+    double scaler_params[2];
+
+    /**
+     * How many threads to use for processing, or 0 for automatic selection.
+     */
+    int threads;
+
+    /**
+     * Dither mode.
+     */
+    SwsDither dither;
+
+    /**
+     * Alpha blending mode. See `SwsAlphaBlend` for details.
+     */
+    SwsAlphaBlend alpha_blend;
+
+    /**
+     * Use gamma correct scaling.
+     */
+    int gamma_flag;
+
+    /**
+     * Frame property overrides.
+     */
+    int src_w, src_h;  ///< Width and height of the source frame
+    int dst_w, dst_h;  ///< Width and height of the destination frame
+    int src_format;    ///< Source pixel format
+    int dst_format;    ///< Destination pixel format
+    int src_range;     ///< Source is full range
+    int dst_range;     ///< Destination is full range
+    int src_v_chr_pos; ///< Source vertical chroma position in luma grid / 256
+    int src_h_chr_pos; ///< Source horizontal chroma position
+    int dst_v_chr_pos; ///< Destination vertical chroma position
+    int dst_h_chr_pos; ///< Destination horizontal chroma position
+} SwsContext;
+
+/**
+ * Allocate an empty SwsContext and set its fields to default values.
  */
 SwsContext *sws_alloc_context(void);
 
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 6b85ecadae..1f95966bd1 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -70,26 +70,9 @@  typedef struct SwsInternal SwsInternal;
 
 static inline SwsInternal *sws_internal(const SwsContext *sws)
 {
-    return (SwsInternal *) sws;
+    return sws ? sws->internal : NULL;
 }
 
-typedef enum SwsDither {
-    SWS_DITHER_NONE = 0,
-    SWS_DITHER_AUTO,
-    SWS_DITHER_BAYER,
-    SWS_DITHER_ED,
-    SWS_DITHER_A_DITHER,
-    SWS_DITHER_X_DITHER,
-    SWS_DITHER_NB,
-} SwsDither;
-
-typedef enum SwsAlphaBlend {
-    SWS_ALPHA_BLEND_NONE  = 0,
-    SWS_ALPHA_BLEND_UNIFORM,
-    SWS_ALPHA_BLEND_CHECKERBOARD,
-    SWS_ALPHA_BLEND_NB,
-} SwsAlphaBlend;
-
 typedef struct Range {
     unsigned int start;
     unsigned int len;
@@ -329,11 +312,10 @@  struct SwsFilterDescriptor;
 
 /* This struct should be aligned on at least a 32-byte boundary. */
 struct SwsInternal {
-    /**
-     * info on struct for av_log
-     */
-    const AVClass *av_class;
+    /* Associated context/options, for convenience use by leaf functions */
+    SwsContext *sws;
 
+    /* Parent context (for slice contexts) */
     SwsContext *parent;
 
     AVSliceThread      *slicethread;
@@ -350,18 +332,12 @@  struct SwsInternal {
      * sws_scale() wrapper so they can be freely modified here.
      */
     SwsFunc convert_unscaled;
-    int srcW;                     ///< Width  of source      luma/alpha planes.
-    int srcH;                     ///< Height of source      luma/alpha planes.
-    int dstW;                     ///< Width  of destination luma/alpha planes.
-    int dstH;                     ///< Height of destination luma/alpha planes.
     int chrSrcW;                  ///< Width  of source      chroma     planes.
     int chrSrcH;                  ///< Height of source      chroma     planes.
     int chrDstW;                  ///< Width  of destination chroma     planes.
     int chrDstH;                  ///< Height of destination chroma     planes.
     int lumXInc, chrXInc;
     int lumYInc, chrYInc;
-    enum AVPixelFormat dstFormat; ///< Destination pixel format.
-    enum AVPixelFormat srcFormat; ///< Source      pixel format.
     int dstFormatBpp;             ///< Number of bits per pixel of the destination pixel format.
     int srcFormatBpp;             ///< Number of bits per pixel of the source      pixel format.
     int dstBpc, srcBpc;
@@ -371,8 +347,6 @@  struct SwsInternal {
     int chrDstVSubSample;         ///< Binary logarithm of vertical   subsampling factor between luma/alpha and chroma planes in destination image.
     int vChrDrop;                 ///< Binary logarithm of extra vertical subsampling factor in source image chroma planes specified by user.
     int sliceDir;                 ///< Direction that slices are fed to the scaler (1 = top-to-bottom, -1 = bottom-to-top).
-    int nb_threads;               ///< Number of threads used for scaling
-    double param[2];              ///< Input parameters for scaling algorithms that need them.
 
     AVFrame *frame_src;
     AVFrame *frame_dst;
@@ -389,7 +363,6 @@  struct SwsInternal {
     int cascaded_mainindex;
 
     double gamma_value;
-    int gamma_flag;
     int is_internal_gamma;
     uint16_t *gamma;
     uint16_t *inv_gamma;
@@ -459,7 +432,6 @@  struct SwsInternal {
     int warned_unuseable_bilinear;
 
     int dstY;                     ///< Last destination vertical line output from last slice.
-    int flags;                    ///< Flags passed by the user to select scaler algorithm, optimizations, subsampling, etc...
     void *yuvTable;             // pointer to the yuv->rgb table start so it can be freed()
     // alignment ensures the offset can be added in a single
     // instruction on e.g. ARM
@@ -485,16 +457,10 @@  struct SwsInternal {
     int contrast, brightness, saturation;    // for sws_getColorspaceDetails
     int srcColorspaceTable[4];
     int dstColorspaceTable[4];
-    int srcRange;                 ///< 0 = MPG YUV range, 1 = JPG YUV range (source      image).
-    int dstRange;                 ///< 0 = MPG YUV range, 1 = JPG YUV range (destination image).
     int src0Alpha;
     int dst0Alpha;
     int srcXYZ;
     int dstXYZ;
-    int src_h_chr_pos;
-    int dst_h_chr_pos;
-    int src_v_chr_pos;
-    int dst_v_chr_pos;
     int yuv2rgb_y_offset;
     int yuv2rgb_y_coeff;
     int yuv2rgb_v2r_coeff;
@@ -682,10 +648,6 @@  struct SwsInternal {
 
     int needs_hcscale; ///< Set if there are chroma planes to be converted.
 
-    SwsDither dither;
-
-    SwsAlphaBlend alphablend;
-
     // scratch buffer for converting packed rgb0 sources
     // filled with a copy of the input frame + fully opaque alpha,
     // then passed as input to further conversion
@@ -712,7 +674,7 @@  static_assert(offsetof(SwsInternal, redDither) + DITHER32_INT == offsetof(SwsInt
 #if ARCH_X86_64
 /* x86 yuv2gbrp uses the SwsInternal for yuv coefficients
    if struct offsets change the asm needs to be updated too */
-static_assert(offsetof(SwsInternal, yuv2rgb_y_offset) == 40292,
+static_assert(offsetof(SwsInternal, yuv2rgb_y_offset) == 40332,
               "yuv2rgb_y_offset must be updated in x86 asm");
 #endif
 
diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
index 1a293483c4..ca3f9476c4 100644
--- a/libswscale/swscale_unscaled.c
+++ b/libswscale/swscale_unscaled.c
@@ -146,10 +146,10 @@  static int planarToNv12Wrapper(SwsInternal *c, const uint8_t *const src[],
 {
     uint8_t *dst = dstParam[1] + dstStride[1] * srcSliceY / 2;
 
-    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
+    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->sws->src_w,
                  dstParam[0], dstStride[0]);
 
-    if (c->dstFormat == AV_PIX_FMT_NV12)
+    if (c->sws->dst_format == AV_PIX_FMT_NV12)
         interleaveBytes(src[1], src[2], dst, c->chrSrcW, (srcSliceH + 1) / 2,
                         srcStride[1], srcStride[2], dstStride[1]);
     else
@@ -167,10 +167,10 @@  static int nv12ToPlanarWrapper(SwsInternal *c, const uint8_t *const src[],
     uint8_t *dst1 = dstParam[1] + dstStride[1] * srcSliceY / 2;
     uint8_t *dst2 = dstParam[2] + dstStride[2] * srcSliceY / 2;
 
-    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
+    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->sws->src_w,
                  dstParam[0], dstStride[0]);
 
-    if (c->srcFormat == AV_PIX_FMT_NV12)
+    if (c->sws->src_format == AV_PIX_FMT_NV12)
         deinterleaveBytes(src[1], dst1, dst2, c->chrSrcW, (srcSliceH + 1) / 2,
                           srcStride[1], dstStride[1], dstStride[2]);
     else
@@ -187,10 +187,10 @@  static int planarToNv24Wrapper(SwsInternal *c, const uint8_t *const src[],
 {
     uint8_t *dst = dstParam[1] + dstStride[1] * srcSliceY;
 
-    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
+    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->sws->src_w,
                  dstParam[0], dstStride[0]);
 
-    if (c->dstFormat == AV_PIX_FMT_NV24)
+    if (c->sws->dst_format == AV_PIX_FMT_NV24)
         interleaveBytes(src[1], src[2], dst, c->chrSrcW, srcSliceH,
                         srcStride[1], srcStride[2], dstStride[1]);
     else
@@ -208,10 +208,10 @@  static int nv24ToPlanarWrapper(SwsInternal *c, const uint8_t *const src[],
     uint8_t *dst1 = dstParam[1] + dstStride[1] * srcSliceY;
     uint8_t *dst2 = dstParam[2] + dstStride[2] * srcSliceY;
 
-    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
+    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->sws->src_w,
                  dstParam[0], dstStride[0]);
 
-    if (c->srcFormat == AV_PIX_FMT_NV24)
+    if (c->sws->src_format == AV_PIX_FMT_NV24)
         deinterleaveBytes(src[1], dst1, dst2, c->chrSrcW, srcSliceH,
                           srcStride[1], dstStride[1], dstStride[2]);
     else
@@ -250,15 +250,15 @@  static int nv24ToYuv420Wrapper(SwsInternal *c, const uint8_t *const src[],
     uint8_t *dst1 = dstParam[1] + dstStride[1] * srcSliceY / 2;
     uint8_t *dst2 = dstParam[2] + dstStride[2] * srcSliceY / 2;
 
-    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
+    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->sws->src_w,
                  dstParam[0], dstStride[0]);
 
-    if (c->srcFormat == AV_PIX_FMT_NV24)
+    if (c->sws->src_format == AV_PIX_FMT_NV24)
         nv24_to_yuv420p_chroma(dst1, dstStride[1], dst2, dstStride[2],
-                               src[1], srcStride[1], c->srcW / 2, srcSliceH);
+                               src[1], srcStride[1], c->sws->src_w / 2, srcSliceH);
     else
         nv24_to_yuv420p_chroma(dst2, dstStride[2], dst1, dstStride[1],
-                               src[1], srcStride[1], c->srcW / 2, srcSliceH);
+                               src[1], srcStride[1], c->sws->src_w / 2, srcSliceH);
 
     return srcSliceH;
 }
@@ -268,8 +268,8 @@  static int planarToP01xWrapper(SwsInternal *c, const uint8_t *const src8[],
                                int srcSliceH, uint8_t *const dstParam8[],
                                const int dstStride[])
 {
-    const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat);
-    const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat);
+    const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->sws->src_format);
+    const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->sws->dst_format);
     const uint16_t **src = (const uint16_t**)src8;
     uint16_t *dstY = (uint16_t*)(dstParam8[0] + dstStride[0] * srcSliceY);
     uint16_t *dstUV = (uint16_t*)(dstParam8[1] + dstStride[1] * srcSliceY / 2);
@@ -291,7 +291,7 @@  static int planarToP01xWrapper(SwsInternal *c, const uint8_t *const src8[],
     for (y = 0; y < srcSliceH; y++) {
         uint16_t *tdstY = dstY;
         const uint16_t *tsrc0 = src[0];
-        for (x = c->srcW; x > 0; x--) {
+        for (x = c->sws->src_w; x > 0; x--) {
             *tdstY++ = *tsrc0++ << shift[0];
         }
         src[0] += srcStride[0] / 2;
@@ -301,7 +301,7 @@  static int planarToP01xWrapper(SwsInternal *c, const uint8_t *const src8[],
             uint16_t *tdstUV = dstUV;
             const uint16_t *tsrc1 = src[1];
             const uint16_t *tsrc2 = src[2];
-            for (x = c->srcW / 2; x > 0; x--) {
+            for (x = c->sws->src_w / 2; x > 0; x--) {
                 *tdstUV++ = *tsrc1++ << shift[1];
                 *tdstUV++ = *tsrc2++ << shift[2];
             }
@@ -338,7 +338,7 @@  static int planar8ToP01xleWrapper(SwsInternal *c, const uint8_t *const src[],
     for (y = 0; y < srcSliceH; y++) {
         uint16_t *tdstY = dstY;
         const uint8_t *tsrc0 = src0;
-        for (x = c->srcW; x > 0; x--) {
+        for (x = c->sws->src_w; x > 0; x--) {
             t = *tsrc0++;
             output_pixel(tdstY++, t | (t << 8));
         }
@@ -349,7 +349,7 @@  static int planar8ToP01xleWrapper(SwsInternal *c, const uint8_t *const src[],
             uint16_t *tdstUV = dstUV;
             const uint8_t *tsrc1 = src1;
             const uint8_t *tsrc2 = src2;
-            for (x = c->srcW / 2; x > 0; x--) {
+            for (x = c->sws->src_w / 2; x > 0; x--) {
                 t = *tsrc1++;
                 output_pixel(tdstUV++, t | (t << 8));
                 t = *tsrc2++;
@@ -372,7 +372,7 @@  static int planarToYuy2Wrapper(SwsInternal *c, const uint8_t *const src[],
 {
     uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
 
-    yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
+    yv12toyuy2(src[0], src[1], src[2], dst, c->sws->src_w, srcSliceH, srcStride[0],
                srcStride[1], dstStride[0]);
 
     return srcSliceH;
@@ -384,7 +384,7 @@  static int planarToUyvyWrapper(SwsInternal *c, const uint8_t *const src[],
 {
     uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
 
-    yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
+    yv12touyvy(src[0], src[1], src[2], dst, c->sws->src_w, srcSliceH, srcStride[0],
                srcStride[1], dstStride[0]);
 
     return srcSliceH;
@@ -396,7 +396,7 @@  static int yuv422pToYuy2Wrapper(SwsInternal *c, const uint8_t *const src[],
 {
     uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
 
-    yuv422ptoyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
+    yuv422ptoyuy2(src[0], src[1], src[2], dst, c->sws->src_w, srcSliceH, srcStride[0],
                   srcStride[1], dstStride[0]);
 
     return srcSliceH;
@@ -408,7 +408,7 @@  static int yuv422pToUyvyWrapper(SwsInternal *c, const uint8_t *const src[],
 {
     uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
 
-    yuv422ptouyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
+    yuv422ptouyvy(src[0], src[1], src[2], dst, c->sws->src_w, srcSliceH, srcStride[0],
                   srcStride[1], dstStride[0]);
 
     return srcSliceH;
@@ -422,11 +422,11 @@  static int yuyvToYuv420Wrapper(SwsInternal *c, const uint8_t *const src[],
     uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2;
     uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2;
 
-    yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
+    yuyvtoyuv420(ydst, udst, vdst, src[0], c->sws->src_w, srcSliceH, dstStride[0],
                  dstStride[1], srcStride[0]);
 
     if (dstParam[3])
-        fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
+        fillPlane(dstParam[3], dstStride[3], c->sws->src_w, srcSliceH, srcSliceY, 255);
 
     return srcSliceH;
 }
@@ -439,7 +439,7 @@  static int yuyvToYuv422Wrapper(SwsInternal *c, const uint8_t *const src[],
     uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY;
     uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY;
 
-    yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
+    yuyvtoyuv422(ydst, udst, vdst, src[0], c->sws->src_w, srcSliceH, dstStride[0],
                  dstStride[1], srcStride[0]);
 
     return srcSliceH;
@@ -453,11 +453,11 @@  static int uyvyToYuv420Wrapper(SwsInternal *c, const uint8_t *const src[],
     uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2;
     uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2;
 
-    uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
+    uyvytoyuv420(ydst, udst, vdst, src[0], c->sws->src_w, srcSliceH, dstStride[0],
                  dstStride[1], srcStride[0]);
 
     if (dstParam[3])
-        fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
+        fillPlane(dstParam[3], dstStride[3], c->sws->src_w, srcSliceH, srcSliceY, 255);
 
     return srcSliceH;
 }
@@ -470,7 +470,7 @@  static int uyvyToYuv422Wrapper(SwsInternal *c, const uint8_t *const src[],
     uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY;
     uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY;
 
-    uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
+    uyvytoyuv422(ydst, udst, vdst, src[0], c->sws->src_w, srcSliceH, dstStride[0],
                  dstStride[1], srcStride[0]);
 
     return srcSliceH;
@@ -566,8 +566,8 @@  static int palToRgbWrapper(SwsInternal *c, const uint8_t *const src[], const int
                            int srcSliceY, int srcSliceH, uint8_t *const dst[],
                            const int dstStride[])
 {
-    const enum AVPixelFormat srcFormat = c->srcFormat;
-    const enum AVPixelFormat dstFormat = c->dstFormat;
+    const enum AVPixelFormat srcFormat = c->sws->src_format;
+    const enum AVPixelFormat dstFormat = c->sws->dst_format;
     void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels,
                  const uint8_t *palette) = NULL;
     int i;
@@ -595,11 +595,11 @@  static int palToRgbWrapper(SwsInternal *c, const uint8_t *const src[], const int
     }
 
     if (!conv)
-        av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
+        av_log(c->sws, AV_LOG_ERROR, "internal error %s -> %s converter\n",
                av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
     else {
         for (i = 0; i < srcSliceH; i++) {
-            conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
+            conv(srcPtr, dstPtr, c->sws->src_w, (uint8_t *) c->pal_rgb);
             srcPtr += srcStride[0];
             dstPtr += dstStride[0];
         }
@@ -750,8 +750,8 @@  static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[],
     uint16_t *dst1023[] = { (uint16_t *)dst[1], (uint16_t *)dst[0], (uint16_t *)dst[2], (uint16_t *)dst[3] };
     int stride2013[] = { dstStride[2], dstStride[0], dstStride[1], dstStride[3] };
     int stride1023[] = { dstStride[1], dstStride[0], dstStride[2], dstStride[3] };
-    const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat);
-    const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat);
+    const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->sws->src_format);
+    const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->sws->dst_format);
     int bpc = dst_format->comp[0].depth;
     int alpha = src_format->flags & AV_PIX_FMT_FLAG_ALPHA;
     int swap = 0;
@@ -766,7 +766,7 @@  static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[],
 
     if ((dst_format->flags & (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB)) !=
         (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB) || bpc < 9) {
-        av_log(c, AV_LOG_ERROR, "unsupported conversion to planar RGB %s -> %s\n",
+        av_log(c->sws, AV_LOG_ERROR, "unsupported conversion to planar RGB %s -> %s\n",
                src_format->name, dst_format->name);
         return srcSliceH;
     }
@@ -776,14 +776,14 @@  static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[],
         dst1023[i] += stride1023[i] * srcSliceY / 2;
     }
 
-    switch (c->srcFormat) {
+    switch (c->sws->src_format) {
     case AV_PIX_FMT_RGB48LE:
     case AV_PIX_FMT_RGB48BE:
     case AV_PIX_FMT_RGBA64LE:
     case AV_PIX_FMT_RGBA64BE:
         packed16togbra16(src[0], srcStride[0],
                          dst2013, stride2013, srcSliceH, alpha, swap,
-                         16 - bpc, c->srcW);
+                         16 - bpc, c->sws->src_w);
         break;
     case AV_PIX_FMT_BGR48LE:
     case AV_PIX_FMT_BGR48BE:
@@ -791,10 +791,10 @@  static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[],
     case AV_PIX_FMT_BGRA64BE:
         packed16togbra16(src[0], srcStride[0],
                          dst1023, stride1023, srcSliceH, alpha, swap,
-                         16 - bpc, c->srcW);
+                         16 - bpc, c->sws->src_w);
         break;
     default:
-        av_log(c, AV_LOG_ERROR,
+        av_log(c->sws, AV_LOG_ERROR,
                "unsupported conversion to planar RGB %s -> %s\n",
                src_format->name, dst_format->name);
     }
@@ -929,8 +929,8 @@  static int planarRgb16ToRgb16Wrapper(SwsInternal *c, const uint8_t *const src[],
     const uint16_t *src201[] = { (uint16_t *)src[2], (uint16_t *)src[0], (uint16_t *)src[1], (uint16_t *)src[3] };
     int stride102[] = { srcStride[1], srcStride[0], srcStride[2], srcStride[3] };
     int stride201[] = { srcStride[2], srcStride[0], srcStride[1], srcStride[3] };
-    const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat);
-    const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat);
+    const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->sws->src_format);
+    const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->sws->dst_format);
     int bits_per_sample = src_format->comp[0].depth;
     int swap = 0;
     if ( HAVE_BIGENDIAN && !(src_format->flags & AV_PIX_FMT_FLAG_BE) ||
@@ -943,37 +943,37 @@  static int planarRgb16ToRgb16Wrapper(SwsInternal *c, const uint8_t *const src[],
     if ((src_format->flags & (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB)) !=
         (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB) ||
         bits_per_sample <= 8) {
-        av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
+        av_log(c->sws, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
                src_format->name, dst_format->name);
         return srcSliceH;
     }
-    switch (c->dstFormat) {
+    switch (c->sws->dst_format) {
     case AV_PIX_FMT_BGR48LE:
     case AV_PIX_FMT_BGR48BE:
         gbr16ptopacked16(src102, stride102,
                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
-                         srcSliceH, 0, swap, bits_per_sample, c->srcW);
+                         srcSliceH, 0, swap, bits_per_sample, c->sws->src_w);
         break;
     case AV_PIX_FMT_RGB48LE:
     case AV_PIX_FMT_RGB48BE:
         gbr16ptopacked16(src201, stride201,
                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
-                         srcSliceH, 0, swap, bits_per_sample, c->srcW);
+                         srcSliceH, 0, swap, bits_per_sample, c->sws->src_w);
         break;
     case AV_PIX_FMT_RGBA64LE:
     case AV_PIX_FMT_RGBA64BE:
          gbr16ptopacked16(src201, stride201,
                           dst[0] + srcSliceY * dstStride[0], dstStride[0],
-                          srcSliceH, 1, swap, bits_per_sample, c->srcW);
+                          srcSliceH, 1, swap, bits_per_sample, c->sws->src_w);
         break;
     case AV_PIX_FMT_BGRA64LE:
     case AV_PIX_FMT_BGRA64BE:
         gbr16ptopacked16(src102, stride102,
                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
-                         srcSliceH, 1, swap, bits_per_sample, c->srcW);
+                         srcSliceH, 1, swap, bits_per_sample, c->sws->src_w);
         break;
     default:
-        av_log(c, AV_LOG_ERROR,
+        av_log(c->sws, AV_LOG_ERROR,
                "unsupported planar RGB conversion %s -> %s\n",
                src_format->name, dst_format->name);
     }
@@ -1067,24 +1067,24 @@  static int planarRgbaToRgbWrapper(SwsInternal *c, const uint8_t *const src[],
     int stride102[] = { srcStride[1], srcStride[0], srcStride[2], srcStride[3] };
     int stride201[] = { srcStride[2], srcStride[0], srcStride[1], srcStride[3] };
 
-    if (c->srcFormat != AV_PIX_FMT_GBRAP) {
-        av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
-               av_get_pix_fmt_name(c->srcFormat),
-               av_get_pix_fmt_name(c->dstFormat));
+    if (c->sws->src_format != AV_PIX_FMT_GBRAP) {
+        av_log(c->sws, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
+               av_get_pix_fmt_name(c->sws->src_format),
+               av_get_pix_fmt_name(c->sws->dst_format));
         return srcSliceH;
     }
 
-    switch (c->dstFormat) {
+    switch (c->sws->dst_format) {
     case AV_PIX_FMT_BGR24:
         gbr24ptopacked24(src102, stride102,
                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
-                         srcSliceH, c->srcW);
+                         srcSliceH, c->sws->src_w);
         break;
 
     case AV_PIX_FMT_RGB24:
         gbr24ptopacked24(src201, stride201,
                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
-                         srcSliceH, c->srcW);
+                         srcSliceH, c->sws->src_w);
         break;
 
     case AV_PIX_FMT_ARGB:
@@ -1092,7 +1092,7 @@  static int planarRgbaToRgbWrapper(SwsInternal *c, const uint8_t *const src[],
     case AV_PIX_FMT_RGBA:
         gbraptopacked32(src201, stride201,
                         dst[0] + srcSliceY * dstStride[0], dstStride[0],
-                        srcSliceH, alpha_first, c->srcW);
+                        srcSliceH, alpha_first, c->sws->src_w);
         break;
 
     case AV_PIX_FMT_ABGR:
@@ -1100,14 +1100,14 @@  static int planarRgbaToRgbWrapper(SwsInternal *c, const uint8_t *const src[],
     case AV_PIX_FMT_BGRA:
         gbraptopacked32(src102, stride102,
                         dst[0] + srcSliceY * dstStride[0], dstStride[0],
-                        srcSliceH, alpha_first, c->srcW);
+                        srcSliceH, alpha_first, c->sws->src_w);
         break;
 
     default:
-        av_log(c, AV_LOG_ERROR,
+        av_log(c->sws, AV_LOG_ERROR,
                "unsupported planar RGB conversion %s -> %s\n",
-               av_get_pix_fmt_name(c->srcFormat),
-               av_get_pix_fmt_name(c->dstFormat));
+               av_get_pix_fmt_name(c->sws->src_format),
+               av_get_pix_fmt_name(c->sws->dst_format));
     }
 
     return srcSliceH;
@@ -1123,24 +1123,24 @@  static int planarRgbToRgbWrapper(SwsInternal *c, const uint8_t *const src[],
     int stride102[] = { srcStride[1], srcStride[0], srcStride[2] };
     int stride201[] = { srcStride[2], srcStride[0], srcStride[1] };
 
-    if (c->srcFormat != AV_PIX_FMT_GBRP) {
-        av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
-               av_get_pix_fmt_name(c->srcFormat),
-               av_get_pix_fmt_name(c->dstFormat));
+    if (c->sws->src_format != AV_PIX_FMT_GBRP) {
+        av_log(c->sws, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
+               av_get_pix_fmt_name(c->sws->src_format),
+               av_get_pix_fmt_name(c->sws->dst_format));
         return srcSliceH;
     }
 
-    switch (c->dstFormat) {
+    switch (c->sws->dst_format) {
     case AV_PIX_FMT_BGR24:
         gbr24ptopacked24(src102, stride102,
                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
-                         srcSliceH, c->srcW);
+                         srcSliceH, c->sws->src_w);
         break;
 
     case AV_PIX_FMT_RGB24:
         gbr24ptopacked24(src201, stride201,
                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
-                         srcSliceH, c->srcW);
+                         srcSliceH, c->sws->src_w);
         break;
 
     case AV_PIX_FMT_ARGB:
@@ -1148,7 +1148,7 @@  static int planarRgbToRgbWrapper(SwsInternal *c, const uint8_t *const src[],
     case AV_PIX_FMT_RGBA:
         gbr24ptopacked32(src201, stride201,
                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
-                         srcSliceH, alpha_first, c->srcW);
+                         srcSliceH, alpha_first, c->sws->src_w);
         break;
 
     case AV_PIX_FMT_ABGR:
@@ -1156,14 +1156,14 @@  static int planarRgbToRgbWrapper(SwsInternal *c, const uint8_t *const src[],
     case AV_PIX_FMT_BGRA:
         gbr24ptopacked32(src102, stride102,
                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
-                         srcSliceH, alpha_first, c->srcW);
+                         srcSliceH, alpha_first, c->sws->src_w);
         break;
 
     default:
-        av_log(c, AV_LOG_ERROR,
+        av_log(c->sws, AV_LOG_ERROR,
                "unsupported planar RGB conversion %s -> %s\n",
-               av_get_pix_fmt_name(c->srcFormat),
-               av_get_pix_fmt_name(c->dstFormat));
+               av_get_pix_fmt_name(c->sws->src_format),
+               av_get_pix_fmt_name(c->sws->dst_format));
     }
 
     return srcSliceH;
@@ -1174,14 +1174,14 @@  static int planarRgbToplanarRgbWrapper(SwsInternal *c,
                                        int srcSliceY, int srcSliceH,
                                        uint8_t *const dst[], const int dstStride[])
 {
-    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
+    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->sws->src_w,
                  dst[0], dstStride[0]);
-    ff_copyPlane(src[1], srcStride[1], srcSliceY, srcSliceH, c->srcW,
+    ff_copyPlane(src[1], srcStride[1], srcSliceY, srcSliceH, c->sws->src_w,
                  dst[1], dstStride[1]);
-    ff_copyPlane(src[2], srcStride[2], srcSliceY, srcSliceH, c->srcW,
+    ff_copyPlane(src[2], srcStride[2], srcSliceY, srcSliceH, c->sws->src_w,
                  dst[2], dstStride[2]);
     if (dst[3])
-        fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
+        fillPlane(dst[3], dstStride[3], c->sws->src_w, srcSliceH, srcSliceY, 255);
 
     return srcSliceH;
 }
@@ -1229,32 +1229,32 @@  static int rgbToPlanarRgbWrapper(SwsInternal *c, const uint8_t *const src[],
                           dst[0] + srcSliceY * dstStride[0],
                           dst[1] + srcSliceY * dstStride[1] };
 
-    switch (c->srcFormat) {
+    switch (c->sws->src_format) {
     case AV_PIX_FMT_RGB24:
         packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst201,
-                       stride201, srcSliceH, alpha_first, 3, c->srcW);
+                       stride201, srcSliceH, alpha_first, 3, c->sws->src_w);
         break;
     case AV_PIX_FMT_BGR24:
         packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst102,
-                       stride102, srcSliceH, alpha_first, 3, c->srcW);
+                       stride102, srcSliceH, alpha_first, 3, c->sws->src_w);
         break;
     case AV_PIX_FMT_ARGB:
         alpha_first = 1;
     case AV_PIX_FMT_RGBA:
         packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst201,
-                       stride201, srcSliceH, alpha_first, 4, c->srcW);
+                       stride201, srcSliceH, alpha_first, 4, c->sws->src_w);
         break;
     case AV_PIX_FMT_ABGR:
         alpha_first = 1;
     case AV_PIX_FMT_BGRA:
         packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst102,
-                       stride102, srcSliceH, alpha_first, 4, c->srcW);
+                       stride102, srcSliceH, alpha_first, 4, c->sws->src_w);
         break;
     default:
-        av_log(c, AV_LOG_ERROR,
+        av_log(c->sws, AV_LOG_ERROR,
                "unsupported planar RGB conversion %s -> %s\n",
-               av_get_pix_fmt_name(c->srcFormat),
-               av_get_pix_fmt_name(c->dstFormat));
+               av_get_pix_fmt_name(c->sws->src_format),
+               av_get_pix_fmt_name(c->sws->dst_format));
     }
 
     return srcSliceH;
@@ -1330,7 +1330,7 @@  static int bayer_to_rgb24_wrapper(SwsInternal *c, const uint8_t *const src[],
     void (*copy)       (const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width);
     void (*interpolate)(const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width);
 
-    switch(c->srcFormat) {
+    switch(c->sws->src_format) {
 #define CASE(pixfmt, prefix) \
     case pixfmt: copy        = bayer_##prefix##_to_rgb24_copy; \
                  interpolate = bayer_##prefix##_to_rgb24_interpolate; \
@@ -1353,20 +1353,20 @@  static int bayer_to_rgb24_wrapper(SwsInternal *c, const uint8_t *const src[],
 
     av_assert0(srcSliceH > 1);
 
-    copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW);
+    copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->sws->src_w);
     srcPtr += 2 * srcStride[0];
     dstPtr += 2 * dstStride[0];
 
     for (i = 2; i < srcSliceH - 2; i += 2) {
-        interpolate(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW);
+        interpolate(srcPtr, srcStride[0], dstPtr, dstStride[0], c->sws->src_w);
         srcPtr += 2 * srcStride[0];
         dstPtr += 2 * dstStride[0];
     }
 
     if (i + 1 == srcSliceH) {
-        copy(srcPtr, -srcStride[0], dstPtr, -dstStride[0], c->srcW);
+        copy(srcPtr, -srcStride[0], dstPtr, -dstStride[0], c->sws->src_w);
     } else if (i < srcSliceH)
-        copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW);
+        copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->sws->src_w);
     return srcSliceH;
 }
 
@@ -1380,7 +1380,7 @@  static int bayer_to_rgb48_wrapper(SwsInternal *c, const uint8_t *const src[],
     void (*copy)       (const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width);
     void (*interpolate)(const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width);
 
-    switch(c->srcFormat) {
+    switch(c->sws->src_format) {
 #define CASE(pixfmt, prefix) \
     case pixfmt: copy        = bayer_##prefix##_to_rgb48_copy; \
                  interpolate = bayer_##prefix##_to_rgb48_interpolate; \
@@ -1403,20 +1403,20 @@  static int bayer_to_rgb48_wrapper(SwsInternal *c, const uint8_t *const src[],
 
     av_assert0(srcSliceH > 1);
 
-    copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW);
+    copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->sws->src_w);
     srcPtr += 2 * srcStride[0];
     dstPtr += 2 * dstStride[0];
 
     for (i = 2; i < srcSliceH - 2; i += 2) {
-        interpolate(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW);
+        interpolate(srcPtr, srcStride[0], dstPtr, dstStride[0], c->sws->src_w);
         srcPtr += 2 * srcStride[0];
         dstPtr += 2 * dstStride[0];
     }
 
     if (i + 1 == srcSliceH) {
-        copy(srcPtr, -srcStride[0], dstPtr, -dstStride[0], c->srcW);
+        copy(srcPtr, -srcStride[0], dstPtr, -dstStride[0], c->sws->src_w);
     } else if (i < srcSliceH)
-        copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW);
+        copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->sws->src_w);
     return srcSliceH;
 }
 
@@ -1432,7 +1432,7 @@  static int bayer_to_yv12_wrapper(SwsInternal *c, const uint8_t *const src[],
     void (*copy)       (const uint8_t *src, int src_stride, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, int luma_stride, int width, const int32_t *rgb2yuv);
     void (*interpolate)(const uint8_t *src, int src_stride, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, int luma_stride, int width, const int32_t *rgb2yuv);
 
-    switch(c->srcFormat) {
+    switch(c->sws->src_format) {
 #define CASE(pixfmt, prefix) \
     case pixfmt: copy        = bayer_##prefix##_to_yv12_copy; \
                  interpolate = bayer_##prefix##_to_yv12_interpolate; \
@@ -1455,14 +1455,14 @@  static int bayer_to_yv12_wrapper(SwsInternal *c, const uint8_t *const src[],
 
     av_assert0(srcSliceH > 1);
 
-    copy(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->srcW, c->input_rgb2yuv_table);
+    copy(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->sws->src_w, c->input_rgb2yuv_table);
     srcPtr += 2 * srcStride[0];
     dstY   += 2 * dstStride[0];
     dstU   +=     dstStride[1];
     dstV   +=     dstStride[1];
 
     for (i = 2; i < srcSliceH - 2; i += 2) {
-        interpolate(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->srcW, c->input_rgb2yuv_table);
+        interpolate(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->sws->src_w, c->input_rgb2yuv_table);
         srcPtr += 2 * srcStride[0];
         dstY   += 2 * dstStride[0];
         dstU   +=     dstStride[1];
@@ -1470,9 +1470,9 @@  static int bayer_to_yv12_wrapper(SwsInternal *c, const uint8_t *const src[],
     }
 
     if (i + 1 == srcSliceH) {
-        copy(srcPtr, -srcStride[0], dstY, dstU, dstV, -dstStride[0], c->srcW, c->input_rgb2yuv_table);
+        copy(srcPtr, -srcStride[0], dstY, dstU, dstV, -dstStride[0], c->sws->src_w, c->input_rgb2yuv_table);
     } else if (i < srcSliceH)
-        copy(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->srcW, c->input_rgb2yuv_table);
+        copy(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->sws->src_w, c->input_rgb2yuv_table);
     return srcSliceH;
 }
 
@@ -1501,8 +1501,8 @@  static int bayer_to_yv12_wrapper(SwsInternal *c, const uint8_t *const src[],
 typedef void (* rgbConvFn) (const uint8_t *, uint8_t *, int);
 static rgbConvFn findRgbConvFn(SwsInternal *c)
 {
-    const enum AVPixelFormat srcFormat = c->srcFormat;
-    const enum AVPixelFormat dstFormat = c->dstFormat;
+    const enum AVPixelFormat srcFormat = c->sws->src_format;
+    const enum AVPixelFormat dstFormat = c->sws->dst_format;
     const int srcId = c->srcFormatBpp;
     const int dstId = c->dstFormatBpp;
     rgbConvFn conv = NULL;
@@ -1614,7 +1614,7 @@  static rgbConvFn findRgbConvFn(SwsInternal *c)
         return NULL;
 
     // Maintain symmetry between endianness
-    if (c->flags & SWS_BITEXACT)
+    if (c->sws->flags & SWS_BITEXACT)
         if ((dstFormat == AV_PIX_FMT_RGB32   || dstFormat == AV_PIX_FMT_BGR32  ) && !isRGBA32(srcFormat) && ALT32_CORR>0)
             return NULL;
 
@@ -1627,16 +1627,16 @@  static int rgbToRgbWrapper(SwsInternal *c, const uint8_t *const src[], const int
                            const int dstStride[])
 
 {
-    const enum AVPixelFormat srcFormat = c->srcFormat;
-    const enum AVPixelFormat dstFormat = c->dstFormat;
-    const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
-    const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
+    const enum AVPixelFormat srcFormat = c->sws->src_format;
+    const enum AVPixelFormat dstFormat = c->sws->dst_format;
+    const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->sws->src_format);
+    const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->sws->dst_format);
     const int srcBpp = (c->srcFormatBpp + 7) >> 3;
     const int dstBpp = (c->dstFormatBpp + 7) >> 3;
     rgbConvFn conv = findRgbConvFn(c);
 
     if (!conv) {
-        av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
+        av_log(c->sws, AV_LOG_ERROR, "internal error %s -> %s converter\n",
                av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
     } else {
         const uint8_t *srcPtr = src[0];
@@ -1660,20 +1660,20 @@  static int rgbToRgbWrapper(SwsInternal *c, const uint8_t *const src[], const int
         if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 &&
             !(srcStride[0] % srcBpp) && !dst_bswap && !src_bswap)
             conv(srcPtr, dstPtr + dstStride[0] * srcSliceY,
-                 (srcSliceH - 1) * srcStride[0] + c->srcW * srcBpp);
+                 (srcSliceH - 1) * srcStride[0] + c->sws->src_w * srcBpp);
         else {
             int i, j;
             dstPtr += dstStride[0] * srcSliceY;
 
             for (i = 0; i < srcSliceH; i++) {
                 if(src_bswap) {
-                    for(j=0; j<c->srcW; j++)
+                    for(j=0; j<c->sws->src_w; j++)
                         ((uint16_t*)c->formatConvBuffer)[j] = av_bswap16(((uint16_t*)srcPtr)[j]);
-                    conv(c->formatConvBuffer, dstPtr, c->srcW * srcBpp);
+                    conv(c->formatConvBuffer, dstPtr, c->sws->src_w * srcBpp);
                 }else
-                    conv(srcPtr, dstPtr, c->srcW * srcBpp);
+                    conv(srcPtr, dstPtr, c->sws->src_w * srcBpp);
                 if(dst_bswap)
-                    for(j=0; j<c->srcW; j++)
+                    for(j=0; j<c->sws->src_w; j++)
                         ((uint16_t*)dstPtr)[j] = av_bswap16(((uint16_t*)dstPtr)[j]);
                 srcPtr += srcStride[0];
                 dstPtr += dstStride[0];
@@ -1692,11 +1692,11 @@  static int bgr24ToYv12Wrapper(SwsInternal *c, const uint8_t *const src[],
         dst[0] +  srcSliceY       * dstStride[0],
         dst[1] + (srcSliceY >> 1) * dstStride[1],
         dst[2] + (srcSliceY >> 1) * dstStride[2],
-        c->srcW, srcSliceH,
+        c->sws->src_w, srcSliceH,
         dstStride[0], dstStride[1], srcStride[0],
         c->input_rgb2yuv_table);
     if (dst[3])
-        fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
+        fillPlane(dst[3], dstStride[3], c->sws->src_w, srcSliceH, srcSliceY, 255);
     return srcSliceH;
 }
 
@@ -1704,7 +1704,7 @@  static int yvu9ToYv12Wrapper(SwsInternal *c, const uint8_t *const src[],
                              const int srcStride[], int srcSliceY, int srcSliceH,
                              uint8_t *const dst[], const int dstStride[])
 {
-    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
+    ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->sws->src_w,
                  dst[0], dstStride[0]);
 
     planar2x(src[1], dst[1] + dstStride[1] * (srcSliceY >> 1), c->chrSrcW,
@@ -1712,7 +1712,7 @@  static int yvu9ToYv12Wrapper(SwsInternal *c, const uint8_t *const src[],
     planar2x(src[2], dst[2] + dstStride[2] * (srcSliceY >> 1), c->chrSrcW,
              srcSliceH >> 2, srcStride[2], dstStride[2]);
     if (dst[3])
-        fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
+        fillPlane(dst[3], dstStride[3], c->sws->src_w, srcSliceH, srcSliceY, 255);
     return srcSliceH;
 }
 
@@ -1726,7 +1726,7 @@  static int uint_y_to_float_y_wrapper(SwsInternal *c, const uint8_t *const src[],
     float *dstPtr = (float *)(dst[0] + dstStride[0] * srcSliceY);
 
     for (y = 0; y < srcSliceH; ++y){
-        for (x = 0; x < c->srcW; ++x){
+        for (x = 0; x < c->sws->src_w; ++x){
             dstPtr[x] = c->uint2float_lut[srcPtr[x]];
         }
         srcPtr += srcStride[0];
@@ -1748,7 +1748,7 @@  static int float_y_to_uint_y_wrapper(SwsInternal *c,
     uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
 
     for (y = 0; y < srcSliceH; ++y){
-        for (x = 0; x < c->srcW; ++x){
+        for (x = 0; x < c->sws->src_w; ++x){
             dstPtr[x] = av_clip_uint8(lrintf(255.0f * srcPtr[x]));
         }
         srcPtr += srcStrideFloat;
@@ -1772,9 +1772,9 @@  static int packedCopyWrapper(SwsInternal *c, const uint8_t *const src[],
         int length = 0;
 
         /* universal length finder */
-        while (length + c->srcW <= FFABS(dstStride[0]) &&
-               length + c->srcW <= FFABS(srcStride[0]))
-            length += c->srcW;
+        while (length + c->sws->src_w <= FFABS(dstStride[0]) &&
+               length + c->sws->src_w <= FFABS(srcStride[0]))
+            length += c->sws->src_w;
         av_assert1(length != 0);
 
         for (i = 0; i < srcSliceH; i++) {
@@ -1788,7 +1788,7 @@  static int packedCopyWrapper(SwsInternal *c, const uint8_t *const src[],
 
 #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\
     unsigned shift= src_depth-dst_depth, tmp;\
-    if (c->dither == SWS_DITHER_NONE) {\
+    if (c->sws->dither == SWS_DITHER_NONE) {\
         for (i = 0; i < height; i++) {\
             for (j = 0; j < length-7; j+=8) {\
                 dst[j+0] = dbswap(bswap(src[j+0])>>shift);\
@@ -1850,31 +1850,31 @@  static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[],
                              const int srcStride[], int srcSliceY, int srcSliceH,
                              uint8_t *const dst[], const int dstStride[])
 {
-    const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
-    const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
+    const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->sws->src_format);
+    const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->sws->dst_format);
     int plane, i, j;
     for (plane = 0; plane < 4 && dst[plane] != NULL; plane++) {
-        int length = (plane == 0 || plane == 3) ? c->srcW  : AV_CEIL_RSHIFT(c->srcW,   c->chrDstHSubSample);
+        int length = (plane == 0 || plane == 3) ? c->sws->src_w  : AV_CEIL_RSHIFT(c->sws->src_w,   c->chrDstHSubSample);
         int y =      (plane == 0 || plane == 3) ? srcSliceY: AV_CEIL_RSHIFT(srcSliceY, c->chrDstVSubSample);
         int height = (plane == 0 || plane == 3) ? srcSliceH: AV_CEIL_RSHIFT(srcSliceH, c->chrDstVSubSample);
         const uint8_t *srcPtr = src[plane];
         uint8_t *dstPtr = dst[plane] + dstStride[plane] * y;
-        int shiftonly = plane == 1 || plane == 2 || (!c->srcRange && plane == 0);
+        int shiftonly = plane == 1 || plane == 2 || (!c->sws->src_range && plane == 0);
 
         // ignore palette for GRAY8
         if (plane == 1 && !dst[2]) continue;
         if (!src[plane] || (plane == 1 && !src[2])) {
-            if (is16BPS(c->dstFormat) || isNBPS(c->dstFormat)) {
+            if (is16BPS(c->sws->dst_format) || isNBPS(c->sws->dst_format)) {
                 fillPlane16(dst[plane], dstStride[plane], length, height, y,
                         plane == 3, desc_dst->comp[plane].depth,
-                        isBE(c->dstFormat));
+                        isBE(c->sws->dst_format));
             } else {
                 fillPlane(dst[plane], dstStride[plane], length, height, y,
                         (plane == 3) ? 255 : 128);
             }
         } else {
-            if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat)
-               || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat))
+            if(isNBPS(c->sws->src_format) || isNBPS(c->sws->dst_format)
+               || (is16BPS(c->sws->src_format) != is16BPS(c->sws->dst_format))
             ) {
                 const int src_depth = desc_src->comp[plane].depth;
                 const int dst_depth = desc_dst->comp[plane].depth;
@@ -1882,7 +1882,7 @@  static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[],
                 uint16_t *dstPtr2 = (uint16_t*)dstPtr;
 
                 if (dst_depth == 8) {
-                    if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
+                    if(isBE(c->sws->src_format) == HAVE_BIGENDIAN){
                         DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , )
                     } else {
                         DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, )
@@ -1898,7 +1898,7 @@  static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[],
                                 w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\
                                                (srcPtr[j]>>(2*8-dst_depth)));\
                         }
-                        if(isBE(c->dstFormat)){
+                        if(isBE(c->sws->dst_format)){
                             COPY816(AV_WB16)
                         } else {
                             COPY816(AV_WL16)
@@ -1909,8 +1909,8 @@  static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[],
                 } else if (src_depth <= dst_depth) {
                     for (i = 0; i < height; i++) {
                         j = 0;
-                        if(isBE(c->srcFormat) == HAVE_BIGENDIAN &&
-                           isBE(c->dstFormat) == HAVE_BIGENDIAN &&
+                        if(isBE(c->sws->src_format) == HAVE_BIGENDIAN &&
+                           isBE(c->sws->dst_format) == HAVE_BIGENDIAN &&
                            shiftonly) {
                              unsigned shift = dst_depth - src_depth;
 #if HAVE_FAST_64BIT
@@ -1945,14 +1945,14 @@  static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[],
                         (v>>(2*src_depth-dst_depth)));\
         }\
     }
-                        if(isBE(c->srcFormat)){
-                            if(isBE(c->dstFormat)){
+                        if(isBE(c->sws->src_format)){
+                            if(isBE(c->sws->dst_format)){
                                 COPY_UP(AV_RB16, AV_WB16)
                             } else {
                                 COPY_UP(AV_RB16, AV_WL16)
                             }
                         } else {
-                            if(isBE(c->dstFormat)){
+                            if(isBE(c->sws->dst_format)){
                                 COPY_UP(AV_RL16, AV_WB16)
                             } else {
                                 COPY_UP(AV_RL16, AV_WL16)
@@ -1962,22 +1962,22 @@  static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[],
                         srcPtr2 += srcStride[plane]/2;
                     }
                 } else {
-                    if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
-                        if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
+                    if(isBE(c->sws->src_format) == HAVE_BIGENDIAN){
+                        if(isBE(c->sws->dst_format) == HAVE_BIGENDIAN){
                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , )
                         } else {
                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16)
                         }
                     }else{
-                        if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
+                        if(isBE(c->sws->dst_format) == HAVE_BIGENDIAN){
                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, )
                         } else {
                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16)
                         }
                     }
                 }
-            } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) &&
-                      isBE(c->srcFormat) != isBE(c->dstFormat)) {
+            } else if (is16BPS(c->sws->src_format) && is16BPS(c->sws->dst_format) &&
+                      isBE(c->sws->src_format) != isBE(c->sws->dst_format)) {
 
                 for (i = 0; i < height; i++) {
                     for (j = 0; j < length; j++)
@@ -1985,8 +1985,8 @@  static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[],
                     srcPtr += srcStride[plane];
                     dstPtr += dstStride[plane];
                 }
-            } else if (isFloat(c->srcFormat) && isFloat(c->dstFormat) &&
-                       isBE(c->srcFormat) != isBE(c->dstFormat)) { /* swap float plane */
+            } else if (isFloat(c->sws->src_format) && isFloat(c->sws->dst_format) &&
+                       isBE(c->sws->src_format) != isBE(c->sws->dst_format)) { /* swap float plane */
                 for (i = 0; i < height; i++) {
                     for (j = 0; j < length; j++)
                         ((uint32_t *) dstPtr)[j] = av_bswap32(((const uint32_t *) srcPtr)[j]);
@@ -1998,7 +1998,7 @@  static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[],
                 memcpy(dst[plane] + dstStride[plane] * y, src[plane],
                        height * dstStride[plane]);
             } else {
-                if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
+                if (is16BPS(c->sws->src_format) && is16BPS(c->sws->dst_format))
                     length *= 2;
                 else if (desc_src->comp[0].depth == 1)
                     length >>= 3; // monowhite/black
@@ -2021,11 +2021,11 @@  static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[],
 
 void ff_get_unscaled_swscale(SwsInternal *c)
 {
-    const enum AVPixelFormat srcFormat = c->srcFormat;
-    const enum AVPixelFormat dstFormat = c->dstFormat;
-    const int flags = c->flags;
-    const int dstH = c->dstH;
-    const int dstW = c->dstW;
+    const enum AVPixelFormat srcFormat = c->sws->src_format;
+    const enum AVPixelFormat dstFormat = c->sws->dst_format;
+    const int flags = c->sws->flags;
+    const int dstH = c->sws->dst_h;
+    const int dstW = c->sws->dst_w;
     int needsDither;
 
     needsDither = isAnyRGB(dstFormat) &&
@@ -2055,7 +2055,7 @@  void ff_get_unscaled_swscale(SwsInternal *c)
     /* yuv2bgr */
     if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P ||
          srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) &&
-        !(flags & SWS_ACCURATE_RND) && (c->dither == SWS_DITHER_BAYER || c->dither == SWS_DITHER_AUTO) && !(dstH & 1)) {
+        !(flags & SWS_ACCURATE_RND) && (c->sws->dither == SWS_DITHER_BAYER || c->sws->dither == SWS_DITHER_AUTO) && !(dstH & 1)) {
         c->convert_unscaled = ff_yuv2rgb_get_func_ptr(c);
         c->dst_slice_align = 2;
     }
@@ -2088,7 +2088,7 @@  void ff_get_unscaled_swscale(SwsInternal *c)
 
     /* RGB/BGR -> RGB/BGR (no dither needed forms) */
     if (isAnyRGB(srcFormat) && isAnyRGB(dstFormat) && findRgbConvFn(c)
-        && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
+        && (!needsDither || (c->sws->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
         c->convert_unscaled = rgbToRgbWrapper;
 
     /* RGB to planar RGB */
@@ -2153,7 +2153,7 @@  void ff_get_unscaled_swscale(SwsInternal *c)
         else if (dstFormat == AV_PIX_FMT_YUV420P)
             c->convert_unscaled = bayer_to_yv12_wrapper;
         else if (!isBayer(dstFormat)) {
-            av_log(c, AV_LOG_ERROR, "unsupported bayer conversion\n");
+            av_log(c->sws, AV_LOG_ERROR, "unsupported bayer conversion\n");
             av_assert0(0);
         }
     }
@@ -2235,7 +2235,7 @@  void ff_get_unscaled_swscale(SwsInternal *c)
     }
 
     /* LQ converters if -sws 0 or -sws 4*/
-    if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
+    if (c->sws->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
         /* yv12_to_yuy2 */
         if (srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) {
             if (dstFormat == AV_PIX_FMT_YUYV422)
@@ -2271,7 +2271,7 @@  void ff_get_unscaled_swscale(SwsInternal *c)
          c->chrDstVSubSample == c->chrSrcVSubSample &&
          !isSemiPlanarYUV(srcFormat) && !isSemiPlanarYUV(dstFormat))))
     {
-        if (isPacked(c->srcFormat))
+        if (isPacked(c->sws->src_format))
             c->convert_unscaled = packedCopyWrapper;
         else /* Planar YUV or gray */
             c->convert_unscaled = planarCopyWrapper;
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 3ce9a92504..49387694cd 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -290,22 +290,20 @@  static SwsContext *alloc_set_opts(int srcW, int srcH, enum AVPixelFormat srcForm
                                   int flags, const double *param)
 {
     SwsContext *sws = sws_alloc_context();
-    SwsInternal *c = sws_internal(sws);
-
-    if (!c)
+    if (!sws)
         return NULL;
 
-    c->flags     = flags;
-    c->srcW      = srcW;
-    c->srcH      = srcH;
-    c->dstW      = dstW;
-    c->dstH      = dstH;
-    c->srcFormat = srcFormat;
-    c->dstFormat = dstFormat;
+    sws->flags = flags;
+    sws->src_w = srcW;
+    sws->src_h = srcH;
+    sws->dst_w = dstW;
+    sws->dst_h      = dstH;
+    sws->src_format = srcFormat;
+    sws->dst_format = dstFormat;
 
     if (param) {
-        c->param[0] = param[0];
-        c->param[1] = param[1];
+        sws->scaler_params[0] = param[0];
+        sws->scaler_params[1] = param[1];
     }
 
     return sws;
@@ -1025,12 +1023,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->srcFormat);
-    c->dst0Alpha |= handle_0alpha(&c->dstFormat);
-    c->srcXYZ    |= handle_xyz(&c->srcFormat);
-    c->dstXYZ    |= handle_xyz(&c->dstFormat);
+    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);
 }
@@ -1062,17 +1061,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->dstFormat);
-    desc_src = av_pix_fmt_desc_get(c->srcFormat);
+    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->dstFormat))
+    if(range_override_needed(sws->dst_format))
         dstRange = 0;
-    if(range_override_needed(c->srcFormat))
+    if(range_override_needed(sws->src_format))
         srcRange = 0;
 
-    if (c->srcRange != srcRange ||
-        c->dstRange != dstRange ||
+    if (sws->src_range != srcRange ||
+        sws->dst_range != dstRange ||
         c->brightness != brightness ||
         c->contrast   != contrast ||
         c->saturation != saturation ||
@@ -1089,8 +1088,8 @@  int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4],
     c->brightness = brightness;
     c->contrast   = contrast;
     c->saturation = saturation;
-    c->srcRange   = srcRange;
-    c->dstRange   = dstRange;
+    sws->src_range = srcRange;
+    sws->dst_range = dstRange;
 
     if (need_reinit) {
         ff_sws_init_range_convert(c);
@@ -1112,27 +1111,27 @@  int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4],
     if (!need_reinit)
         return 0;
 
-    if ((isYUV(c->dstFormat) || isGray(c->dstFormat)) && (isYUV(c->srcFormat) || isGray(c->srcFormat))) {
+    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->srcW && c->srcH && c->dstW && c->dstH) {
+            sws->src_w && sws->src_h && sws->dst_w && sws->dst_h) {
             enum AVPixelFormat tmp_format;
             int tmp_width, tmp_height;
-            int srcW = c->srcW;
-            int srcH = c->srcH;
-            int dstW = c->dstW;
-            int dstH = c->dstH;
+            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");
+            av_log(sws, AV_LOG_VERBOSE, "YUV color matrix differs for YUV->YUV, using intermediate RGB to convert\n");
 
-            if (isNBPS(c->dstFormat) || is16BPS(c->dstFormat)) {
-                if (isALPHA(c->srcFormat) && isALPHA(c->dstFormat)) {
+            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->srcFormat) && isALPHA(c->dstFormat)) {
+                if (isALPHA(sws->src_format) && isALPHA(sws->dst_format)) {
                     tmp_format = AV_PIX_FMT_BGRA;
                 } else {
                     tmp_format = AV_PIX_FMT_BGR24;
@@ -1152,13 +1151,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->srcFormat,
+            c->cascaded_context[0] = alloc_set_opts(srcW, srcH, sws->src_format,
                                                     tmp_width, tmp_height, tmp_format,
-                                                    c->flags, c->param);
+                                                    sws->flags, sws->scaler_params);
             if (!c->cascaded_context[0])
                 return -1;
 
-            sws_internal(c->cascaded_context[0])->alphablend = c->alphablend;
+            c->cascaded_context[0]->alpha_blend = sws->alpha_blend;
             ret = sws_init_context(c->cascaded_context[0], NULL , NULL);
             if (ret < 0)
                 return ret;
@@ -1168,12 +1167,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->dstFormat,
-                                                    c->flags, c->param);
+                                                    dstW, dstH, sws->dst_format,
+                                                    sws->flags, sws->scaler_params);
             if (!c->cascaded_context[1])
                 return -1;
-            sws_internal(c->cascaded_context[1])->srcRange = srcRange;
-            sws_internal(c->cascaded_context[1])->dstRange = 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;
@@ -1188,7 +1187,7 @@  int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4],
         return 0;
     }
 
-    if (!isYUV(c->dstFormat) && !isGray(c->dstFormat)) {
+    if (!isYUV(sws->dst_format) && !isGray(sws->dst_format)) {
         ff_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness,
                                  contrast, saturation);
         // FIXME factorize
@@ -1220,8 +1219,8 @@  int sws_getColorspaceDetails(SwsContext *sws, int **inv_table,
 
     *inv_table  = c->srcColorspaceTable;
     *table      = c->dstColorspaceTable;
-    *srcRange   = range_override_needed(c->srcFormat) ? 1 : c->srcRange;
-    *dstRange   = range_override_needed(c->dstFormat) ? 1 : c->dstRange;
+    *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;
@@ -1231,16 +1230,24 @@  int sws_getColorspaceDetails(SwsContext *sws, int **inv_table,
 
 SwsContext *sws_alloc_context(void)
 {
-    SwsInternal *c = av_mallocz(sizeof(SwsInternal));
+    SwsInternal *c;
+    SwsContext *sws = (SwsContext *) av_mallocz(sizeof(SwsContext));
+    if (!sws)
+        return NULL;
+    sws->av_class = &ff_sws_context_class;
 
-    if (c) {
-        c->av_class = &ff_sws_context_class;
-        av_opt_set_defaults(c);
-        atomic_init(&c->stride_unaligned_warned, 0);
-        atomic_init(&c->data_unaligned_warned,   0);
+    c = sws->internal = av_mallocz(sizeof(SwsInternal));
+    if (!c) {
+        av_free(sws);
+        return NULL;
     }
+    c->sws = sws;
+
+    av_opt_set_defaults(sws);
+    atomic_init(&c->stride_unaligned_warned, 0);
+    atomic_init(&c->data_unaligned_warned,   0);
 
-    return (SwsContext *) c;
+    return sws;
 }
 
 static uint16_t * alloc_gamma_tbl(double e)
@@ -1326,10 +1333,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->srcW;
-    int srcH              = c->srcH;
-    int dstW              = c->dstW;
-    int dstH              = c->dstH;
+    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;
@@ -1340,35 +1347,35 @@  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->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->srcRange,
+        sws_setColorspaceDetails(sws, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], sws->src_range,
                                  ff_yuv2rgb_coeffs[SWS_CS_DEFAULT],
-                                 c->dstRange, 0, 1 << 16, 1 << 16);
+                                 sws->dst_range, 0, 1 << 16, 1 << 16);
 
-    handle_formats(c);
-    srcFormat = c->srcFormat;
-    dstFormat = c->dstFormat;
+    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->alphablend = SWS_ALPHA_BLEND_NONE;
+        sws->alpha_blend = SWS_ALPHA_BLEND_NONE;
 
     if (!(unscaled && sws_isSupportedEndiannessConversion(srcFormat) &&
           av_pix_fmt_swap_endianness(srcFormat) == dstFormat)) {
         if (!sws_isSupportedInput(srcFormat)) {
-            av_log(c, AV_LOG_ERROR, "%s is not supported as input pixel format\n",
+            av_log(sws, AV_LOG_ERROR, "%s is not supported as input pixel format\n",
                    av_get_pix_fmt_name(srcFormat));
             return AVERROR(EINVAL);
         }
         if (!sws_isSupportedOutput(dstFormat)) {
-            av_log(c, AV_LOG_ERROR, "%s is not supported as output pixel format\n",
+            av_log(sws, AV_LOG_ERROR, "%s is not supported as output pixel format\n",
                    av_get_pix_fmt_name(dstFormat));
             return AVERROR(EINVAL);
         }
@@ -1395,9 +1402,9 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
             flags |= SWS_BICUBIC;
         else
             flags |= SWS_BICUBIC;
-        c->flags = flags;
+        sws->flags = flags;
     } else if (i & (i - 1)) {
-        av_log(c, AV_LOG_ERROR,
+        av_log(sws, AV_LOG_ERROR,
                "Exactly one scaler algorithm must be chosen, got %X\n", i);
         return AVERROR(EINVAL);
     }
@@ -1405,14 +1412,14 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
     if (srcW < 1 || srcH < 1 || dstW < 1 || dstH < 1) {
         /* FIXME check if these are enough and try to lower them after
          * fixing the relevant parts of the code */
-        av_log(c, AV_LOG_ERROR, "%dx%d -> %dx%d is invalid scaling dimension\n",
+        av_log(sws, AV_LOG_ERROR, "%dx%d -> %dx%d is invalid scaling dimension\n",
                srcW, srcH, dstW, dstH);
         return AVERROR(EINVAL);
     }
     if (flags & SWS_FAST_BILINEAR) {
         if (srcW < 8 || dstW < 8) {
             flags ^= SWS_FAST_BILINEAR | SWS_BILINEAR;
-            c->flags = flags;
+            sws->flags = flags;
         }
     }
 
@@ -1443,58 +1450,58 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
 
     if (isAnyRGB(dstFormat) && !(flags&SWS_FULL_CHR_H_INT)) {
         if (dstW&1) {
-            av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to odd output size\n");
+            av_log(sws, AV_LOG_DEBUG, "Forcing full internal H chroma due to odd output size\n");
             flags |= SWS_FULL_CHR_H_INT;
-            c->flags = flags;
+            sws->flags = flags;
         }
 
         if (   c->chrSrcHSubSample == 0
             && c->chrSrcVSubSample == 0
-            && c->dither != SWS_DITHER_BAYER //SWS_FULL_CHR_H_INT is currently not supported with SWS_DITHER_BAYER
-            && !(c->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");
+            av_log(sws, AV_LOG_DEBUG, "Forcing full internal H chroma due to input having non subsampled chroma\n");
             flags |= SWS_FULL_CHR_H_INT;
-            c->flags = flags;
+            sws->flags = flags;
         }
     }
 
-    if (c->dither == SWS_DITHER_AUTO) {
+    if (sws->dither == SWS_DITHER_AUTO) {
         if (flags & SWS_ERROR_DIFFUSION)
-            c->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->dither == SWS_DITHER_AUTO)
-            c->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->dither == SWS_DITHER_ED || c->dither == SWS_DITHER_A_DITHER || c->dither == SWS_DITHER_X_DITHER || c->dither == SWS_DITHER_NONE) {
-                av_log(c, AV_LOG_DEBUG,
+            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(sws, 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->flags = flags;
+                sws->flags = flags;
             }
         }
         if (flags & SWS_FULL_CHR_H_INT) {
-            if (c->dither == SWS_DITHER_BAYER) {
-                av_log(c, AV_LOG_DEBUG,
+            if (sws->dither == SWS_DITHER_BAYER) {
+                av_log(sws, AV_LOG_DEBUG,
                     "Ordered dither is not supported in full chroma interpolation for destination format '%s'\n",
                     av_get_pix_fmt_name(dstFormat));
-                c->dither = SWS_DITHER_ED;
+                sws->dither = SWS_DITHER_ED;
             }
         }
     }
     if (isPlanarRGB(dstFormat)) {
         if (!(flags & SWS_FULL_CHR_H_INT)) {
-            av_log(c, AV_LOG_DEBUG,
+            av_log(sws, AV_LOG_DEBUG,
                    "%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->flags = flags;
+            sws->flags = flags;
         }
     }
 
@@ -1522,11 +1529,11 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
         dstFormat != AV_PIX_FMT_BGR8 &&
         dstFormat != AV_PIX_FMT_RGB8
     ) {
-        av_log(c, AV_LOG_WARNING,
+        av_log(sws, AV_LOG_WARNING,
                "full chroma interpolation for destination format '%s' not yet implemented\n",
                av_get_pix_fmt_name(dstFormat));
         flags   &= ~SWS_FULL_CHR_H_INT;
-        c->flags = flags;
+        sws->flags = flags;
     }
     if (isAnyRGB(dstFormat) && !(flags & SWS_FULL_CHR_H_INT))
         c->chrDstHSubSample = 1;
@@ -1585,10 +1592,10 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
 
             && (flags & SWS_FAST_BILINEAR)) {
             if (flags & SWS_PRINT_INFO)
-                av_log(c, AV_LOG_INFO,
+                av_log(sws, AV_LOG_INFO,
                        "output width is not a multiple of 32 -> no MMXEXT scaler\n");
         }
-        if (usesHFilter || isNBPS(c->srcFormat) || is16BPS(c->srcFormat) || isAnyRGB(c->srcFormat))
+        if (usesHFilter || isNBPS(sws->src_format) || is16BPS(sws->src_format) || isAnyRGB(sws->src_format))
             c->canMMXEXTBeUsed = 0;
     } else
         c->canMMXEXTBeUsed = 0;
@@ -1619,8 +1626,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->gamma_flag && (srcFormat != tmpFmt || dstFormat != tmpFmt)) {
+    if (!unscaled && sws->gamma_flag && (srcFormat != tmpFmt || dstFormat != tmpFmt)) {
         SwsInternal *c2;
         c->cascaded_context[0] = NULL;
 
@@ -1631,14 +1637,16 @@  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->param);
+                                                flags, NULL, NULL,
+                                                sws->scaler_params);
         if (!c->cascaded_context[0]) {
             return AVERROR(ENOMEM);
         }
 
         c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFmt,
                                                 dstW, dstH, tmpFmt,
-                                                flags, srcFilter, dstFilter, c->param);
+                                                flags, srcFilter, dstFilter,
+                                                sws->scaler_params);
 
         if (!c->cascaded_context[1])
             return AVERROR(ENOMEM);
@@ -1668,8 +1676,9 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
                 return ret;
 
             c->cascaded_context[2] = sws_getContext(dstW, dstH, tmpFmt,
-                                                dstW, dstH, dstFormat,
-                                                flags, NULL, NULL, c->param);
+                                                    dstW, dstH, dstFormat,
+                                                    flags, NULL, NULL,
+                                                    sws->scaler_params);
             if (!c->cascaded_context[2])
                 return AVERROR(ENOMEM);
         }
@@ -1689,13 +1698,15 @@  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->param);
+                                                    flags, srcFilter, NULL,
+                                                    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->param);
+                                                    flags, NULL, dstFilter,
+                                                    sws->scaler_params);
             if (!c->cascaded_context[1])
                 return AVERROR(ENOMEM);
             return 0;
@@ -1718,11 +1729,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->alphablend != SWS_ALPHA_BLEND_NONE) {
+        if (tmpFormat != AV_PIX_FMT_NONE && sws->alpha_blend != SWS_ALPHA_BLEND_NONE) {
             if (!unscaled ||
                 dstFormat != tmpFormat ||
                 usesHFilter || usesVFilter ||
-                c->srcRange != c->dstRange
+                sws->src_range != sws->dst_range
             ) {
                 c->cascaded_mainindex = 1;
                 ret = av_image_alloc(c->cascaded_tmp[0], c->cascaded_tmpStride[0],
@@ -1732,22 +1743,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->param);
+                                                        flags, sws->scaler_params);
                 if (!c->cascaded_context[0])
                     return AVERROR(EINVAL);
-                sws_internal(c->cascaded_context[0])->alphablend = c->alphablend;
+                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->param);
+                                                        flags, sws->scaler_params);
                 if (!c->cascaded_context[1])
                     return AVERROR(EINVAL);
 
-                sws_internal(c->cascaded_context[1])->srcRange = c->srcRange;
-                sws_internal(c->cascaded_context[1])->dstRange = c->dstRange;
+                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;
@@ -1759,15 +1770,15 @@  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->alphablend != SWS_ALPHA_BLEND_NONE &&
+        sws->alpha_blend != SWS_ALPHA_BLEND_NONE &&
         isALPHA(srcFormat) &&
-        (c->srcRange == c->dstRange || isAnyRGB(dstFormat)) &&
+        (sws->src_range == sws->dst_range || isAnyRGB(dstFormat)) &&
         alphaless_fmt(srcFormat) == dstFormat
     ) {
         c->convert_unscaled = ff_sws_alphablendaway;
 
         if (flags & SWS_PRINT_INFO)
-            av_log(c, AV_LOG_INFO,
+            av_log(sws, AV_LOG_INFO,
                     "using alpha blendaway %s -> %s special converter\n",
                     av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
         return 0;
@@ -1775,14 +1786,14 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
 
     /* unscaled special cases */
     if (unscaled && !usesHFilter && !usesVFilter &&
-        (c->srcRange == c->dstRange || isAnyRGB(dstFormat) ||
+        (sws->src_range == sws->dst_range || isAnyRGB(dstFormat) ||
          isFloat(srcFormat) || isFloat(dstFormat) || isBayer(srcFormat))){
 
         ff_get_unscaled_swscale(c);
 
         if (c->convert_unscaled) {
             if (flags & SWS_PRINT_INFO)
-                av_log(c, AV_LOG_INFO,
+                av_log(sws, AV_LOG_INFO,
                        "using unscaled %s -> %s special converter\n",
                        av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
             return 0;
@@ -1834,7 +1845,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
             if (!c->lumMmxextFilterCode || !c->chrMmxextFilterCode)
 #endif
             {
-                av_log(c, AV_LOG_ERROR, "Failed to allocate MMX2FilterCode\n");
+                av_log(sws, AV_LOG_ERROR, "Failed to allocate MMX2FilterCode\n");
                 return AVERROR(ENOMEM);
             }
 
@@ -1852,7 +1863,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
 #if USE_MMAP
             if (   mprotect(c->lumMmxextFilterCode, c->lumMmxextFilterCodeSize, PROT_EXEC | PROT_READ) == -1
                 || mprotect(c->chrMmxextFilterCode, c->chrMmxextFilterCodeSize, PROT_EXEC | PROT_READ) == -1) {
-                av_log(c, AV_LOG_ERROR, "mprotect failed, cannot use fast bilinear scaler\n");
+                av_log(sws, AV_LOG_ERROR, "mprotect failed, cannot use fast bilinear scaler\n");
                 ret = AVERROR(EINVAL);
                 goto fail;
             }
@@ -1871,7 +1882,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->param,
+                           sws->scaler_params,
                            get_local_pos(c, 0, 0, 0),
                            get_local_pos(c, 0, 0, 0))) < 0)
                 goto fail;
@@ -1882,9 +1893,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->param,
-                           get_local_pos(c, c->chrSrcHSubSample, c->src_h_chr_pos, 0),
-                           get_local_pos(c, c->chrDstHSubSample, c->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;
@@ -1901,7 +1912,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->param,
+                       sws->scaler_params,
                        get_local_pos(c, 0, 0, 1),
                        get_local_pos(c, 0, 0, 1))) < 0)
             goto fail;
@@ -1910,18 +1921,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->param,
-                       get_local_pos(c, c->chrSrcVSubSample, c->src_v_chr_pos, 1),
-                       get_local_pos(c, c->chrDstVSubSample, c->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->dstH) ||
+        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->dstH; 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++)
@@ -1938,10 +1949,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->dstW + 3))
+        if (!FF_ALLOCZ_TYPED_ARRAY(c->dither_error[i], sws->dst_w + 3))
             goto nomem;
 
-    c->needAlpha = (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat)) ? 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);
@@ -1960,7 +1971,7 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
         }
         if (!scaler)
             scaler =  "ehh flags invalid?!";
-        av_log(c, AV_LOG_INFO, "%s scaler, from %s to %s%s ",
+        av_log(sws, AV_LOG_INFO, "%s scaler, from %s to %s%s ",
                scaler,
                av_get_pix_fmt_name(srcFormat),
                dstFormat == AV_PIX_FMT_BGR555   || dstFormat == AV_PIX_FMT_BGR565   ||
@@ -1978,13 +1989,13 @@  static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter
         else
             cpucaps = "C";
 
-        av_log(c, AV_LOG_INFO, "using %s\n", cpucaps);
+        av_log(sws, AV_LOG_INFO, "using %s\n", cpucaps);
 
-        av_log(c, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);
-        av_log(c, AV_LOG_DEBUG,
+        av_log(sws, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);
+        av_log(sws, AV_LOG_DEBUG,
                "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
-               c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc);
-        av_log(c, AV_LOG_DEBUG,
+               sws->src_w, sws->src_h, sws->dst_w, sws->dst_h, c->lumXInc, c->lumYInc);
+        av_log(sws, 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,
                c->chrXInc, c->chrYInc);
@@ -2014,13 +2025,15 @@  fail: // FIXME replace things by appropriate error codes
 
         c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat,
                                                 tmpW, tmpH, tmpFormat,
-                                                flags, srcFilter, NULL, c->param);
+                                                flags, srcFilter, NULL,
+                                                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->param);
+                                                flags, NULL, dstFilter,
+                                                sws->scaler_params);
         if (!c->cascaded_context[1])
             return AVERROR(ENOMEM);
         return 0;
@@ -2035,42 +2048,39 @@  static int context_init_threaded(SwsContext *sws,
     int ret;
 
     ret = avpriv_slicethread_create(&c->slicethread, (void*) sws,
-                                    ff_sws_slice_worker, NULL, c->nb_threads);
+                                    ff_sws_slice_worker, NULL, sws->threads);
     if (ret == AVERROR(ENOSYS)) {
-        c->nb_threads = 1;
+        sws->threads = 1;
         return 0;
     } else if (ret < 0)
         return ret;
 
-    c->nb_threads = ret;
+    sws->threads = ret;
 
-    c->slice_ctx = av_calloc(c->nb_threads, sizeof(*c->slice_ctx));
-    c->slice_err = av_calloc(c->nb_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->nb_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->nb_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->dither == SWS_DITHER_ED) {
-            av_log(c, AV_LOG_VERBOSE,
+        if (slice->dither == SWS_DITHER_ED) {
+            av_log(sws, AV_LOG_VERBOSE,
                    "Error-diffusion dither is in use, scaling will be single-threaded.");
             break;
         }
@@ -2095,17 +2105,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->srcFormat;
-    dst_format = c->dstFormat;
-    c->srcRange |= handle_jpeg(&c->srcFormat);
-    c->dstRange |= handle_jpeg(&c->dstFormat);
+    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->srcFormat || dst_format != c->dstFormat)
-        av_log(c, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n");
+    if (src_format != sws->src_format || dst_format != sws->dst_format)
+        av_log(sws, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n");
 
-    if (c->nb_threads != 1) {
+    if (sws->threads != 1) {
         ret = context_init_threaded(sws, srcFilter, dstFilter);
-        if (ret < 0 || c->nb_threads > 1)
+        if (ret < 0 || sws->threads > 1)
             return ret;
         // threading disabled in this build, init as single-threaded
     }
@@ -2517,6 +2527,7 @@  void sws_freeContext(SwsContext *sws)
 
     ff_free_filters(c);
 
+    av_free(c);
     av_free(sws);
 }
 
@@ -2530,7 +2541,7 @@  void sws_free_context(SwsContext **pctx)
     *pctx = NULL;
 }
 
-SwsContext *sws_getCachedContext(SwsContext *sws, int srcW,
+SwsContext *sws_getCachedContext(SwsContext *prev, int srcW,
                                  int srcH, enum AVPixelFormat srcFormat,
                                  int dstW, int dstH,
                                  enum AVPixelFormat dstFormat, int flags,
@@ -2538,59 +2549,48 @@  SwsContext *sws_getCachedContext(SwsContext *sws, int srcW,
                                  SwsFilter *dstFilter,
                                  const double *param)
 {
-    SwsInternal *context;
-
+    SwsContext *sws;
     static const double default_param[2] = { SWS_PARAM_DEFAULT,
                                              SWS_PARAM_DEFAULT };
-    int64_t src_h_chr_pos = -513, dst_h_chr_pos = -513,
-            src_v_chr_pos = -513, dst_v_chr_pos = -513;
 
     if (!param)
         param = default_param;
 
-    if ((context = sws_internal(sws)) &&
-        (context->srcW      != srcW      ||
-         context->srcH      != srcH      ||
-         context->srcFormat != srcFormat ||
-         context->dstW      != dstW      ||
-         context->dstH      != dstH      ||
-         context->dstFormat != dstFormat ||
-         context->flags     != flags     ||
-         context->param[0]  != param[0]  ||
-         context->param[1]  != param[1])) {
-
-        av_opt_get_int(context, "src_h_chr_pos", 0, &src_h_chr_pos);
-        av_opt_get_int(context, "src_v_chr_pos", 0, &src_v_chr_pos);
-        av_opt_get_int(context, "dst_h_chr_pos", 0, &dst_h_chr_pos);
-        av_opt_get_int(context, "dst_v_chr_pos", 0, &dst_v_chr_pos);
-        sws_freeContext(sws);
-        sws = NULL;
-    }
-
-    if (!sws) {
-        if (!(sws = sws_alloc_context()))
-            return NULL;
-        context            = sws_internal(sws);
-        context->srcW      = srcW;
-        context->srcH      = srcH;
-        context->srcFormat = srcFormat;
-        context->dstW      = dstW;
-        context->dstH      = dstH;
-        context->dstFormat = dstFormat;
-        context->flags     = flags;
-        context->param[0]  = param[0];
-        context->param[1]  = param[1];
-
-        av_opt_set_int(context, "src_h_chr_pos", src_h_chr_pos, 0);
-        av_opt_set_int(context, "src_v_chr_pos", src_v_chr_pos, 0);
-        av_opt_set_int(context, "dst_h_chr_pos", dst_h_chr_pos, 0);
-        av_opt_set_int(context, "dst_v_chr_pos", dst_v_chr_pos, 0);
-
-        if (sws_init_context(sws, srcFilter, dstFilter) < 0) {
-            sws_freeContext(sws);
-            return NULL;
-        }
+    if (prev && (prev->src_w            == srcW      ||
+                 prev->src_h            == srcH      ||
+                 prev->src_format       == srcFormat ||
+                 prev->dst_w            == dstW      ||
+                 prev->dst_h            == dstH      ||
+                 prev->dst_format       == dstFormat ||
+                 prev->flags            == flags     ||
+                 prev->scaler_params[0] == param[0]  ||
+                 prev->scaler_params[1] == param[1])) {
+        return prev;
+    }
+
+    if (!(sws = sws_alloc_context())) {
+        sws_free_context(&prev);
+        return NULL;
+    }
+
+    if (prev) {
+        av_opt_copy(sws, prev);
+        sws_free_context(&prev);
     }
+
+    sws->src_w            = srcW;
+    sws->src_h            = srcH;
+    sws->src_format       = srcFormat;
+    sws->dst_w            = dstW;
+    sws->dst_h            = dstH;
+    sws->dst_format       = dstFormat;
+    sws->flags            = flags;
+    sws->scaler_params[0] = param[0];
+    sws->scaler_params[1] = param[1];
+
+    if (sws_init_context(sws, srcFilter, dstFilter) < 0)
+        sws_free_context(&sws);
+
     return sws;
 }
 
diff --git a/libswscale/vscale.c b/libswscale/vscale.c
index 9b700ec58e..802cd48186 100644
--- a/libswscale/vscale.c
+++ b/libswscale/vscale.c
@@ -93,7 +93,7 @@  static int chr_planar_vscale(SwsInternal *c, SwsFilterDescriptor *desc, int slic
         uint16_t *filter = inst->filter[0] + (inst->isMMX ? 0 : chrSliceY * inst->filter_size);
 
         if (c->yuv2nv12cX) {
-            inst->pfn.yuv2interleavedX(c->dstFormat, c->chrDither8, filter, inst->filter_size, (const int16_t**)src1, (const int16_t**)src2, dst1[0], dstW);
+            inst->pfn.yuv2interleavedX(c->sws->dst_format, c->chrDither8, filter, inst->filter_size, (const int16_t**)src1, (const int16_t**)src2, dst1[0], dstW);
         } else if (inst->filter_size == 1) {
             inst->pfn.yuv2planar1((const int16_t*)src1[0], dst1[0], dstW, c->chrDither8, 0);
             inst->pfn.yuv2planar1((const int16_t*)src2[0], dst2[0], dstW, c->chrDither8, 3);
@@ -159,7 +159,7 @@  static int packed_vscale(SwsInternal *c, SwsFilterDescriptor *desc, int sliceY,
         if ((c->yuv2packed1 && lum_fsize == 1 && chr_fsize == 2) ||
             (c->yuv2packed2 && lum_fsize == 2 && chr_fsize == 2)) {
             if (!c->warned_unuseable_bilinear)
-                av_log(c, AV_LOG_INFO, "Optimized 2 tap filter code cannot be used\n");
+                av_log(c->sws, AV_LOG_INFO, "Optimized 2 tap filter code cannot be used\n");
             c->warned_unuseable_bilinear = 1;
         }
 
@@ -216,7 +216,7 @@  int ff_init_vscale(SwsInternal *c, SwsFilterDescriptor *desc, SwsSlice *src, Sws
     VScalerContext *lumCtx = NULL;
     VScalerContext *chrCtx = NULL;
 
-    if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) {
+    if (isPlanarYUV(c->sws->dst_format) || (isGray(c->sws->dst_format) && !isALPHA(c->sws->dst_format))) {
         lumCtx = av_mallocz(sizeof(VScalerContext));
         if (!lumCtx)
             return AVERROR(ENOMEM);
@@ -228,7 +228,7 @@  int ff_init_vscale(SwsInternal *c, SwsFilterDescriptor *desc, SwsSlice *src, Sws
         desc[0].dst = dst;
         desc[0].alpha = c->needAlpha;
 
-        if (!isGray(c->dstFormat)) {
+        if (!isGray(c->sws->dst_format)) {
             chrCtx = av_mallocz(sizeof(VScalerContext));
             if (!chrCtx)
                 return AVERROR(ENOMEM);
@@ -268,8 +268,8 @@  void ff_init_vscale_pfn(SwsInternal *c,
     VScalerContext *chrCtx = NULL;
     int idx = c->numDesc - (c->is_internal_gamma ? 2 : 1); //FIXME avoid hardcoding indexes
 
-    if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) {
-        if (!isGray(c->dstFormat)) {
+    if (isPlanarYUV(c->sws->dst_format) || (isGray(c->sws->dst_format) && !isALPHA(c->sws->dst_format))) {
+        if (!isGray(c->sws->dst_format)) {
             chrCtx = c->desc[idx].instance;
 
             chrCtx->filter[0] = use_mmx ? (int16_t*)c->chrMmxFilter : c->vChrFilter;
diff --git a/libswscale/x86/output.asm b/libswscale/x86/output.asm
index 0f854e521d..7a1e5d9bc1 100644
--- a/libswscale/x86/output.asm
+++ b/libswscale/x86/output.asm
@@ -582,7 +582,7 @@  yuv2nv12cX_fn yuv2nv21
 
 %if ARCH_X86_64
 struc SwsInternal
-    .padding:           resb 40292 ; offsetof(SwsInternal, yuv2rgb_y_offset)
+    .padding:           resb 40332 ; offsetof(SwsInternal, yuv2rgb_y_offset)
     .yuv2rgb_y_offset:  resd 1
     .yuv2rgb_y_coeff:   resd 1
     .yuv2rgb_v2r_coeff: resd 1
diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c
index 48f0aea3f2..fd19b4d1bf 100644
--- a/libswscale/x86/swscale.c
+++ b/libswscale/x86/swscale.c
@@ -63,8 +63,8 @@  DECLARE_ASM_ALIGNED(8, const uint64_t, ff_w1111)        = 0x0001000100010001ULL;
 
 void ff_updateMMXDitherTables(SwsInternal *c, int dstY)
 {
-    const int dstH= c->dstH;
-    const int flags= c->flags;
+    const int dstH= c->sws->dst_h;
+    const int flags= c->sws->flags;
 
     SwsPlane *lumPlane = &c->slice[c->numSlice-2].plane[0];
     SwsPlane *chrUPlane = &c->slice[c->numSlice-2].plane[1];
@@ -85,7 +85,7 @@  void ff_updateMMXDitherTables(SwsInternal *c, int dstY)
     const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input
 
     c->blueDither= ff_dither8[dstY&1];
-    if (c->dstFormat == AV_PIX_FMT_RGB555 || c->dstFormat == AV_PIX_FMT_BGR555)
+    if (c->sws->dst_format == AV_PIX_FMT_RGB555 || c->sws->dst_format == AV_PIX_FMT_BGR555)
         c->greenDither= ff_dither8[dstY&1];
     else
         c->greenDither= ff_dither4[dstY&1];
@@ -96,10 +96,10 @@  void ff_updateMMXDitherTables(SwsInternal *c, int dstY)
         const int16_t **alpSrcPtr  = (CONFIG_SWSCALE_ALPHA && hasAlpha) ? (const int16_t **)(void*) alpPlane->line + firstLumSrcY - alpPlane->sliceY : NULL;
 
         int i;
-        if (firstLumSrcY < 0 || firstLumSrcY + vLumFilterSize > c->srcH) {
+        if (firstLumSrcY < 0 || firstLumSrcY + vLumFilterSize > c->sws->src_h) {
             const int16_t **tmpY = (const int16_t **) lumPlane->tmp;
 
-            int neg = -firstLumSrcY, i, end = FFMIN(c->srcH - firstLumSrcY, vLumFilterSize);
+            int neg = -firstLumSrcY, i, end = FFMIN(c->sws->src_h - firstLumSrcY, vLumFilterSize);
             for (i = 0; i < neg;            i++)
                 tmpY[i] = lumSrcPtr[neg];
             for (     ; i < end;            i++)
@@ -453,7 +453,7 @@  INPUT_PLANAR_RGB_A_ALL_DECL(avx2);
 
 #define RANGE_CONVERT_FUNCS(opt) do {                                       \
     if (c->dstBpc <= 14) {                                                  \
-        if (c->srcRange) {                                                  \
+        if (c->sws->src_range) {                                            \
             c->lumConvertRange = ff_lumRangeFromJpeg_ ##opt;                \
             c->chrConvertRange = ff_chrRangeFromJpeg_ ##opt;                \
         } else {                                                            \
@@ -474,7 +474,7 @@  RANGE_CONVERT_FUNCS_DECL(avx2);
 
 av_cold void ff_sws_init_range_convert_x86(SwsInternal *c)
 {
-    if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
+    if (c->sws->src_range != c->sws->dst_range && !isAnyRGB(c->sws->dst_format)) {
         int cpu_flags = av_get_cpu_flags();
         if (EXTERNAL_AVX2_FAST(cpu_flags)) {
             RANGE_CONVERT_FUNCS(avx2);
@@ -492,7 +492,7 @@  av_cold void ff_sws_init_swscale_x86(SwsInternal *c)
     if (INLINE_MMXEXT(cpu_flags))
         sws_init_swscale_mmxext(c);
 #endif
-    if(c->use_mmx_vfilter && !(c->flags & SWS_ACCURATE_RND)) {
+    if(c->use_mmx_vfilter && !(c->sws->flags & SWS_ACCURATE_RND)) {
 #if HAVE_MMXEXT_EXTERNAL
         if (EXTERNAL_MMXEXT(cpu_flags))
             c->yuv2planeX = yuv2yuvX_mmxext;
@@ -528,7 +528,7 @@  av_cold void ff_sws_init_swscale_x86(SwsInternal *c)
     } else if (c->srcBpc == 12) { \
         hscalefn = c->dstBpc <= 14 ? ff_hscale12to15_ ## filtersize ## _ ## opt2 : \
                                      ff_hscale12to19_ ## filtersize ## _ ## opt1; \
-    } else if (c->srcBpc == 14 || ((c->srcFormat==AV_PIX_FMT_PAL8||isAnyRGB(c->srcFormat)) && av_pix_fmt_desc_get(c->srcFormat)->comp[0].depth<16)) { \
+    } else if (c->srcBpc == 14 || ((c->sws->src_format==AV_PIX_FMT_PAL8||isAnyRGB(c->sws->src_format)) && av_pix_fmt_desc_get(c->sws->src_format)->comp[0].depth<16)) { \
         hscalefn = c->dstBpc <= 14 ? ff_hscale14to15_ ## filtersize ## _ ## opt2 : \
                                      ff_hscale14to19_ ## filtersize ## _ ## opt1; \
     } else { /* c->srcBpc == 16 */ \
@@ -540,15 +540,15 @@  av_cold void ff_sws_init_swscale_x86(SwsInternal *c)
 #define ASSIGN_VSCALEX_FUNC(vscalefn, opt, do_16_case, condition_8bit) \
 switch(c->dstBpc){ \
     case 16:                          do_16_case;                          break; \
-    case 10: if (!isBE(c->dstFormat) && !isSemiPlanarYUV(c->dstFormat)) vscalefn = ff_yuv2planeX_10_ ## opt; break; \
-    case 9:  if (!isBE(c->dstFormat)) vscalefn = ff_yuv2planeX_9_  ## opt; break; \
+    case 10: if (!isBE(c->sws->dst_format) && !isSemiPlanarYUV(c->sws->dst_format)) vscalefn = ff_yuv2planeX_10_ ## opt; break; \
+    case 9:  if (!isBE(c->sws->dst_format)) vscalefn = ff_yuv2planeX_9_  ## opt; break; \
     case 8: if ((condition_8bit) && !c->use_mmx_vfilter) vscalefn = ff_yuv2planeX_8_  ## opt; break; \
     }
 #define ASSIGN_VSCALE_FUNC(vscalefn, opt) \
     switch(c->dstBpc){ \
-    case 16: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2plane1_16_ ## opt; break; \
-    case 10: if (!isBE(c->dstFormat) && !isSemiPlanarYUV(c->dstFormat)) vscalefn = ff_yuv2plane1_10_ ## opt; break; \
-    case 9:  if (!isBE(c->dstFormat)) vscalefn = ff_yuv2plane1_9_  ## opt;  break; \
+    case 16: if (!isBE(c->sws->dst_format)) vscalefn = ff_yuv2plane1_16_ ## opt; break; \
+    case 10: if (!isBE(c->sws->dst_format) && !isSemiPlanarYUV(c->sws->dst_format)) vscalefn = ff_yuv2plane1_10_ ## opt; break; \
+    case 9:  if (!isBE(c->sws->dst_format)) vscalefn = ff_yuv2plane1_9_  ## opt;  break; \
     case 8:                           vscalefn = ff_yuv2plane1_8_  ## opt;  break; \
     default: av_assert0(c->dstBpc>8); \
     }
@@ -571,10 +571,10 @@  switch(c->dstBpc){ \
         ASSIGN_SSE_SCALE_FUNC(c->hcScale, c->hChrFilterSize, sse2, sse2);
         ASSIGN_VSCALEX_FUNC(c->yuv2planeX, sse2, ,
                             HAVE_ALIGNED_STACK || ARCH_X86_64);
-        if (!(c->flags & SWS_ACCURATE_RND))
+        if (!(c->sws->flags & SWS_ACCURATE_RND))
             ASSIGN_VSCALE_FUNC(c->yuv2plane1, sse2);
 
-        switch (c->srcFormat) {
+        switch (c->sws->src_format) {
         case AV_PIX_FMT_YA8:
             c->lumToYV12 = ff_yuyvToY_sse2;
             if (c->needAlpha)
@@ -607,7 +607,7 @@  switch(c->dstBpc){ \
     if (EXTERNAL_SSSE3(cpu_flags)) {
         ASSIGN_SSE_SCALE_FUNC(c->hyScale, c->hLumFilterSize, ssse3, ssse3);
         ASSIGN_SSE_SCALE_FUNC(c->hcScale, c->hChrFilterSize, ssse3, ssse3);
-        switch (c->srcFormat) {
+        switch (c->sws->src_format) {
         case_rgb(rgb24, RGB24, ssse3);
         case_rgb(bgr24, BGR24, ssse3);
         default:
@@ -619,19 +619,19 @@  switch(c->dstBpc){ \
         ASSIGN_SSE_SCALE_FUNC(c->hyScale, c->hLumFilterSize, sse4, ssse3);
         ASSIGN_SSE_SCALE_FUNC(c->hcScale, c->hChrFilterSize, sse4, ssse3);
         ASSIGN_VSCALEX_FUNC(c->yuv2planeX, sse4,
-                            if (!isBE(c->dstFormat)) c->yuv2planeX = ff_yuv2planeX_16_sse4,
+                            if (!isBE(c->sws->dst_format)) c->yuv2planeX = ff_yuv2planeX_16_sse4,
                             HAVE_ALIGNED_STACK || ARCH_X86_64);
-        if (c->dstBpc == 16 && !isBE(c->dstFormat) && !(c->flags & SWS_ACCURATE_RND))
+        if (c->dstBpc == 16 && !isBE(c->sws->dst_format) && !(c->sws->flags & SWS_ACCURATE_RND))
             c->yuv2plane1 = ff_yuv2plane1_16_sse4;
     }
 
     if (EXTERNAL_AVX(cpu_flags)) {
         ASSIGN_VSCALEX_FUNC(c->yuv2planeX, avx, ,
                             HAVE_ALIGNED_STACK || ARCH_X86_64);
-        if (!(c->flags & SWS_ACCURATE_RND))
+        if (!(c->sws->flags & SWS_ACCURATE_RND))
             ASSIGN_VSCALE_FUNC(c->yuv2plane1, avx);
 
-        switch (c->srcFormat) {
+        switch (c->sws->src_format) {
         case AV_PIX_FMT_YUYV422:
             c->chrToYV12 = ff_yuyvToUV_avx;
             break;
@@ -672,7 +672,7 @@  switch(c->dstBpc){ \
 
     if (EXTERNAL_AVX2_FAST(cpu_flags)) {
         if (ARCH_X86_64)
-            switch (c->srcFormat) {
+            switch (c->sws->src_format) {
             case_rgb(rgb24, RGB24, avx2);
             case_rgb(bgr24, BGR24, avx2);
             case_rgb(bgra,  BGRA,  avx2);
@@ -680,7 +680,7 @@  switch(c->dstBpc){ \
             case_rgb(abgr,  ABGR,  avx2);
             case_rgb(argb,  ARGB,  avx2);
             }
-        switch (c->dstFormat) {
+        switch (c->sws->dst_format) {
         case AV_PIX_FMT_NV12:
         case AV_PIX_FMT_NV24:
             c->yuv2nv12cX = ff_yuv2nv12cX_avx2;
@@ -753,7 +753,7 @@  switch(c->dstBpc){ \
 
 
     if (EXTERNAL_SSE2(cpu_flags)) {
-        switch (c->srcFormat) {
+        switch (c->sws->src_format) {
         INPUT_PLANER_RGB_A_FUNC_CASE_NOBREAK(AV_PIX_FMT_GBRAP,                         rgb, sse2);
         INPUT_PLANER_RGB_UV_FUNC_CASE(     AV_PIX_FMT_GBRP,                            rgb, sse2);
         INPUT_PLANER_RGBXX_UV_FUNC_CASE(   AV_PIX_FMT_GBRP9,                          rgb9, sse2);
@@ -768,7 +768,7 @@  switch(c->dstBpc){ \
     }
 
     if (EXTERNAL_SSE4(cpu_flags)) {
-        switch (c->srcFormat) {
+        switch (c->sws->src_format) {
         case AV_PIX_FMT_GBRAP:
         INPUT_PLANER_RGB_YUV_FUNC_CASE(    AV_PIX_FMT_GBRP,                            rgb, sse4);
         INPUT_PLANER_RGBXX_YUV_FUNC_CASE(  AV_PIX_FMT_GBRP9,                          rgb9, sse4);
@@ -783,14 +783,14 @@  switch(c->dstBpc){ \
     }
 
     if (EXTERNAL_AVX2_FAST(cpu_flags)) {
-        switch (c->srcFormat) {
+        switch (c->sws->src_format) {
         INPUT_PLANER_RGB_YUVA_ALL_CASES(avx2)
         default:
             break;
         }
     }
 
-    if(c->flags & SWS_FULL_CHR_H_INT) {
+    if(c->sws->flags & SWS_FULL_CHR_H_INT) {
 
 #define YUV2ANYX_FUNC_CASE(fmt, name, opt)              \
         case fmt:                                       \
@@ -822,7 +822,7 @@  switch(c->dstBpc){ \
         YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAPF32BE, gbrapf32be, opt)
 
         if (EXTERNAL_SSE2(cpu_flags)) {
-            switch (c->dstFormat) {
+            switch (c->sws->dst_format) {
             YUV2ANYX_GBRAP_CASES(sse2)
             default:
                 break;
@@ -830,7 +830,7 @@  switch(c->dstBpc){ \
         }
 
         if (EXTERNAL_SSE4(cpu_flags)) {
-            switch (c->dstFormat) {
+            switch (c->sws->dst_format) {
             YUV2ANYX_GBRAP_CASES(sse4)
             default:
                 break;
@@ -838,7 +838,7 @@  switch(c->dstBpc){ \
         }
 
         if (EXTERNAL_AVX2_FAST(cpu_flags)) {
-            switch (c->dstFormat) {
+            switch (c->sws->dst_format) {
             YUV2ANYX_GBRAP_CASES(avx2)
             default:
                 break;
diff --git a/libswscale/x86/swscale_template.c b/libswscale/x86/swscale_template.c
index cffafccb24..d57d1dba0d 100644
--- a/libswscale/x86/swscale_template.c
+++ b/libswscale/x86/swscale_template.c
@@ -1384,15 +1384,15 @@  static void RENAME(yuv2yuyv422_1)(SwsInternal *c, const int16_t *buf0,
 }
 static av_cold void RENAME(sws_init_swscale)(SwsInternal *c)
 {
-    enum AVPixelFormat dstFormat = c->dstFormat;
+    enum AVPixelFormat dstFormat = c->sws->dst_format;
 
     c->use_mmx_vfilter= 0;
     if (!is16BPS(dstFormat) && !isNBPS(dstFormat) && !isSemiPlanarYUV(dstFormat)
         && dstFormat != AV_PIX_FMT_GRAYF32BE && dstFormat != AV_PIX_FMT_GRAYF32LE
-        && !(c->flags & SWS_BITEXACT)) {
-            if (c->flags & SWS_ACCURATE_RND) {
-                if (!(c->flags & SWS_FULL_CHR_H_INT)) {
-                    switch (c->dstFormat) {
+        && !(c->sws->flags & SWS_BITEXACT)) {
+            if (c->sws->flags & SWS_ACCURATE_RND) {
+                if (!(c->sws->flags & SWS_FULL_CHR_H_INT)) {
+                    switch (c->sws->dst_format) {
                     case AV_PIX_FMT_RGB32:   c->yuv2packedX = RENAME(yuv2rgb32_X_ar);   break;
 #if HAVE_6REGS
                     case AV_PIX_FMT_BGR24:   c->yuv2packedX = RENAME(yuv2bgr24_X_ar);   break;
@@ -1405,8 +1405,8 @@  static av_cold void RENAME(sws_init_swscale)(SwsInternal *c)
                 }
             } else {
                 c->use_mmx_vfilter= 1;
-                if (!(c->flags & SWS_FULL_CHR_H_INT)) {
-                    switch (c->dstFormat) {
+                if (!(c->sws->flags & SWS_FULL_CHR_H_INT)) {
+                    switch (c->sws->dst_format) {
                     case AV_PIX_FMT_RGB32:   c->yuv2packedX = RENAME(yuv2rgb32_X);   break;
                     case AV_PIX_FMT_BGR32:   c->yuv2packedX = RENAME(yuv2bgr32_X);   break;
 #if HAVE_6REGS
@@ -1419,8 +1419,8 @@  static av_cold void RENAME(sws_init_swscale)(SwsInternal *c)
                     }
                 }
             }
-        if (!(c->flags & SWS_FULL_CHR_H_INT)) {
-            switch (c->dstFormat) {
+        if (!(c->sws->flags & SWS_FULL_CHR_H_INT)) {
+            switch (c->sws->dst_format) {
             case AV_PIX_FMT_RGB32:
                 c->yuv2packed1 = RENAME(yuv2rgb32_1);
                 c->yuv2packed2 = RENAME(yuv2rgb32_2);
@@ -1449,7 +1449,7 @@  static av_cold void RENAME(sws_init_swscale)(SwsInternal *c)
 
     if (c->srcBpc == 8 && c->dstBpc <= 14) {
         // Use the new MMX scaler if the MMXEXT one can't be used (it is faster than the x86 ASM one).
-        if (c->flags & SWS_FAST_BILINEAR && c->canMMXEXTBeUsed) {
+        if (c->sws->flags & SWS_FAST_BILINEAR && c->canMMXEXTBeUsed) {
             c->hyscale_fast = ff_hyscale_fast_mmxext;
             c->hcscale_fast = ff_hcscale_fast_mmxext;
         } else {
diff --git a/libswscale/x86/yuv2rgb.c b/libswscale/x86/yuv2rgb.c
index 93a6b9a6e2..b1ea493fed 100644
--- a/libswscale/x86/yuv2rgb.c
+++ b/libswscale/x86/yuv2rgb.c
@@ -41,11 +41,11 @@ 
 #if HAVE_X86ASM
 
 #define YUV2RGB_LOOP(depth)                                          \
-    h_size = (c->dstW + 7) & ~7;                                     \
+    h_size = (c->sws->dst_w + 7) & ~7;                               \
     if (h_size * depth > FFABS(dstStride[0]))                        \
         h_size -= 8;                                                 \
                                                                      \
-    vshift = c->srcFormat != AV_PIX_FMT_YUV422P;                     \
+    vshift = c->sws->src_format != AV_PIX_FMT_YUV422P;               \
                                                                      \
     for (y = 0; y < srcSliceH; y++) {                                \
         uint8_t *image    = dst[0] + (y + srcSliceY) * dstStride[0]; \
@@ -215,11 +215,11 @@  static inline int yuv420_gbrp_ssse3(SwsInternal *c, const uint8_t *const src[],
 {
     int y, h_size, vshift;
 
-    h_size = (c->dstW + 7) & ~7;
+    h_size = (c->sws->dst_w + 7) & ~7;
     if (h_size * 3 > FFABS(dstStride[0]))
         h_size -= 8;
 
-    vshift = c->srcFormat != AV_PIX_FMT_YUV422P;
+    vshift = c->sws->src_format != AV_PIX_FMT_YUV422P;
 
     for (y = 0; y < srcSliceH; y++) {
         uint8_t *dst_g    = dst[0] + (y + srcSliceY) * dstStride[0];
@@ -244,9 +244,9 @@  av_cold SwsFunc ff_yuv2rgb_init_x86(SwsInternal *c)
     int cpu_flags = av_get_cpu_flags();
 
     if (EXTERNAL_SSSE3(cpu_flags)) {
-        switch (c->dstFormat) {
+        switch (c->sws->dst_format) {
         case AV_PIX_FMT_RGB32:
-            if (c->srcFormat == AV_PIX_FMT_YUVA420P) {
+            if (c->sws->src_format == AV_PIX_FMT_YUVA420P) {
 #if CONFIG_SWSCALE_ALPHA
                 return yuva420_rgb32_ssse3;
 #endif
@@ -254,7 +254,7 @@  av_cold SwsFunc ff_yuv2rgb_init_x86(SwsInternal *c)
             } else
                 return yuv420_rgb32_ssse3;
         case AV_PIX_FMT_BGR32:
-            if (c->srcFormat == AV_PIX_FMT_YUVA420P) {
+            if (c->sws->src_format == AV_PIX_FMT_YUVA420P) {
 #if CONFIG_SWSCALE_ALPHA
                 return yuva420_bgr32_ssse3;
 #endif
diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c
index f4fa1c0549..51e5408bee 100644
--- a/libswscale/yuv2rgb.c
+++ b/libswscale/yuv2rgb.c
@@ -155,7 +155,7 @@  const int *sws_getCoefficients(int colorspace)
             const uint8_t av_unused *pv_1 = src[2] + (y >> !yuv422) * srcStride[2]; \
             const uint8_t av_unused *pu_2, *pv_2;                           \
             const uint8_t av_unused *pa_1, *pa_2;                           \
-            unsigned int h_size = c->dstW >> 3;                             \
+            unsigned int h_size = c->sws->dst_w >> 3;                       \
             if (nb_dst_planes > 1) {                                        \
                 dst1_1 = (dst_type *)(dst[1] + (yd)     * dstStride[1]);    \
                 dst1_2 = (dst_type *)(dst[1] + (yd + 1) * dstStride[1]);    \
@@ -195,7 +195,7 @@  const int *sws_getCoefficients(int colorspace)
         dst2_2 += dst_delta >> ss;                  \
     }                                               \
     }                                               \
-    if (c->dstW & (4 >> ss)) {                      \
+    if (c->sws->dst_w & (4 >> ss)) {                \
         int av_unused Y, U, V;                      \
 
 #define ENDYUV2RGBFUNC()                            \
@@ -485,9 +485,9 @@  YUV2RGBFUNC(yuv2rgb_c_1_ordered_dither, uint8_t, 0, 0, 1)
     dst_1 += 1;
     dst_2 += 1;
     }
-    if (c->dstW & 7) {
+    if (c->sws->dst_w & 7) {
         int av_unused Y, U, V;
-        int pixels_left = c->dstW & 7;
+        int pixels_left = c->sws->dst_w & 7;
     const uint8_t *d128 = ff_dither_8x8_220[yd & 7];
     char out_1 = 0, out_2 = 0;
     g = c->table_gU[128 + YUVRGB_TABLE_HEADROOM] + c->table_gV[128 + YUVRGB_TABLE_HEADROOM];
@@ -573,12 +573,12 @@  SwsFunc ff_yuv2rgb_get_func_ptr(SwsInternal *c)
     if (t)
         return t;
 
-    av_log(c, AV_LOG_WARNING,
+    av_log(c->sws, AV_LOG_WARNING,
            "No accelerated colorspace conversion found from %s to %s.\n",
-           av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
+           av_get_pix_fmt_name(c->sws->src_format), av_get_pix_fmt_name(c->sws->dst_format));
 
-    if (c->srcFormat == AV_PIX_FMT_YUV422P) {
-        switch (c->dstFormat) {
+    if (c->sws->src_format == AV_PIX_FMT_YUV422P) {
+        switch (c->sws->dst_format) {
         case AV_PIX_FMT_BGR48BE:
         case AV_PIX_FMT_BGR48LE:
             return yuv422p_bgr48_c;
@@ -587,11 +587,11 @@  SwsFunc ff_yuv2rgb_get_func_ptr(SwsInternal *c)
             return yuv422p_rgb48_c;
         case AV_PIX_FMT_ARGB:
         case AV_PIX_FMT_ABGR:
-            if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat))
+            if (CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format))
                 return yuva422p_argb_c;
         case AV_PIX_FMT_RGBA:
         case AV_PIX_FMT_BGRA:
-            return (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) ? yuva422p_rgba_c : yuv422p_rgb32_c;
+            return (CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format)) ? yuva422p_rgba_c : yuv422p_rgb32_c;
         case AV_PIX_FMT_RGB24:
             return yuv422p_rgb24_c;
         case AV_PIX_FMT_BGR24:
@@ -620,7 +620,7 @@  SwsFunc ff_yuv2rgb_get_func_ptr(SwsInternal *c)
             return yuv422p_gbrp_c;
         }
     } else {
-        switch (c->dstFormat) {
+        switch (c->sws->dst_format) {
         case AV_PIX_FMT_BGR48BE:
         case AV_PIX_FMT_BGR48LE:
             return yuv2rgb_c_bgr48;
@@ -629,11 +629,11 @@  SwsFunc ff_yuv2rgb_get_func_ptr(SwsInternal *c)
             return yuv2rgb_c_48;
         case AV_PIX_FMT_ARGB:
         case AV_PIX_FMT_ABGR:
-            if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat))
+            if (CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format))
                 return yuva2argb_c;
         case AV_PIX_FMT_RGBA:
         case AV_PIX_FMT_BGRA:
-            return (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) ? yuva2rgba_c : yuv2rgb_c_32;
+            return (CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format)) ? yuva2rgba_c : yuv2rgb_c_32;
         case AV_PIX_FMT_RGB24:
             return yuv2rgb_c_24_rgb;
         case AV_PIX_FMT_BGR24:
@@ -706,29 +706,29 @@  av_cold int ff_yuv2rgb_c_init_tables(SwsInternal *c, const int inv_table[4],
                                      int fullRange, int brightness,
                                      int contrast, int saturation)
 {
-    const int isRgb = c->dstFormat == AV_PIX_FMT_RGB32     ||
-                      c->dstFormat == AV_PIX_FMT_RGB32_1   ||
-                      c->dstFormat == AV_PIX_FMT_BGR24     ||
-                      c->dstFormat == AV_PIX_FMT_RGB565BE  ||
-                      c->dstFormat == AV_PIX_FMT_RGB565LE  ||
-                      c->dstFormat == AV_PIX_FMT_RGB555BE  ||
-                      c->dstFormat == AV_PIX_FMT_RGB555LE  ||
-                      c->dstFormat == AV_PIX_FMT_RGB444BE  ||
-                      c->dstFormat == AV_PIX_FMT_RGB444LE  ||
-                      c->dstFormat == AV_PIX_FMT_X2RGB10BE ||
-                      c->dstFormat == AV_PIX_FMT_X2RGB10LE ||
-                      c->dstFormat == AV_PIX_FMT_RGB8      ||
-                      c->dstFormat == AV_PIX_FMT_RGB4      ||
-                      c->dstFormat == AV_PIX_FMT_RGB4_BYTE ||
-                      c->dstFormat == AV_PIX_FMT_MONOBLACK;
-    const int isNotNe = c->dstFormat == AV_PIX_FMT_NE(RGB565LE, RGB565BE) ||
-                        c->dstFormat == AV_PIX_FMT_NE(RGB555LE, RGB555BE) ||
-                        c->dstFormat == AV_PIX_FMT_NE(RGB444LE, RGB444BE) ||
-                        c->dstFormat == AV_PIX_FMT_NE(BGR565LE, BGR565BE) ||
-                        c->dstFormat == AV_PIX_FMT_NE(BGR555LE, BGR555BE) ||
-                        c->dstFormat == AV_PIX_FMT_NE(BGR444LE, BGR444BE) ||
-                        c->dstFormat == AV_PIX_FMT_NE(X2RGB10LE, X2RGB10BE) ||
-                        c->dstFormat == AV_PIX_FMT_NE(X2BGR10LE, X2BGR10BE);
+    const int isRgb = c->sws->dst_format == AV_PIX_FMT_RGB32     ||
+                      c->sws->dst_format == AV_PIX_FMT_RGB32_1   ||
+                      c->sws->dst_format == AV_PIX_FMT_BGR24     ||
+                      c->sws->dst_format == AV_PIX_FMT_RGB565BE  ||
+                      c->sws->dst_format == AV_PIX_FMT_RGB565LE  ||
+                      c->sws->dst_format == AV_PIX_FMT_RGB555BE  ||
+                      c->sws->dst_format == AV_PIX_FMT_RGB555LE  ||
+                      c->sws->dst_format == AV_PIX_FMT_RGB444BE  ||
+                      c->sws->dst_format == AV_PIX_FMT_RGB444LE  ||
+                      c->sws->dst_format == AV_PIX_FMT_X2RGB10BE ||
+                      c->sws->dst_format == AV_PIX_FMT_X2RGB10LE ||
+                      c->sws->dst_format == AV_PIX_FMT_RGB8      ||
+                      c->sws->dst_format == AV_PIX_FMT_RGB4      ||
+                      c->sws->dst_format == AV_PIX_FMT_RGB4_BYTE ||
+                      c->sws->dst_format == AV_PIX_FMT_MONOBLACK;
+    const int isNotNe = c->sws->dst_format == AV_PIX_FMT_NE(RGB565LE, RGB565BE) ||
+                        c->sws->dst_format == AV_PIX_FMT_NE(RGB555LE, RGB555BE) ||
+                        c->sws->dst_format == AV_PIX_FMT_NE(RGB444LE, RGB444BE) ||
+                        c->sws->dst_format == AV_PIX_FMT_NE(BGR565LE, BGR565BE) ||
+                        c->sws->dst_format == AV_PIX_FMT_NE(BGR555LE, BGR555BE) ||
+                        c->sws->dst_format == AV_PIX_FMT_NE(BGR444LE, BGR444BE) ||
+                        c->sws->dst_format == AV_PIX_FMT_NE(X2RGB10LE, X2RGB10BE) ||
+                        c->sws->dst_format == AV_PIX_FMT_NE(X2BGR10LE, X2BGR10BE);
     const int bpp = c->dstFormatBpp;
     uint8_t *y_table;
     uint16_t *y_table16;
@@ -904,7 +904,7 @@  av_cold int ff_yuv2rgb_c_init_tables(SwsInternal *c, const int inv_table[4],
         rbase = isRgb ? 20 : 0;
         gbase = 10;
         bbase = isRgb ? 0 : 20;
-        needAlpha = CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat);
+        needAlpha = CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format);
         if (!needAlpha)
             abase = 30;
         ALLOC_YUV_TABLE(table_plane_size * 3 * 4);
@@ -928,12 +928,12 @@  av_cold int ff_yuv2rgb_c_init_tables(SwsInternal *c, const int inv_table[4],
         break;
     case 32:
     case 64:
-        base      = (c->dstFormat == AV_PIX_FMT_RGB32_1 ||
-                     c->dstFormat == AV_PIX_FMT_BGR32_1) ? 8 : 0;
+        base      = (c->sws->dst_format == AV_PIX_FMT_RGB32_1 ||
+                     c->sws->dst_format == AV_PIX_FMT_BGR32_1) ? 8 : 0;
         rbase     = base + (isRgb ? 16 : 0);
         gbase     = base + 8;
         bbase     = base + (isRgb ? 0 : 16);
-        needAlpha = CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat);
+        needAlpha = CONFIG_SWSCALE_ALPHA && isALPHA(c->sws->src_format);
         if (!needAlpha)
             abase = (base + 24) & 31;
         ALLOC_YUV_TABLE(table_plane_size * 3 * 4);
@@ -953,8 +953,8 @@  av_cold int ff_yuv2rgb_c_init_tables(SwsInternal *c, const int inv_table[4],
         fill_gv_table(c->table_gV, 4, cgv);
         break;
     default:
-        if(!isPlanar(c->dstFormat) || bpp <= 24)
-            av_log(c, AV_LOG_ERROR, "%ibpp not supported by yuv2rgb\n", bpp);
+        if(!isPlanar(c->sws->dst_format) || bpp <= 24)
+            av_log(c->sws, AV_LOG_ERROR, "%ibpp not supported by yuv2rgb\n", bpp);
         return AVERROR(EINVAL);
     }
     return 0;
diff --git a/tests/checkasm/sw_gbrp.c b/tests/checkasm/sw_gbrp.c
index 039be8006b..18b72be250 100644
--- a/tests/checkasm/sw_gbrp.c
+++ b/tests/checkasm/sw_gbrp.c
@@ -136,13 +136,13 @@  static void check_output_yuv2gbrp(void)
         fail();
 
     c = sws_internal(sws);
-    c->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 < INPUT_SIZES; isi++ ) {
                 desc = av_pix_fmt_desc_get(planar_fmts[fmi]);
-                c->dstFormat = planar_fmts[fmi];
+                sws->dst_format = planar_fmts[fmi];
 
                 dstW = input_sizes[isi];
                 luma_filter_size = filter_sizes[fsi];
@@ -232,8 +232,8 @@  static void check_input_planar_rgb_to_y(void)
     for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) {
         for (isi = 0; isi < INPUT_SIZES; isi++ ) {
             desc = av_pix_fmt_desc_get(planar_fmts[fmi]);
-            c->srcFormat = planar_fmts[fmi];
-            c->dstFormat = AV_PIX_FMT_YUVA444P16;
+            sws->src_format = planar_fmts[fmi];
+            sws->dst_format = AV_PIX_FMT_YUVA444P16;
             byte_size = 2;
             dstW = input_sizes[isi];
 
@@ -305,8 +305,8 @@  static void check_input_planar_rgb_to_uv(void)
     for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) {
         for (isi = 0; isi < INPUT_SIZES; isi++ ) {
             desc = av_pix_fmt_desc_get(planar_fmts[fmi]);
-            c->srcFormat = planar_fmts[fmi];
-            c->dstFormat = AV_PIX_FMT_YUVA444P16;
+            sws->src_format = planar_fmts[fmi];
+            sws->dst_format = AV_PIX_FMT_YUVA444P16;
             byte_size = 2;
             dstW = input_sizes[isi];
 
@@ -380,8 +380,8 @@  static void check_input_planar_rgb_to_a(void)
             if (!(desc->flags & AV_PIX_FMT_FLAG_ALPHA))
                 continue;
 
-            c->srcFormat = planar_fmts[fmi];
-            c->dstFormat = 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 7da29b896e..fcc6f75e54 100644
--- a/tests/checkasm/sw_range_convert.c
+++ b/tests/checkasm/sw_range_convert.c
@@ -47,10 +47,10 @@  static void check_lumConvertRange(int from)
         fail();
 
     c = sws_internal(sws);
-    c->srcFormat = from ? AV_PIX_FMT_YUVJ444P : AV_PIX_FMT_YUV444P;
-    c->dstFormat = from ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P;
-    c->srcRange = from;
-    c->dstRange = !from;
+    sws->src_format = from ? AV_PIX_FMT_YUVJ444P : AV_PIX_FMT_YUV444P;
+    sws->dst_format = from ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P;
+    sws->src_range = from;
+    sws->dst_range = !from;
 
     for (int dstWi = 0; dstWi < INPUT_SIZES; dstWi++) {
         int width = input_sizes[dstWi];
@@ -95,10 +95,10 @@  static void check_chrConvertRange(int from)
         fail();
 
     c = sws_internal(sws);
-    c->srcFormat = from ? AV_PIX_FMT_YUVJ444P : AV_PIX_FMT_YUV444P;
-    c->dstFormat = from ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P;
-    c->srcRange = from;
-    c->dstRange = !from;
+    sws->src_format = from ? AV_PIX_FMT_YUVJ444P : AV_PIX_FMT_YUV444P;
+    sws->dst_format = from ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P;
+    sws->src_range = from;
+    sws->dst_range = !from;
 
     for (int dstWi = 0; dstWi < INPUT_SIZES; dstWi++) {
         int width = input_sizes[dstWi];
diff --git a/tests/checkasm/sw_rgb.c b/tests/checkasm/sw_rgb.c
index 7af82f0fc7..cd8c3fce55 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->srcFormat = 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->srcFormat == AV_PIX_FMT_RGB32 || ctx->srcFormat == 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->srcFormat = src_fmt;
-        ctx->dstFormat = 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->srcFormat == AV_PIX_FMT_RGB32 || ctx->srcFormat == 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);
             }
         }
@@ -485,14 +490,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 b383fa0930..f9be390695 100644
--- a/tests/checkasm/sw_scale.c
+++ b/tests/checkasm/sw_scale.c
@@ -124,12 +124,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->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 < INPUT_SIZES; ++isi) {
         dstW = input_sizes[isi];
@@ -192,12 +192,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->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 < INPUT_SIZES; ++isi){
         dstW = input_sizes[isi];
@@ -344,20 +344,20 @@  static void check_hscale(void)
 
                     filter[SRC_PIXELS * width + i] = rnd();
                 }
-                c->dstW = 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->dstW);
+                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->dstW)) {
+                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->dstW, src, filter, filterPos, width);
-                    call_new(NULL, dst1, c->dstW, src, filterAvx2, filterPosAvx, width);
-                    if (memcmp(dst0, dst1, c->dstW * 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->dstW, src, filter, filterPosAvx, width);
+                    bench_new(NULL, dst0, sws->dst_w, src, filter, filterPosAvx, width);
                 }
             }
         }