35d95c8927df55cf78b8474dd64594a9a2d703d0
[platform/upstream/gstreamer.git] / subprojects / gstreamer-vaapi / gst-libs / gst / vaapi / gstvaapiprofile.c
1 /*
2  *  gstvaapiprofile.c - VA profile abstraction
3  *
4  *  Copyright (C) 2010-2011 Splitted-Desktop Systems
5  *    Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
6  *  Copyright (C) 2012-2013 Intel Corporation
7  *    Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Lesser General Public License
11  *  as published by the Free Software Foundation; either version 2.1
12  *  of the License, or (at your option) any later version.
13  *
14  *  This library is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  Lesser General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public
20  *  License along with this library; if not, write to the Free
21  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  *  Boston, MA 02110-1301 USA
23  */
24
25 /**
26  * SECTION:gstvaapiprofile
27  * @short_description: VA profile abstraction
28  */
29
30 #include "sysdeps.h"
31 #include <gst/gstbuffer.h>
32 #include "gstvaapicompat.h"
33 #include "gstvaapiprofile.h"
34 #include "gstvaapiutils.h"
35 #include "gstvaapiworkarounds.h"
36
37 typedef struct _GstVaapiCodecMap GstVaapiCodecMap;
38 typedef struct _GstVaapiProfileMap GstVaapiProfileMap;
39 typedef struct _GstVaapiEntrypointMap GstVaapiEntrypointMap;
40
41 struct _GstVaapiCodecMap
42 {
43   GstVaapiCodec codec;
44   const gchar *name;
45 };
46
47 struct _GstVaapiProfileMap
48 {
49   GstVaapiProfile profile;
50   VAProfile va_profile;
51   const char *media_str;
52   const gchar *profile_str;
53 };
54
55 struct _GstVaapiEntrypointMap
56 {
57   GstVaapiEntrypoint entrypoint;
58   VAEntrypoint va_entrypoint;
59 };
60
61 /* Codecs */
62 static const GstVaapiCodecMap gst_vaapi_codecs[] = {
63   {GST_VAAPI_CODEC_MPEG1, "mpeg1"},
64   {GST_VAAPI_CODEC_MPEG2, "mpeg2"},
65   {GST_VAAPI_CODEC_MPEG4, "mpeg4"},
66   {GST_VAAPI_CODEC_H263, "h263"},
67   {GST_VAAPI_CODEC_H264, "h264"},
68   {GST_VAAPI_CODEC_WMV3, "wmv3"},
69   {GST_VAAPI_CODEC_VC1, "vc1"},
70   {GST_VAAPI_CODEC_JPEG, "jpeg"},
71   {GST_VAAPI_CODEC_VP8, "vp8"},
72   {GST_VAAPI_CODEC_H265, "h265"},
73   {GST_VAAPI_CODEC_VP9, "vp9"},
74   {GST_VAAPI_CODEC_AV1, "av1"},
75   {0,}
76 };
77
78 /* Profiles */
79 static const GstVaapiProfileMap gst_vaapi_profiles[] = {
80   {GST_VAAPI_PROFILE_MPEG2_SIMPLE, VAProfileMPEG2Simple,
81       "video/mpeg, mpegversion=2", "simple"},
82   {GST_VAAPI_PROFILE_MPEG2_MAIN, VAProfileMPEG2Main,
83       "video/mpeg, mpegversion=2", "main"},
84   {GST_VAAPI_PROFILE_MPEG4_SIMPLE, VAProfileMPEG4Simple,
85       "video/mpeg, mpegversion=4", "simple"},
86   {GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE, VAProfileMPEG4AdvancedSimple,
87       "video/mpeg, mpegversion=4", "advanced-simple"},
88   {GST_VAAPI_PROFILE_MPEG4_MAIN, VAProfileMPEG4Main,
89       "video/mpeg, mpegversion=4", "main"},
90   {GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE, VAProfileMPEG4AdvancedSimple,
91       "video/x-divx, divxversion=5", "advanced-simple"},
92   {GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE, VAProfileMPEG4AdvancedSimple,
93       "video/x-xvid", "advanced-simple"},
94   {GST_VAAPI_PROFILE_H263_BASELINE, VAProfileH263Baseline,
95       "video/x-h263, variant=itu, h263version=h263", "baseline"},
96 #if !VA_CHECK_VERSION(1,0,0)
97   {GST_VAAPI_PROFILE_H264_BASELINE, VAProfileH264Baseline,
98       "video/x-h264", "baseline"},
99 #endif
100   {GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE,
101         VAProfileH264ConstrainedBaseline,
102       "video/x-h264", "constrained-baseline"},
103   {GST_VAAPI_PROFILE_H264_MAIN, VAProfileH264Main,
104       "video/x-h264", "main"},
105   {GST_VAAPI_PROFILE_H264_HIGH, VAProfileH264High,
106       "video/x-h264", "high"},
107   {GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH, VAProfileH264MultiviewHigh,
108       "video/x-h264", "multiview-high"},
109   {GST_VAAPI_PROFILE_H264_STEREO_HIGH, VAProfileH264StereoHigh,
110       "video/x-h264", "stereo-high"},
111   {GST_VAAPI_PROFILE_VC1_SIMPLE, VAProfileVC1Simple,
112       "video/x-wmv, wmvversion=3", "simple"},
113   {GST_VAAPI_PROFILE_VC1_MAIN, VAProfileVC1Main,
114       "video/x-wmv, wmvversion=3", "main"},
115   {GST_VAAPI_PROFILE_VC1_ADVANCED, VAProfileVC1Advanced,
116       "video/x-wmv, wmvversion=3, format=(string)WVC1", "advanced"},
117   {GST_VAAPI_PROFILE_JPEG_BASELINE, VAProfileJPEGBaseline,
118       "image/jpeg", NULL},
119   {GST_VAAPI_PROFILE_VP8, VAProfileVP8Version0_3,
120       "video/x-vp8", NULL},
121   {GST_VAAPI_PROFILE_H265_MAIN, VAProfileHEVCMain,
122       "video/x-h265", "main"},
123   {GST_VAAPI_PROFILE_H265_MAIN10, VAProfileHEVCMain10,
124       "video/x-h265", "main-10"},
125 #if VA_CHECK_VERSION(1,2,0)
126   {GST_VAAPI_PROFILE_H265_MAIN_422_10, VAProfileHEVCMain422_10,
127       "video/x-h265", "main-422-10"},
128   {GST_VAAPI_PROFILE_H265_MAIN_444, VAProfileHEVCMain444,
129       "video/x-h265", "main-444"},
130   {GST_VAAPI_PROFILE_H265_MAIN_444_10, VAProfileHEVCMain444_10,
131       "video/x-h265", "main-444-10"},
132   {GST_VAAPI_PROFILE_H265_MAIN12, VAProfileHEVCMain12,
133       "video/x-h265", "main-12"},
134   {GST_VAAPI_PROFILE_H265_MAIN_444_12, VAProfileHEVCMain444_12,
135       "video/x-h265", "main-444-12"},
136   {GST_VAAPI_PROFILE_H265_MAIN_422_12, VAProfileHEVCMain422_12,
137       "video/x-h265", "main-422-12"},
138   {GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN, VAProfileHEVCSccMain,
139       "video/x-h265", "screen-extended-main"},
140   {GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN_10, VAProfileHEVCSccMain10,
141       "video/x-h265", "screen-extended-main-10"},
142   {GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN_444, VAProfileHEVCSccMain444,
143       "video/x-h265", "screen-extended-main-444"},
144 #endif
145 #if VA_CHECK_VERSION(1,8,0)
146   {GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN_444_10,
147         VAProfileHEVCSccMain444_10,
148       "video/x-h265", "screen-extended-main-444-10"},
149 #endif
150   {GST_VAAPI_PROFILE_VP9_0, VAProfileVP9Profile0,
151       "video/x-vp9", "0"},
152   {GST_VAAPI_PROFILE_VP9_1, VAProfileVP9Profile1,
153       "video/x-vp9", "1"},
154   {GST_VAAPI_PROFILE_VP9_2, VAProfileVP9Profile2,
155       "video/x-vp9", "2"},
156   {GST_VAAPI_PROFILE_VP9_3, VAProfileVP9Profile3,
157       "video/x-vp9", "3"},
158 #if VA_CHECK_VERSION(1,8,0)
159   {GST_VAAPI_PROFILE_AV1_0, VAProfileAV1Profile0,
160       "video/x-av1", "0"},
161   {GST_VAAPI_PROFILE_AV1_1, VAProfileAV1Profile1,
162       "video/x-av1", "1"},
163 #endif
164   {0,}
165 };
166
167 /* Entry-points */
168 static const GstVaapiEntrypointMap gst_vaapi_entrypoints[] = {
169   {GST_VAAPI_ENTRYPOINT_VLD, VAEntrypointVLD},
170   {GST_VAAPI_ENTRYPOINT_IDCT, VAEntrypointIDCT},
171   {GST_VAAPI_ENTRYPOINT_MOCO, VAEntrypointMoComp},
172   {GST_VAAPI_ENTRYPOINT_SLICE_ENCODE, VAEntrypointEncSlice},
173   {GST_VAAPI_ENTRYPOINT_PICTURE_ENCODE, VAEntrypointEncPicture},
174 #if VA_CHECK_VERSION(0,39,1)
175   {GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_LP, VAEntrypointEncSliceLP},
176 #endif
177   {0,}
178 };
179
180 static const GstVaapiCodecMap *
181 get_codecs_map (GstVaapiCodec codec)
182 {
183   const GstVaapiCodecMap *m;
184
185   for (m = gst_vaapi_codecs; m->codec; m++)
186     if (m->codec == codec)
187       return m;
188   return NULL;
189 }
190
191 static const GstVaapiProfileMap *
192 get_profiles_map (GstVaapiProfile profile)
193 {
194   const GstVaapiProfileMap *m;
195
196   for (m = gst_vaapi_profiles; m->profile; m++)
197     if (m->profile == profile)
198       return m;
199   return NULL;
200 }
201
202 static const GstVaapiEntrypointMap *
203 get_entrypoints_map (GstVaapiEntrypoint entrypoint)
204 {
205   const GstVaapiEntrypointMap *m;
206
207   for (m = gst_vaapi_entrypoints; m->entrypoint; m++)
208     if (m->entrypoint == entrypoint)
209       return m;
210   return NULL;
211 }
212
213 /**
214  * gst_vaapi_codec_get_name:
215  * @codec: a #GstVaapiCodec
216  *
217  * Returns a string representation for the supplied @codec type.
218  *
219  * Return value: the statically allocated string representation of @codec
220  */
221 const gchar *
222 gst_vaapi_codec_get_name (GstVaapiCodec codec)
223 {
224   const GstVaapiCodecMap *const m = get_codecs_map (codec);
225
226   return m ? m->name : NULL;
227 }
228
229 /**
230  * gst_vaapi_profile:
231  * @profile: a #VAProfile
232  *
233  * Converts a VA profile into the corresponding #GstVaapiProfile. If
234  * the profile cannot be represented by #GstVaapiProfile, then zero is
235  * returned.
236  *
237  * Return value: the #GstVaapiProfile describing the @profile
238  */
239 GstVaapiProfile
240 gst_vaapi_profile (VAProfile profile)
241 {
242   const GstVaapiProfileMap *m;
243
244   for (m = gst_vaapi_profiles; m->profile; m++)
245     if (m->va_profile == profile)
246       return m->profile;
247   return 0;
248 }
249
250 /**
251  * gst_vaapi_profile_get_name:
252  * @profile: a #GstVaapiProfile
253  *
254  * Returns a string representation for the supplied @profile.
255  *
256  * Return value: the statically allocated string representation of @profile
257  */
258 const gchar *
259 gst_vaapi_profile_get_name (GstVaapiProfile profile)
260 {
261   const GstVaapiProfileMap *const m = get_profiles_map (profile);
262
263   return m ? m->profile_str : NULL;
264 }
265
266 /**
267  * gst_vaapi_profile_get_va_name:
268  * @profile: a #GstVaapiProfile
269  *
270  * Returns a string representation for the supplied @profile as VAProfile.
271  *
272  * Return value: the statically allocated string representation of
273  * @profile as VAProfile
274  */
275 const gchar *
276 gst_vaapi_profile_get_va_name (GstVaapiProfile profile)
277 {
278   const GstVaapiProfileMap *const m = get_profiles_map (profile);
279
280   return m ? string_of_VAProfile (m->va_profile) : NULL;
281 }
282
283 /**
284  * gst_vaapi_profile_get_media_type_name:
285  * @profile: a #GstVaapiProfileo
286  *
287  * Returns a string representation for the media type of the supplied
288  * @profile.
289  *
290  * Return value: the statically allocated string representation of
291  *   @profile media type
292  */
293 const gchar *
294 gst_vaapi_profile_get_media_type_name (GstVaapiProfile profile)
295 {
296   const GstVaapiProfileMap *const m = get_profiles_map (profile);
297
298   return m ? m->media_str : NULL;
299 }
300
301 /**
302  * gst_vaapi_profile_from_codec_data:
303  * @codec: a #GstVaapiCodec
304  * @buffer: a #GstBuffer holding code data
305  *
306  * Tries to parse VA profile from @buffer data and @codec information.
307  *
308  * Return value: the #GstVaapiProfile described in @buffer
309  */
310 static GstVaapiProfile
311 gst_vaapi_profile_from_codec_data_h264 (GstBuffer * buffer)
312 {
313   /* MPEG-4 Part 15: Advanced Video Coding (AVC) file format */
314   guchar buf[3];
315
316   if (gst_buffer_extract (buffer, 0, buf, sizeof (buf)) != sizeof (buf))
317     return 0;
318
319   if (buf[0] != 1)              /* configurationVersion = 1 */
320     return 0;
321
322   switch (buf[1]) {             /* AVCProfileIndication */
323     case 66:
324       return ((buf[2] & 0x40) ?
325           GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE :
326           GST_VAAPI_PROFILE_H264_BASELINE);
327     case 77:
328       return GST_VAAPI_PROFILE_H264_MAIN;
329     case 100:
330       return GST_VAAPI_PROFILE_H264_HIGH;
331     case 118:
332       return GST_VAAPI_PROFILE_H264_MULTIVIEW_HIGH;
333     case 128:
334       return GST_VAAPI_PROFILE_H264_STEREO_HIGH;
335
336   }
337   return 0;
338 }
339
340 static GstVaapiProfile
341 gst_vaapi_profile_from_codec_data_h265 (GstBuffer * buffer)
342 {
343   /* ISO/IEC 14496-15:  HEVC file format */
344   guchar buf[3];
345
346   if (gst_buffer_extract (buffer, 0, buf, sizeof (buf)) != sizeof (buf))
347     return 0;
348
349   if (buf[0] != 1)              /* configurationVersion = 1 */
350     return 0;
351
352   if (buf[1] & 0xc0)            /* general_profile_space = 0 */
353     return 0;
354
355   /* We may not recognize the exactly correct profile, which needs more
356      info such as depth, chroma and constraint_flag. We just return the
357      first one that belongs to that profile IDC. */
358   switch (buf[1] & 0x1f) {      /* HEVCProfileIndication */
359     case 1:
360       return GST_VAAPI_PROFILE_H265_MAIN;
361     case 2:
362       return GST_VAAPI_PROFILE_H265_MAIN10;
363     case 3:
364       return GST_VAAPI_PROFILE_H265_MAIN_STILL_PICTURE;
365     case 4:
366       return GST_VAAPI_PROFILE_H265_MAIN_422_10;
367     case 9:
368       return GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN;
369   }
370   return 0;
371 }
372
373 static GstVaapiProfile
374 gst_vaapi_profile_from_codec_data (GstVaapiCodec codec, GstBuffer * buffer)
375 {
376   GstVaapiProfile profile;
377
378   if (!codec || !buffer)
379     return 0;
380
381   switch (codec) {
382     case GST_VAAPI_CODEC_H264:
383       profile = gst_vaapi_profile_from_codec_data_h264 (buffer);
384       break;
385     case GST_VAAPI_CODEC_H265:
386       profile = gst_vaapi_profile_from_codec_data_h265 (buffer);
387       break;
388     default:
389       profile = 0;
390       break;
391   }
392   return profile;
393 }
394
395 /**
396  * gst_vaapi_profile_from_caps:
397  * @caps: a #GstCaps
398  *
399  * Converts @caps into the corresponding #GstVaapiProfile. If the
400  * profile cannot be represented by #GstVaapiProfile, then zero is
401  * returned.
402  *
403  * Return value: the #GstVaapiProfile describing the @caps
404  */
405 GstVaapiProfile
406 gst_vaapi_profile_from_caps (const GstCaps * caps)
407 {
408   const GstVaapiProfileMap *m;
409   GstCaps *caps_test;
410   GstStructure *structure;
411   const gchar *profile_str;
412   GstVaapiProfile profile, best_profile;
413   GstBuffer *codec_data = NULL;
414   const gchar *name;
415   gsize namelen;
416
417   if (!caps)
418     return 0;
419
420   structure = gst_caps_get_structure (caps, 0);
421   if (!structure)
422     return 0;
423
424   name = gst_structure_get_name (structure);
425   namelen = strlen (name);
426
427   profile_str = gst_structure_get_string (structure, "profile");
428   if (!profile_str) {
429     const GValue *v_codec_data;
430     v_codec_data = gst_structure_get_value (structure, "codec_data");
431     if (v_codec_data)
432       codec_data = gst_value_get_buffer (v_codec_data);
433   }
434
435   profile = 0;
436   best_profile = 0;
437   for (m = gst_vaapi_profiles; !profile && m->profile; m++) {
438     if (strncmp (name, m->media_str, namelen) != 0)
439       continue;
440     caps_test = gst_caps_from_string (m->media_str);
441     if (gst_caps_is_always_compatible (caps, caps_test)) {
442       best_profile = m->profile;
443       if (profile_str && m->profile_str &&
444           strcmp (profile_str, m->profile_str) == 0)
445         profile = best_profile;
446     }
447     if (!profile) {
448       profile =
449           gst_vaapi_profile_from_codec_data (gst_vaapi_profile_get_codec
450           (m->profile), codec_data);
451       if (!profile && WORKAROUND_QTDEMUX_NO_H263_PROFILES
452           && strncmp (name, "video/x-h263", namelen) == 0) {
453         /* HACK: qtdemux does not report profiles for h263 */
454         profile = m->profile;
455       }
456
457       /* Consider HEVC -intra profiles. Just map them to their
458        * non-intra profiles */
459       if (!profile && profile_str
460           && strncmp (name, "video/x-h265", namelen) == 0
461           && g_str_has_prefix (profile_str, m->profile_str)
462           && strncmp (profile_str + strlen (m->profile_str), "-intra", 6) == 0) {
463         profile = m->profile;
464       }
465     }
466     gst_caps_unref (caps_test);
467   }
468   return profile ? profile : best_profile;
469 }
470
471 /**
472  * gst_vaapi_get_codec_from_caps:
473  * @caps: a #GstCaps
474  *
475  * Converts @caps into the corresponding #GstVaapiCodec. If we can
476  * not recognize the #GstVaapiCodec, then zero is returned.
477  *
478  * Return value: the #GstVaapiCodec describing the @caps
479  */
480 GstVaapiCodec
481 gst_vaapi_get_codec_from_caps (const GstCaps * caps)
482 {
483   GstStructure *structure;
484   const gchar *name;
485   gsize namelen;
486   const GstVaapiProfileMap *m;
487   GstVaapiProfile profile;
488
489   if (!caps)
490     return 0;
491
492   structure = gst_caps_get_structure (caps, 0);
493   if (!structure)
494     return 0;
495
496   name = gst_structure_get_name (structure);
497   namelen = strlen (name);
498
499   profile = GST_VAAPI_PROFILE_UNKNOWN;
500   for (m = gst_vaapi_profiles; m->profile; m++) {
501     if (strncmp (name, m->media_str, namelen) == 0) {
502       profile = m->profile;
503       break;
504     }
505   }
506
507   if (profile == GST_VAAPI_PROFILE_UNKNOWN)
508     return 0;
509
510   return gst_vaapi_profile_get_codec (profile);
511 }
512
513 /**
514  * gst_vaapi_profile_get_va_profile:
515  * @profile: a #GstVaapiProfile
516  *
517  * Converts a #GstVaapiProfile into the corresponding VA profile. If
518  * no matching VA profile was found, -1 is returned and this error
519  * must be reported to be fixed.
520  *
521  * Return value: the VA profile, or -1 if none was found
522  */
523 VAProfile
524 gst_vaapi_profile_get_va_profile (GstVaapiProfile profile)
525 {
526   const GstVaapiProfileMap *const m = get_profiles_map (profile);
527
528   return m ? m->va_profile : (VAProfile) - 1;
529 }
530
531 /**
532  * gst_vaapi_profile_get_caps:
533  * @profile: a #GstVaapiProfile
534  *
535  * Converts a #GstVaapiProfile into the corresponding #GstCaps. If no
536  * matching caps were found, %NULL is returned.
537  *
538  * Return value: the newly allocated #GstCaps, or %NULL if none was found
539  */
540 GstCaps *
541 gst_vaapi_profile_get_caps (GstVaapiProfile profile)
542 {
543   const GstVaapiProfileMap *m;
544   GstCaps *out_caps, *caps;
545
546   out_caps = gst_caps_new_empty ();
547   if (!out_caps)
548     return NULL;
549
550   for (m = gst_vaapi_profiles; m->profile; m++) {
551     if (m->profile != profile)
552       continue;
553     caps = gst_caps_from_string (m->media_str);
554     if (!caps)
555       continue;
556     gst_caps_set_simple (caps, "profile", G_TYPE_STRING, m->profile_str, NULL);
557     out_caps = gst_caps_merge (out_caps, caps);
558   }
559   return out_caps;
560 }
561
562 /**
563  * gst_vaapi_profile_get_codec:
564  * @profile: a #GstVaapiProfile
565  *
566  * Extracts the #GstVaapiCodec from @profile.
567  *
568  * Return value: the #GstVaapiCodec from @profile
569  */
570 GstVaapiCodec
571 gst_vaapi_profile_get_codec (GstVaapiProfile profile)
572 {
573   GstVaapiCodec codec;
574
575   switch (profile) {
576     case GST_VAAPI_PROFILE_VC1_SIMPLE:
577     case GST_VAAPI_PROFILE_VC1_MAIN:
578       codec = GST_VAAPI_CODEC_WMV3;
579       break;
580     case GST_VAAPI_PROFILE_VC1_ADVANCED:
581       codec = GST_VAAPI_CODEC_VC1;
582       break;
583     case GST_VAAPI_PROFILE_JPEG_BASELINE:
584       codec = GST_VAAPI_CODEC_JPEG;
585       break;
586     default:
587       codec = (guint32) profile & GST_MAKE_FOURCC (0xff, 0xff, 0xff, 0);
588       break;
589   }
590   return codec;
591 }
592
593 /**
594  * gst_vaapi_entrypoint:
595  * @entrypoint: a #VAEntrypoint
596  *
597  * Converts a VA entry-point into the corresponding #GstVaapiEntrypoint.
598  * If the entry-point cannot be represented by #GstVaapiEntrypoint,
599  * then zero is returned.
600  *
601  * Return value: the #GstVaapiEntrypoint describing the @entrypoint
602  */
603 GstVaapiEntrypoint
604 gst_vaapi_entrypoint (VAEntrypoint entrypoint)
605 {
606   const GstVaapiEntrypointMap *m;
607
608   for (m = gst_vaapi_entrypoints; m->entrypoint; m++)
609     if (m->va_entrypoint == entrypoint)
610       return m->entrypoint;
611   return 0;
612 }
613
614 /**
615  * gst_vaapi_entrypoint_get_va_entrypoint:
616  * @entrypoint: a #GstVaapiEntrypoint
617  *
618  * Converts a #GstVaapiEntrypoint into the corresponding VA
619  * entry-point. If no matching VA entry-point was found, -1 is
620  * returned and this error must be reported to be fixed.
621  *
622  * Return value: the VA entry-point, or -1 if none was found
623  */
624 VAEntrypoint
625 gst_vaapi_entrypoint_get_va_entrypoint (GstVaapiEntrypoint entrypoint)
626 {
627   const GstVaapiEntrypointMap *const m = get_entrypoints_map (entrypoint);
628
629   return m ? m->va_entrypoint : (VAEntrypoint) - 1;
630 }