summaryrefslogtreecommitdiff
path: root/libavcodec/qsvdec.c
diff options
context:
space:
mode:
authorLinjie Fu <linjie.fu@intel.com>2019-10-08 21:41:02 +0800
committerZhong Li <zhong.li@intel.com>2019-10-09 11:27:34 +0800
commit5345965b3f088ad5acd5151bec421c97470675a4 (patch)
tree55e28c563f3f87cf4627ded67ec89f34a50f5e97 /libavcodec/qsvdec.c
parent949a1b3e2f75338e17e446e97105e06ad6b4012a (diff)
downloadffmpeg-5345965b3f088ad5acd5151bec421c97470675a4.tar.gz
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.c60
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;
}