vaapi: fix mismatched close callback prototype
[vlc.git] / modules / codec / avcodec / vaapi.c
1 /*****************************************************************************
2  * vaapi.c: VAAPI helpers for the libavcodec decoder
3  *****************************************************************************
4  * Copyright (C) 2017 VLC authors and VideoLAN
5  * Copyright (C) 2009-2010 Laurent Aimar
6  * Copyright (C) 2012-2014 RĂ©mi Denis-Courmont
7  *
8  * Authors: Laurent Aimar <fenrir_AT_ videolan _DOT_ org>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <assert.h>
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_fourcc.h>
34 #include <vlc_picture.h>
35 #include <vlc_picture_pool.h>
36
37 #ifdef VLC_VA_BACKEND_DRM
38 # include <sys/types.h>
39 # include <sys/stat.h>
40 # include <fcntl.h>
41 # include <vlc_fs.h>
42 # include <va/va_drm.h>
43 #endif
44 #include <libavcodec/avcodec.h>
45 #include <libavcodec/vaapi.h>
46
47 #include "avcodec.h"
48 #include "va.h"
49 #include "../../hw/vaapi/vlc_vaapi.h"
50
51 struct vlc_va_sys_t
52 {
53     vlc_decoder_device *dec_device;
54     struct vaapi_context hw_ctx;
55 };
56
57 static int GetVaProfile(AVCodecContext *ctx, const es_format_t *fmt,
58                         VAProfile *va_profile, int *vlc_chroma,
59                         unsigned *pic_count)
60 {
61     VAProfile i_profile;
62     unsigned count = 3;
63     int i_vlc_chroma = VLC_CODEC_VAAPI_420;
64
65     switch(ctx->codec_id)
66     {
67     case AV_CODEC_ID_MPEG1VIDEO:
68     case AV_CODEC_ID_MPEG2VIDEO:
69         i_profile = VAProfileMPEG2Main;
70         count = 4;
71         break;
72     case AV_CODEC_ID_MPEG4:
73         i_profile = VAProfileMPEG4AdvancedSimple;
74         break;
75     case AV_CODEC_ID_WMV3:
76         i_profile = VAProfileVC1Main;
77         break;
78     case AV_CODEC_ID_VC1:
79         i_profile = VAProfileVC1Advanced;
80         break;
81     case AV_CODEC_ID_H264:
82         i_profile = VAProfileH264High;
83         count = 18;
84         break;
85     case AV_CODEC_ID_HEVC:
86         if (fmt->i_profile == FF_PROFILE_HEVC_MAIN)
87             i_profile = VAProfileHEVCMain;
88         else if (fmt->i_profile == FF_PROFILE_HEVC_MAIN_10)
89         {
90             i_profile = VAProfileHEVCMain10;
91             i_vlc_chroma = VLC_CODEC_VAAPI_420_10BPP;
92         }
93         else
94             return VLC_EGENERIC;
95         count = 18;
96         break;
97     case AV_CODEC_ID_VP8:
98         i_profile = VAProfileVP8Version0_3;
99         count = 5;
100         break;
101     case AV_CODEC_ID_VP9:
102         if (ctx->profile == FF_PROFILE_VP9_0)
103             i_profile = VAProfileVP9Profile0;
104 #if VA_CHECK_VERSION( 0, 39, 0 )
105         else if (ctx->profile == FF_PROFILE_VP9_2)
106         {
107             i_profile = VAProfileVP9Profile2;
108             i_vlc_chroma = VLC_CODEC_VAAPI_420_10BPP;
109         }
110 #endif
111         else
112             return VLC_EGENERIC;
113         count = 10;
114         break;
115     default:
116         return VLC_EGENERIC;
117     }
118
119     *va_profile = i_profile;
120     *pic_count = count + ctx->thread_count;
121     *vlc_chroma = i_vlc_chroma;
122     return VLC_SUCCESS;
123 }
124
125 static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
126 {
127     (void) va;
128
129     vlc_vaapi_PicAttachContext(pic);
130     *data = (void *) (uintptr_t) vlc_vaapi_PicGetSurface(pic);
131
132     return VLC_SUCCESS;
133 }
134
135 static void Delete(vlc_va_t *va, void **hwctx)
136 {
137     vlc_va_sys_t *sys = va->sys;
138     vlc_object_t *o = VLC_OBJECT(va);
139
140     (void) hwctx;
141
142     vlc_vaapi_DestroyContext(o, sys->hw_ctx.display, sys->hw_ctx.context_id);
143     vlc_vaapi_DestroyConfig(o, sys->hw_ctx.display, sys->hw_ctx.config_id);
144     vlc_decoder_device_Release(sys->dec_device);
145     free(sys);
146 }
147
148 static int Create(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
149                   const es_format_t *fmt, void *p_sys)
150 {
151     if (pix_fmt != AV_PIX_FMT_VAAPI_VLD || p_sys == NULL)
152         return VLC_EGENERIC;
153
154     vlc_va_sys_t *sys = malloc(sizeof *sys);
155     if (unlikely(sys == NULL))
156         return VLC_ENOMEM;
157     memset(sys, 0, sizeof (*sys));
158
159     vlc_object_t *o = VLC_OBJECT(va);
160
161     int ret = VLC_EGENERIC;
162
163     /* The picture must be allocated by the vout */
164     VADisplay va_dpy;
165     vlc_decoder_device *dec_device =
166         vlc_vaapi_PicSysHoldInstance(p_sys, &va_dpy);
167
168     VASurfaceID *render_targets;
169     unsigned num_render_targets =
170         vlc_vaapi_PicSysGetRenderTargets(p_sys, &render_targets);
171     if (num_render_targets == 0)
172         goto error;
173
174     VAProfile i_profile;
175     unsigned count;
176     int i_vlc_chroma;
177     if (GetVaProfile(ctx, fmt, &i_profile, &i_vlc_chroma, &count) != VLC_SUCCESS)
178         goto error;
179
180     /* */
181     sys->dec_device = dec_device;
182     sys->hw_ctx.display = va_dpy;
183     sys->hw_ctx.config_id = VA_INVALID_ID;
184     sys->hw_ctx.context_id = VA_INVALID_ID;
185
186     sys->hw_ctx.config_id =
187         vlc_vaapi_CreateConfigChecked(o, sys->hw_ctx.display, i_profile,
188                                       VAEntrypointVLD, i_vlc_chroma);
189     if (sys->hw_ctx.config_id == VA_INVALID_ID)
190         goto error;
191
192     /* Create a context */
193     sys->hw_ctx.context_id =
194         vlc_vaapi_CreateContext(o, sys->hw_ctx.display, sys->hw_ctx.config_id,
195                                 ctx->coded_width, ctx->coded_height, VA_PROGRESSIVE,
196                                 render_targets, num_render_targets);
197     if (sys->hw_ctx.context_id == VA_INVALID_ID)
198         goto error;
199
200     msg_Info(va, "Using %s", vaQueryVendorString(sys->hw_ctx.display));
201
202     ctx->hwaccel_context = &sys->hw_ctx;
203     va->sys = sys;
204     va->get = Get;
205     va->close = Delete;
206     return VLC_SUCCESS;
207
208 error:
209     if (sys->hw_ctx.context_id != VA_INVALID_ID)
210         vlc_vaapi_DestroyContext(o, sys->hw_ctx.display, sys->hw_ctx.context_id);
211     if (sys->hw_ctx.config_id != VA_INVALID_ID)
212         vlc_vaapi_DestroyConfig(o, sys->hw_ctx.display, sys->hw_ctx.config_id);
213     free(sys);
214     vlc_decoder_device_Release(dec_device);
215     return ret;
216 }
217
218 vlc_module_begin ()
219     set_description( N_("VA-API video decoder") )
220     set_capability( "hw decoder", 100 )
221     set_callbacks( Create, NULL )
222     add_shortcut( "vaapi" )
223     set_category( CAT_INPUT )
224     set_subcategory( SUBCAT_INPUT_VCODEC )
225 vlc_module_end ()