diff options
author | Linjie Fu <linjie.fu@intel.com> | 2019-10-08 16:41:02 +0300 |
---|---|---|
committer | Zhong Li <zhong.li@intel.com> | 2019-10-09 06:27:34 +0300 |
commit | 5345965b3f088ad5acd5151bec421c97470675a4 (patch) | |
tree | 55e28c563f3f87cf4627ded67ec89f34a50f5e97 /libavcodec/qsvdec.c | |
parent | 949a1b3e2f75338e17e446e97105e06ad6b4012a (diff) |
lavc/qsvdec: Add GPU-accelerated memory copy support
GPU copy enables or disables GPU accelerated copying between video
and system memory. This may lead to a notable performance improvement.
Memory must be sequent and aligned with 128x64.
CMD:
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -c:v h264_qsv
-gpu_copy on -i input.h264 -f null -
or:
ffmpeg -c:v h264_qsv -gpu_copy on -i input.h264 -f null -
Signed-off-by: Linjie Fu <linjie.fu@intel.com>
Signed-off-by: ChaoX A Liu <chaox.a.liu@intel.com>
Signed-off-by: Zhong Li <zhong.li@intel.com>
Diffstat (limited to 'libavcodec/qsvdec.c')
-rw-r--r-- | libavcodec/qsvdec.c | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 9299596e33..ae5023989c 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -34,9 +34,11 @@ #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" #include "libavutil/time.h" +#include "libavutil/imgutils.h" #include "avcodec.h" #include "internal.h" +#include "decode.h" #include "qsv.h" #include "qsv_internal.h" #include "qsvdec.h" @@ -54,11 +56,52 @@ const AVCodecHWConfigInternal *ff_qsv_hw_configs[] = { NULL }; +static int ff_qsv_get_continuous_buffer(AVCodecContext *avctx, AVFrame *frame, AVBufferPool *pool) +{ + int ret = 0; + + ff_decode_frame_props(avctx, frame); + + frame->width = avctx->width; + frame->height = avctx->height; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_NV12: + frame->linesize[0] = FFALIGN(avctx->width, 128); + break; + case AV_PIX_FMT_P010: + frame->linesize[0] = 2 * FFALIGN(avctx->width, 128); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format.\n"); + return AVERROR(ENOMEM); + } + + frame->linesize[1] = frame->linesize[0]; + frame->buf[0] = av_buffer_pool_get(pool); + if (!frame->buf[0]) + return AVERROR(ENOMEM); + + frame->data[0] = frame->buf[0]->data; + frame->data[1] = frame->data[0] + + frame->linesize[0] * FFALIGN(avctx->height, 64); + + ret = ff_attach_decode_data(frame); + if (ret < 0) + return ret; + + return 0; +} + static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session, AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref) { int ret; + if (q->gpu_copy == MFX_GPUCOPY_ON && + !(q->iopattern & MFX_IOPATTERN_OUT_SYSTEM_MEMORY)) + av_log(avctx, AV_LOG_WARNING, "GPU-accelerated memory copy " + "only works in MFX_IOPATTERN_OUT_SYSTEM_MEMORY.\n"); if (session) { q->session = session; } else if (hw_frames_ref) { @@ -74,7 +117,8 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session, &q->frames_ctx, q->load_plugins, - q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY); + q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY, + q->gpu_copy); if (ret < 0) { av_buffer_unref(&q->frames_ctx.hw_frames_ctx); return ret; @@ -88,7 +132,7 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses } ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session, - hw_device_ref, q->load_plugins); + hw_device_ref, q->load_plugins, q->gpu_copy); if (ret < 0) return ret; @@ -96,7 +140,7 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses } else { if (!q->internal_qs.session) { ret = ff_qsv_init_internal_session(avctx, &q->internal_qs, - q->load_plugins); + q->load_plugins, q->gpu_copy); if (ret < 0) return ret; } @@ -229,6 +273,9 @@ static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q, mfxVideoParam * q->frame_info = param->mfx.FrameInfo; + if (!avctx->hw_frames_ctx) + q->pool = av_buffer_pool_init(av_image_get_buffer_size(avctx->pix_fmt, + FFALIGN(avctx->width, 128), FFALIGN(avctx->height, 64), 1), av_buffer_allocz); return 0; } @@ -275,7 +322,11 @@ static int alloc_frame(AVCodecContext *avctx, QSVContext *q, QSVFrame *frame) { int ret; - ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF); + if (q->pool) + ret = ff_qsv_get_continuous_buffer(avctx, frame->frame, q->pool); + else + ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF); + if (ret < 0) return ret; @@ -535,6 +586,7 @@ int ff_qsv_decode_close(QSVContext *q) av_buffer_unref(&q->frames_ctx.hw_frames_ctx); av_buffer_unref(&q->frames_ctx.mids_buf); + av_buffer_pool_uninit(&q->pool); return 0; } |