X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg_cuvid.c;h=766878f58bc3c75a32fd8498e4915e0d7dc21009;hb=e84d587613488df300ee643df7039578b3a8607b;hp=7fb47a2e0b1ff934a3a9cd1bae8fdad206b49d1d;hpb=78c7197ea0e5c53393849a32dd6f49e3b89f7815;p=ffmpeg diff --git a/ffmpeg_cuvid.c b/ffmpeg_cuvid.c index 7fb47a2e0b1..766878f58bc 100644 --- a/ffmpeg_cuvid.c +++ b/ffmpeg_cuvid.c @@ -17,13 +17,9 @@ */ #include "libavutil/hwcontext.h" -#include "libavutil/hwcontext_cuda.h" #include "ffmpeg.h" -#include -#include - typedef struct CUVIDContext { AVBufferRef *hw_frames_ctx; } CUVIDContext; @@ -61,24 +57,13 @@ int cuvid_init(AVCodecContext *avctx) return 0; } -static void cuvid_ctx_free(AVHWDeviceContext *ctx) -{ - AVCUDADeviceContext *hwctx = ctx->hwctx; - cuCtxDestroy(hwctx->cuda_ctx); -} - int cuvid_transcode_init(OutputStream *ost) { InputStream *ist; const enum AVPixelFormat *pix_fmt; - AVCUDADeviceContext *device_hwctx; - AVHWDeviceContext *device_ctx; AVHWFramesContext *hwframe_ctx; + AVBufferRef *device_ref = NULL; CUVIDContext *ctx = NULL; - CUdevice device; - CUcontext cuda_ctx = NULL; - CUcontext dummy; - CUresult err; int ret = 0; av_log(NULL, AV_LOG_TRACE, "Initializing cuvid transcoding\n"); @@ -118,118 +103,51 @@ int cuvid_transcode_init(OutputStream *ost) } } - if (!hw_device_ctx) { - hw_device_ctx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA); - if (!hw_device_ctx) { - av_log(NULL, AV_LOG_ERROR, "av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA) failed\n"); - ret = AVERROR(ENOMEM); - goto error; - } - - err = cuInit(0); - if (err != CUDA_SUCCESS) { - av_log(NULL, AV_LOG_ERROR, "Could not initialize the CUDA driver API\n"); - ret = AVERROR_UNKNOWN; - goto error; - } - - err = cuDeviceGet(&device, 0); ///TODO: Make device index configurable - if (err != CUDA_SUCCESS) { - av_log(NULL, AV_LOG_ERROR, "Could not get the device number %d\n", 0); - ret = AVERROR_UNKNOWN; - goto error; - } - - err = cuCtxCreate(&cuda_ctx, CU_CTX_SCHED_BLOCKING_SYNC, device); - if (err != CUDA_SUCCESS) { - av_log(NULL, AV_LOG_ERROR, "Error creating a CUDA context\n"); - ret = AVERROR_UNKNOWN; - goto error; - } - - device_ctx = (AVHWDeviceContext*)hw_device_ctx->data; - device_ctx->free = cuvid_ctx_free; - - device_hwctx = device_ctx->hwctx; - device_hwctx->cuda_ctx = cuda_ctx; - - err = cuCtxPopCurrent(&dummy); - if (err != CUDA_SUCCESS) { - av_log(NULL, AV_LOG_ERROR, "cuCtxPopCurrent failed\n"); - ret = AVERROR_UNKNOWN; - goto error; - } - - ret = av_hwdevice_ctx_init(hw_device_ctx); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "av_hwdevice_ctx_init failed\n"); + if (!ctx->hw_frames_ctx) { + ret = av_hwdevice_ctx_create(&device_ref, AV_HWDEVICE_TYPE_CUDA, + ist->hwaccel_device, NULL, 0); + if (ret < 0) goto error; - } - } else { - device_ctx = (AVHWDeviceContext*)hw_device_ctx->data; - device_hwctx = device_ctx->hwctx; - cuda_ctx = device_hwctx->cuda_ctx; - } - if (device_ctx->type != AV_HWDEVICE_TYPE_CUDA) { - av_log(NULL, AV_LOG_ERROR, "Hardware device context is already initialized for a diffrent hwaccel.\n"); - ret = AVERROR(EINVAL); - goto error; - } - - if (!ctx->hw_frames_ctx) { - ctx->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx); + ctx->hw_frames_ctx = av_hwframe_ctx_alloc(device_ref); if (!ctx->hw_frames_ctx) { av_log(NULL, AV_LOG_ERROR, "av_hwframe_ctx_alloc failed\n"); ret = AVERROR(ENOMEM); goto error; } - } - - /* This is a bit hacky, av_hwframe_ctx_init is called by the cuvid decoder - * once it has probed the neccesary format information. But as filters/nvenc - * need to know the format/sw_format, set them here so they are happy. - * This is fine as long as CUVID doesn't add another supported pix_fmt. - */ - hwframe_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; - hwframe_ctx->format = AV_PIX_FMT_CUDA; - hwframe_ctx->sw_format = AV_PIX_FMT_NV12; - - ost->hwaccel_ctx = ctx; - ost->enc_ctx->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx); - ost->enc_ctx->pix_fmt = AV_PIX_FMT_CUDA; - - if (!ost->enc_ctx->hw_frames_ctx) { - av_log(NULL, AV_LOG_ERROR, "av_buffer_ref failed\n"); - ret = AVERROR(ENOMEM); - goto error; - } + av_buffer_unref(&device_ref); - if (!ist->hwaccel_ctx) { - ist->hwaccel_ctx = ctx; ist->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx); - ist->dec_ctx->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx); - ist->dec_ctx->pix_fmt = AV_PIX_FMT_CUDA; - ist->resample_pix_fmt = AV_PIX_FMT_CUDA; - - ist->hwaccel_uninit = cuvid_uninit; - - if (!ist->hw_frames_ctx || !ist->dec_ctx->hw_frames_ctx) { + if (!ist->hw_frames_ctx) { av_log(NULL, AV_LOG_ERROR, "av_buffer_ref failed\n"); ret = AVERROR(ENOMEM); goto error; } + + ist->hwaccel_ctx = ctx; + ist->resample_pix_fmt = AV_PIX_FMT_CUDA; + ist->hwaccel_uninit = cuvid_uninit; + + /* This is a bit hacky, av_hwframe_ctx_init is called by the cuvid decoder + * once it has probed the necessary format information. But as filters/nvenc + * need to know the format/sw_format, set them here so they are happy. + * This is fine as long as CUVID doesn't add another supported pix_fmt. + */ + hwframe_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; + hwframe_ctx->format = AV_PIX_FMT_CUDA; + hwframe_ctx->sw_format = AV_PIX_FMT_NV12; } return 0; error: av_freep(&ctx); + av_buffer_unref(&device_ref); return ret; cancel: if (ist->hwaccel_id == HWACCEL_CUVID) { - av_log(NULL, AV_LOG_ERROR, "CUVID hwaccel requested, but impossible to achive.\n"); + av_log(NULL, AV_LOG_ERROR, "CUVID hwaccel requested, but impossible to achieve.\n"); return AVERROR(EINVAL); }