diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 350f233ab7..a52a5e1956 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -1173,6 +1173,21 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
         (o->data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA))
             ist->user_set_discard = AVDISCARD_ALL;
 
+    if (ist->hwaccel_device_type == AV_HWDEVICE_TYPE_CUDA && ist->dec->type == AVMEDIA_TYPE_VIDEO &&
+            (av_strcasecmp(ist->dec->name, "rawvideo") != 0) && (!ist->dec->wrapper_name || av_strcasecmp(ist->dec->wrapper_name, "cuvid") != 0)) {
+        const char *cuvid_suffix = "_cuvid";
+        size_t cuvid_length = av_strnlen(ist->dec->name, 64) + av_strnlen(cuvid_suffix, 64) + 1;
+        char *cuvid_name = (char*)av_malloc(cuvid_length);
+        if (cuvid_name) {
+            av_strlcpy(cuvid_name, ist->dec->name, cuvid_length);
+            av_strlcat(cuvid_name, cuvid_suffix, cuvid_length);
+            const AVCodec *cuvid_codec = avcodec_find_decoder_by_name(cuvid_name);
+            if (cuvid_codec) {
+                ist->dec = cuvid_codec;
+            }
+            av_free(cuvid_name);
+        }
+    }
     ist->dec_ctx = avcodec_alloc_context3(ist->dec);
     if (!ist->dec_ctx)
         return AVERROR(ENOMEM);
diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c
index da37207cf2..7449d8391b 100644
--- a/libavcodec/cuviddec.c
+++ b/libavcodec/cuviddec.c
@@ -66,6 +66,7 @@ typedef struct CuvidContext
     int drop_second_field;
     char *crop_expr;
     char *resize_expr;
+    char* csc_fmt;
 
     struct {
         int left;
@@ -191,6 +192,14 @@ static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* form
     default:
         break;
     }
