2 * Intel MediaSDK QSV encoder/decoder shared code
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <mfx/mfxvideo.h>
22 #include <mfx/mfxplugin.h>
27 #include "libavutil/avstring.h"
28 #include "libavutil/error.h"
31 #include "qsv_internal.h"
33 int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
36 case AV_CODEC_ID_H264:
38 #if QSV_VERSION_ATLEAST(1, 8)
39 case AV_CODEC_ID_HEVC:
40 return MFX_CODEC_HEVC;
42 case AV_CODEC_ID_MPEG1VIDEO:
43 case AV_CODEC_ID_MPEG2VIDEO:
44 return MFX_CODEC_MPEG2;
51 return AVERROR(ENOSYS);
54 int ff_qsv_error(int mfx_err)
59 case MFX_ERR_MEMORY_ALLOC:
60 case MFX_ERR_NOT_ENOUGH_BUFFER:
61 return AVERROR(ENOMEM);
62 case MFX_ERR_INVALID_HANDLE:
63 return AVERROR(EINVAL);
64 case MFX_ERR_DEVICE_FAILED:
65 case MFX_ERR_DEVICE_LOST:
66 case MFX_ERR_LOCK_MEMORY:
68 case MFX_ERR_NULL_PTR:
69 case MFX_ERR_UNDEFINED_BEHAVIOR:
70 case MFX_ERR_NOT_INITIALIZED:
72 case MFX_ERR_UNSUPPORTED:
73 case MFX_ERR_NOT_FOUND:
74 return AVERROR(ENOSYS);
75 case MFX_ERR_MORE_DATA:
76 case MFX_ERR_MORE_SURFACE:
77 case MFX_ERR_MORE_BITSTREAM:
78 return AVERROR(EAGAIN);
79 case MFX_ERR_INCOMPATIBLE_VIDEO_PARAM:
80 case MFX_ERR_INVALID_VIDEO_PARAM:
81 return AVERROR(EINVAL);
85 return AVERROR_UNKNOWN;
88 static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
90 // this code is only required for Linux. It searches for a valid
91 // display handle. First in /dev/dri/renderD then in /dev/dri/card
92 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
93 // VAAPI display handle
95 VADisplay va_dpy = NULL;
96 VAStatus va_res = VA_STATUS_SUCCESS;
97 int major_version = 0, minor_version = 0;
99 char adapterpath[256];
103 qs->va_display = NULL;
105 //search for valid graphics device
106 for (adapter_num = 0;adapter_num < 6;adapter_num++) {
109 snprintf(adapterpath,sizeof(adapterpath),
110 "/dev/dri/renderD%d", adapter_num+128);
112 snprintf(adapterpath,sizeof(adapterpath),
113 "/dev/dri/card%d", adapter_num-3);
116 fd = open(adapterpath, O_RDWR);
118 av_log(avctx, AV_LOG_ERROR,
119 "mfx init: %s fd open failed\n", adapterpath);
123 va_dpy = vaGetDisplayDRM(fd);
125 av_log(avctx, AV_LOG_ERROR,
126 "mfx init: %s vaGetDisplayDRM failed\n", adapterpath);
131 va_res = vaInitialize(va_dpy, &major_version, &minor_version);
132 if (VA_STATUS_SUCCESS != va_res) {
133 av_log(avctx, AV_LOG_ERROR,
134 "mfx init: %s vaInitialize failed\n", adapterpath);
139 av_log(avctx, AV_LOG_VERBOSE,
140 "mfx initialization: %s vaInitialize successful\n",adapterpath);
142 qs->va_display = va_dpy;
143 ret = MFXVideoCORE_SetHandle(qs->session,
144 (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)va_dpy);
146 av_log(avctx, AV_LOG_ERROR,
147 "Error %d during set display handle\n", ret);
148 return ff_qsv_error(ret);
153 #endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
157 * @brief Initialize a MSDK session
159 * Media SDK is based on sessions, so this is the prerequisite
160 * initialization for HW acceleration. For Windows the session is
161 * complete and ready to use, for Linux a display handle is
162 * required. For releases of Media Server Studio >= 2015 R4 the
163 * render nodes interface is preferred (/dev/dri/renderD).
164 * Using Media Server Studio 2015 R4 or newer is recommended
165 * but the older /dev/dri/card interface is also searched
166 * for broader compatibility.
168 * @param avctx ffmpeg metadata for this codec context
169 * @param session the MSDK session used
171 int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
172 const char *load_plugins)
174 mfxIMPL impl = MFX_IMPL_AUTO_ANY;
175 mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
180 ret = MFXInit(impl, &ver, &qs->session);
182 av_log(avctx, AV_LOG_ERROR, "Error initializing an internal MFX session\n");
183 return ff_qsv_error(ret);
186 ret = ff_qsv_set_display_handle(avctx, qs);
190 MFXQueryIMPL(qs->session, &impl);
192 switch (MFX_IMPL_BASETYPE(impl)) {
193 case MFX_IMPL_SOFTWARE:
196 case MFX_IMPL_HARDWARE:
197 case MFX_IMPL_HARDWARE2:
198 case MFX_IMPL_HARDWARE3:
199 case MFX_IMPL_HARDWARE4:
200 desc = "hardware accelerated";
206 if (load_plugins && *load_plugins) {
207 while (*load_plugins) {
211 char *plugin = av_get_token(&load_plugins, ":");
213 return AVERROR(ENOMEM);
214 if (strlen(plugin) != 2 * sizeof(uid.Data)) {
215 av_log(avctx, AV_LOG_ERROR, "Invalid plugin UID length\n");
216 err = AVERROR(EINVAL);
217 goto load_plugin_fail;
220 for (i = 0; i < sizeof(uid.Data); i++) {
221 err = sscanf(plugin + 2 * i, "%2hhx", uid.Data + i);
223 av_log(avctx, AV_LOG_ERROR, "Invalid plugin UID\n");
224 err = AVERROR(EINVAL);
225 goto load_plugin_fail;
230 ret = MFXVideoUSER_Load(qs->session, &uid, 1);
232 av_log(avctx, AV_LOG_ERROR, "Could not load the requested plugin: %s\n",
234 err = ff_qsv_error(ret);
235 goto load_plugin_fail;
245 av_log(avctx, AV_LOG_VERBOSE,
246 "Initialized an internal MFX session using %s implementation\n",
252 int ff_qsv_close_internal_session(QSVSession *qs)
255 MFXClose(qs->session);
258 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
259 if (qs->va_display) {
260 vaTerminate(qs->va_display);
261 qs->va_display = NULL;
263 if (qs->fd_display > 0) {
264 close(qs->fd_display);