+    if (ctx->csc_fmt) {
+        if (strcmp(ctx->csc_fmt, "rgb24") == 0) {
+            pix_fmts[1] = AV_PIX_FMT_RGB24;
+        }
+        else if (strcmp(ctx->csc_fmt, "bgr24") == 0) {
+            pix_fmts[1] = AV_PIX_FMT_BGR24;
+        }
+    }
 
     if (!caps || !caps->bIsSupported) {
         av_log(avctx, AV_LOG_ERROR, "unsupported bit depth: %d\n",
@@ -309,6 +318,12 @@ static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* form
     case AV_PIX_FMT_YUV444P16:
         cuinfo.OutputFormat = cudaVideoSurfaceFormat_YUV444_16Bit;
         break;
+    case AV_PIX_FMT_RGB24:
+        cuinfo.OutputFormat = 17;
+        break;
+    case AV_PIX_FMT_BGR24:
+        cuinfo.OutputFormat = 18;
+        break;
     default:
         av_log(avctx, AV_LOG_ERROR, "Unsupported output format: %s\n",
                av_get_pix_fmt_name(avctx->sw_pix_fmt));
@@ -1136,6 +1151,7 @@ static const AVOption options[] = {
     { "drop_second_field", "Drop second field when deinterlacing", OFFSET(drop_second_field), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD },
     { "crop",     "Crop (top)x(bottom)x(left)x(right)", OFFSET(crop_expr), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VD },
     { "resize",   "Resize (width)x(height)", OFFSET(resize_expr), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VD },
+    { "csc",      "Color space conversion format, currently supports rgb2, bgr24", OFFSET(csc_fmt), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VD },
     { NULL }
 };
 
diff --git a/libavfilter/vf_scale_npp.c b/libavfilter/vf_scale_npp.c
index 3cfead82bf..7c9c5fc34c 100644
--- a/libavfilter/vf_scale_npp.c
+++ b/libavfilter/vf_scale_npp.c
@@ -170,6 +170,7 @@ typedef struct NPPScaleContext {
     double var_values[VARS_NB];
 
     int eval_mode;
+    NppStreamContext nppStreamCtx;
 } NPPScaleContext;
 
 const AVFilter ff_vf_scale2ref_npp;
@@ -703,14 +704,17 @@ static int nppscale_deinterleave(AVFilterContext *ctx, NPPScaleStageContext *sta
                                  AVFrame *out, AVFrame *in)
 {
     AVHWFramesContext *in_frames_ctx = (AVHWFramesContext*)in->hw_frames_ctx->data;
+    NPPScaleContext               *s = ctx->priv;
     NppStatus err;
 
+
     switch (in_frames_ctx->sw_format) {
     case AV_PIX_FMT_NV12:
-        err = nppiYCbCr420_8u_P2P3R(in->data[0], in->linesize[0],
-                                    in->data[1], in->linesize[1],
-                                    out->data, out->linesize,
-                                    (NppiSize){ in->width, in->height });
+        err = nppiYCbCr420_8u_P2P3R_Ctx(in->data[0], in->linesize[0],
+                                        in->data[1], in->linesize[1],
+                                        out->data, out->linesize,
+                                        (NppiSize){ in->width, in->height },
+                                        s->nppStreamCtx);
         break;
     default:
         return AVERROR_BUG;
@@ -736,12 +740,13 @@ static int nppscale_resize(AVFilterContext *ctx, NPPScaleStageContext *stage,
         int ow = stage->planes_out[i].width;
         int oh = stage->planes_out[i].height;
 
-        err = nppiResizeSqrPixel_8u_C1R(in->data[i], (NppiSize){ iw, ih },
-                                        in->linesize[i], (NppiRect){ 0, 0, iw, ih },
-                                        out->data[i], out->linesize[i],
-                                        (NppiRect){ 0, 0, ow, oh },
-                                        (double)ow / iw, (double)oh / ih,
-                                        0.0, 0.0, s->interp_algo);
+        err = nppiResizeSqrPixel_8u_C1R_Ctx(in->data[i], (NppiSize){ iw, ih },
+                                            in->linesize[i], (NppiRect){ 0, 0, iw, ih },
+                                            out->data[i], out->linesize[i],
+                                            (NppiRect){ 0, 0, ow, oh },
+                                            (double)ow / iw, (double)oh / ih,
+                                            0.0, 0.0, s->interp_algo,
+                                            s->nppStreamCtx);
         if (err != NPP_SUCCESS) {
             av_log(ctx, AV_LOG_ERROR, "NPP resize error: %d\n", err);
             return AVERROR_UNKNOWN;
@@ -755,15 +760,17 @@ static int nppscale_interleave(AVFilterContext *ctx, NPPScaleStageContext *stage
                                AVFrame *out, AVFrame *in)
 {
     AVHWFramesContext *out_frames_ctx = (AVHWFramesContext*)out->hw_frames_ctx->data;
+    NPPScaleContext                *s = ctx->priv;
     NppStatus err;
 
     switch (out_frames_ctx->sw_format) {
     case AV_PIX_FMT_NV12:
-        err = nppiYCbCr420_8u_P3P2R((const uint8_t**)in->data,
-                                    in->linesize,
-                                    out->data[0], out->linesize[0],
-                                    out->data[1], out->linesize[1],
-                                    (NppiSize){ in->width, in->height });
+        err = nppiYCbCr420_8u_P3P2R_Ctx((const uint8_t**)in->data,
+                                        in->linesize,
+                                        out->data[0], out->linesize[0],
+                                        out->data[1], out->linesize[1],
+                                        (NppiSize){ in->width, in->height },
+                                        s->nppStreamCtx);
         break;
     default:
         return AVERROR_BUG;
@@ -918,6 +925,39 @@ static int nppscale_filter_frame(AVFilterLink *link, AVFrame *in)
     ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuCtxPushCurrent(device_hwctx->cuda_ctx));
     if (ret < 0)
         goto fail;
+    s->nppStreamCtx.nCudaDeviceId = device_hwctx->internal->cuda_device;
+    s->nppStreamCtx.hStream       = device_hwctx->stream;
+    s->nppStreamCtx.nStreamFlags  = 0;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nCudaDevAttrComputeCapabilityMajor,
+                                                                        CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nCudaDevAttrComputeCapabilityMinor,
+                                                                        CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nMultiProcessorCount,
+                                                                        CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nMaxThreadsPerMultiProcessor,
+                                                                        CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_MULTIPROCESSOR,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nMaxThreadsPerBlock,
+                                                                        CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nSharedMemPerBlock,
+                                                                        CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_BLOCK,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
 
     ret = nppscale_scale(link, out, in);
 
diff --git a/libavfilter/vf_sharpen_npp.c b/libavfilter/vf_sharpen_npp.c
index 0a2c5c458b..7abd813e7e 100644
--- a/libavfilter/vf_sharpen_npp.c
+++ b/libavfilter/vf_sharpen_npp.c
@@ -45,7 +45,8 @@ typedef struct NPPSharpenContext {
     AVFrame* own_frame;
     AVFrame* tmp_frame;
 
-    NppiBorderType border_type;
+    NppiBorderType   border_type;
+    NppStreamContext nppStreamCtx;
 } NPPSharpenContext;
 
 static int nppsharpen_init(AVFilterContext* ctx)
@@ -162,9 +163,10 @@ static int nppsharpen_sharpen(AVFilterContext* ctx, AVFrame* out, AVFrame* in)
         int ow = AV_CEIL_RSHIFT(in->width, (i == 1 || i == 2) ? desc->log2_chroma_w : 0);
         int oh = AV_CEIL_RSHIFT(in->height, (i == 1 || i == 2) ? desc->log2_chroma_h : 0);
 
-        NppStatus err = nppiFilterSharpenBorder_8u_C1R(
+        NppStatus err = nppiFilterSharpenBorder_8u_C1R_Ctx(
             in->data[i], in->linesize[i], (NppiSize){ow, oh}, (NppiPoint){0, 0},
-            out->data[i], out->linesize[i], (NppiSize){ow, oh}, s->border_type);
+            out->data[i], out->linesize[i], (NppiSize){ow, oh}, s->border_type,
+            s->nppStreamCtx);
         if (err != NPP_SUCCESS) {
             av_log(ctx, AV_LOG_ERROR, "NPP sharpen error: %d\n", err);
             return AVERROR_EXTERNAL;
@@ -197,6 +199,39 @@ static int nppsharpen_filter_frame(AVFilterLink* link, AVFrame* in)
         device_hwctx->cuda_ctx));
     if (ret < 0)
         goto fail;
+    s->nppStreamCtx.nCudaDeviceId = device_hwctx->internal->cuda_device;
+    s->nppStreamCtx.hStream       = device_hwctx->stream;
+    s->nppStreamCtx.nStreamFlags  = 0;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nCudaDevAttrComputeCapabilityMajor,
+                                                                        CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nCudaDevAttrComputeCapabilityMinor,
+                                                                        CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nMultiProcessorCount,
+                                                                        CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nMaxThreadsPerMultiProcessor,
+                                                                        CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_MULTIPROCESSOR,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nMaxThreadsPerBlock,
+                                                                        CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nSharedMemPerBlock,
+                                                                        CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_BLOCK,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
 
     ret = nppsharpen_sharpen(ctx, s->own_frame, in);
     if (ret < 0)
diff --git a/libavfilter/vf_transpose_npp.c b/libavfilter/vf_transpose_npp.c
index 047c200096..8ce1b9da2d 100644
--- a/libavfilter/vf_transpose_npp.c
+++ b/libavfilter/vf_transpose_npp.c
@@ -78,6 +78,7 @@ typedef struct NPPTransposeContext {
 
     int passthrough;    ///< PassthroughType, landscape passthrough mode enabled
     int dir;            ///< TransposeDir
+    NppStreamContext nppStreamCtx;
 } NPPTransposeContext;
 
 static int npptranspose_init(AVFilterContext *ctx)
@@ -305,11 +306,12 @@ static int npptranspose_rotate(AVFilterContext *ctx, NPPTransposeStageContext *s
         int shiftw = (s->dir == NPP_TRANSPOSE_CLOCK  || s->dir == NPP_TRANSPOSE_CLOCK_FLIP) ? ow - 1 : 0;
         int shifth = (s->dir == NPP_TRANSPOSE_CCLOCK || s->dir == NPP_TRANSPOSE_CLOCK_FLIP) ? oh - 1 : 0;
 
-        err = nppiRotate_8u_C1R(in->data[i], (NppiSize){ iw, ih },
-                                in->linesize[i], (NppiRect){ 0, 0, iw, ih },
-                                out->data[i], out->linesize[i],
-                                (NppiRect){ 0, 0, ow, oh },
-                                angle, shiftw, shifth, NPPI_INTER_NN);
+        err = nppiRotate_8u_C1R_Ctx(in->data[i], (NppiSize){ iw, ih },
+                                    in->linesize[i], (NppiRect){ 0, 0, iw, ih },
+                                    out->data[i], out->linesize[i],
+                                    (NppiRect){ 0, 0, ow, oh },
+                                    angle, shiftw, shifth, NPPI_INTER_NN,
+                                    s->nppStreamCtx);
         if (err != NPP_SUCCESS) {
             av_log(ctx, AV_LOG_ERROR, "NPP rotate error: %d\n", err);
             return AVERROR_UNKNOWN;
@@ -322,6 +324,7 @@ static int npptranspose_rotate(AVFilterContext *ctx, NPPTransposeStageContext *s
 static int npptranspose_transpose(AVFilterContext *ctx, NPPTransposeStageContext *stage,
                                   AVFrame *out, AVFrame *in)
 {
+    NPPTransposeContext *s = ctx->priv;
     NppStatus err;
     int i;
 
@@ -329,9 +332,10 @@ static int npptranspose_transpose(AVFilterContext *ctx, NPPTransposeStageContext
         int iw = stage->planes_in[i].width;
         int ih = stage->planes_in[i].height;
 
-        err = nppiTranspose_8u_C1R(in->data[i], in->linesize[i],
-                                   out->data[i], out->linesize[i],
-                                   (NppiSize){ iw, ih });
+        err = nppiTranspose_8u_C1R_Ctx(in->data[i], in->linesize[i],
+                                       out->data[i], out->linesize[i],
+                                       (NppiSize){ iw, ih },
+                                       s->nppStreamCtx);
         if (err != NPP_SUCCESS) {
             av_log(ctx, AV_LOG_ERROR, "NPP transpose error: %d\n", err);
             return AVERROR_UNKNOWN;
@@ -372,6 +376,9 @@ static int npptranspose_filter(AVFilterContext *ctx, AVFrame *out, AVFrame *in)
     if (ret < 0)
         return ret;
 
+    s->tmp_frame->width  = src->width;
+    s->tmp_frame->height = src->height;
+
     av_frame_move_ref(out, src);
     av_frame_move_ref(src, s->tmp_frame);
 
@@ -405,6 +412,39 @@ static int npptranspose_filter_frame(AVFilterLink *link, AVFrame *in)
     ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuCtxPushCurrent(device_hwctx->cuda_ctx));
     if (ret < 0)
         goto fail;
+    s->nppStreamCtx.nCudaDeviceId = device_hwctx->internal->cuda_device;
+    s->nppStreamCtx.hStream       = device_hwctx->stream;
+    s->nppStreamCtx.nStreamFlags  = 0;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nCudaDevAttrComputeCapabilityMajor,
+                                                                        CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nCudaDevAttrComputeCapabilityMinor,
+                                                                        CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nMultiProcessorCount,
+                                                                        CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nMaxThreadsPerMultiProcessor,
+                                                                        CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_MULTIPROCESSOR,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nMaxThreadsPerBlock,
+                                                                        CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
+    ret = CHECK_CU(device_hwctx->internal->cuda_dl->cuDeviceGetAttribute(&s->nppStreamCtx.nSharedMemPerBlock,
+                                                                        CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_BLOCK,
+                                                                        device_hwctx->internal->cuda_device));
+    if (ret < 0)
+        goto fail;
 
     ret = npptranspose_filter(ctx, out, in);
 
diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c
index 0312d3b9d7..06b317ee1f 100644
--- a/libavutil/hwcontext_cuda.c
+++ b/libavutil/hwcontext_cuda.c
@@ -50,6 +50,8 @@ static const enum AVPixelFormat supported_formats[] = {
 #if CONFIG_VULKAN
     AV_PIX_FMT_VULKAN,
 #endif
+    AV_PIX_FMT_RGB24,
+    AV_PIX_FMT_BGR24,
 };
 
 #define CHECK_CU(x) FF_CUDA_CHECK_DL(device_ctx, cu, x)
