MythTV  master
mythvaapicontext.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QCoreApplication>
3 #include <QWaitCondition>
4 
5 // Mythtv
6 #include "mythcontext.h"
7 #include "mythmainwindow.h"
8 #include "mythlogging.h"
11 #include "videobuffers.h"
12 #include "mythvaapiinterop.h"
13 #include "mythplayerui.h"
14 #include "mythvaapicontext.h"
15 
16 extern "C" {
17 #include "libavutil/hwcontext_vaapi.h"
18 #include "libavutil/pixdesc.h"
19 #include "libavfilter/buffersink.h"
20 }
21 
22 #define LOC QString("VAAPIDec: ")
23 
33  : MythCodecContext(Parent, CodecID)
34 {
35 }
36 
38 {
40 }
41 
42 VAProfile MythVAAPIContext::VAAPIProfileForCodec(const AVCodecContext *Codec)
43 {
44  if (!Codec)
45  return VAProfileNone;
46 
47  switch (Codec->codec_id)
48  {
49  case AV_CODEC_ID_MPEG2VIDEO:
50  switch (Codec->profile)
51  {
52  case FF_PROFILE_MPEG2_SIMPLE: return VAProfileMPEG2Simple;
53  case FF_PROFILE_MPEG2_MAIN: return VAProfileMPEG2Main;
54  default: break;
55  }
56  break;
57  case AV_CODEC_ID_H263: return VAProfileH263Baseline;
58  case AV_CODEC_ID_MPEG4:
59  switch (Codec->profile)
60  {
61  case FF_PROFILE_MPEG4_SIMPLE: return VAProfileMPEG4Simple;
62  case FF_PROFILE_MPEG4_ADVANCED_SIMPLE: return VAProfileMPEG4AdvancedSimple;
63  case FF_PROFILE_MPEG4_MAIN: return VAProfileMPEG4Main;
64  default: break;
65  }
66  break;
67  case AV_CODEC_ID_H264:
68  switch (Codec->profile)
69  {
70  case FF_PROFILE_H264_CONSTRAINED_BASELINE: return VAProfileH264ConstrainedBaseline;
71  case FF_PROFILE_H264_MAIN: return VAProfileH264Main;
72  case FF_PROFILE_H264_HIGH: return VAProfileH264High;
73  default: break;
74  }
75  break;
76  case AV_CODEC_ID_HEVC:
77 #if VA_CHECK_VERSION(0, 37, 0)
78  switch (Codec->profile)
79  {
80  case FF_PROFILE_HEVC_MAIN: return VAProfileHEVCMain;
81  case FF_PROFILE_HEVC_MAIN_10: return VAProfileHEVCMain10;
82  default: break;
83  }
84 #endif
85  break;
86  case AV_CODEC_ID_MJPEG: return VAProfileJPEGBaseline;
87  case AV_CODEC_ID_WMV3:
88  case AV_CODEC_ID_VC1:
89  switch (Codec->profile)
90  {
91  case FF_PROFILE_VC1_SIMPLE: return VAProfileVC1Simple;
92  case FF_PROFILE_VC1_MAIN: return VAProfileVC1Main;
93  case FF_PROFILE_VC1_ADVANCED:
94  case FF_PROFILE_VC1_COMPLEX: return VAProfileVC1Advanced;
95  default: break;
96  }
97  break;
98  case AV_CODEC_ID_VP8: return VAProfileVP8Version0_3;
99  case AV_CODEC_ID_VP9:
100  switch (Codec->profile)
101  {
102 #if VA_CHECK_VERSION(0, 38, 0)
103  case FF_PROFILE_VP9_0: return VAProfileVP9Profile0;
104 #endif
105 #if VA_CHECK_VERSION(0, 39, 0)
106  case FF_PROFILE_VP9_2: return VAProfileVP9Profile2;
107 #endif
108  default: break;
109  }
110  break;
111  default: break;
112  }
113 
114  return VAProfileNone;
115 }
116 
117 inline AVPixelFormat MythVAAPIContext::FramesFormat(AVPixelFormat Format)
118 {
119  switch (Format)
120  {
121  case AV_PIX_FMT_YUV420P10: return AV_PIX_FMT_P010;
122  case AV_PIX_FMT_YUV420P12:
123  case AV_PIX_FMT_YUV420P14:
124  case AV_PIX_FMT_YUV420P16: return AV_PIX_FMT_P016;
125  default: return AV_PIX_FMT_NV12;
126  }
127 }
128 
132  AVCodec ** /*Codec*/,
133  const QString &Decoder,
134  uint StreamType)
135 {
136  bool decodeonly = Decoder == "vaapi-dec";
137  auto success = static_cast<MythCodecID>((decodeonly ? kCodec_MPEG1_VAAPI_DEC : kCodec_MPEG1_VAAPI) + (StreamType - 1));
138  auto failure = static_cast<MythCodecID>(kCodec_MPEG1 + (StreamType - 1));
139  QString vendor = HaveVAAPI();
140  if (!Decoder.startsWith("vaapi") || vendor.isEmpty() || getenv("NO_VAAPI"))
141  return failure;
142 
143  QString codec = ff_codec_id_string((*Context)->codec_id);
144  QString profile = avcodec_profile_name((*Context)->codec_id, (*Context)->profile);
145  QString pixfmt = av_get_pix_fmt_name((*Context)->pix_fmt);
146 
147  // Simple check for known profile
148  VAProfile desired = VAAPIProfileForCodec(*Context);
149  if (desired == VAProfileNone)
150  {
151  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("VAAPI does not support decoding '%1 %2 %3'")
152  .arg(codec).arg(profile).arg(pixfmt));
153  return failure;
154  }
155 
156  // Check for ironlake decode only - which won't work due to FFmpeg frame format
157  // constraints. May apply to other platforms.
158  if (decodeonly)
159  {
160  if (vendor.contains("ironlake", Qt::CaseInsensitive))
161  {
162  LOG(VB_GENERAL, LOG_WARNING, LOC + "Disallowing VAAPI decode only for Ironlake");
163  return failure;
164  }
165  }
166  else
167  {
168  // Direct rendering needs interop support
169  MythPlayerUI* player = GetPlayerUI(*Context);
171  return failure;
172  }
173 
174  // Check profile support
175  bool ok = false;
176  const VAAPIProfiles& profiles = MythVAAPIContext::GetProfiles();
177  MythCodecContext::CodecProfile mythprofile =
178  MythCodecContext::FFmpegToMythProfile((*Context)->codec_id, (*Context)->profile);
179  auto haveprofile = [=](MythCodecContext::CodecProfile Profile, QSize Size)
180  {
181  return std::any_of(profiles.cbegin(), profiles.cend(),
182  [&Profile,Size](auto vaprofile)
183  { return vaprofile.first == Profile &&
184  vaprofile.second.first.width() <= Size.width() &&
185  vaprofile.second.first.height() <= Size.height() &&
186  vaprofile.second.second.width() >= Size.width() &&
187  vaprofile.second.second.height() >= Size.height(); } );
188  };
189 
190  ok = haveprofile(mythprofile, QSize((*Context)->width, (*Context)->height));
191  // use JPEG support as a proxy for MJPEG (full range YUV)
192  if (ok && (AV_PIX_FMT_YUVJ420P == (*Context)->pix_fmt || AV_PIX_FMT_YUVJ422P == (*Context)->pix_fmt ||
193  AV_PIX_FMT_YUVJ444P == (*Context)->pix_fmt))
194  {
195  ok = haveprofile(MythCodecContext::MJPEG, QSize());
196  }
197 
198  QString desc = QString("'%1 %2 %3 %4x%5'")
199  .arg(codec).arg(profile).arg(pixfmt).arg((*Context)->width).arg((*Context)->height);
200 
201  if (ok)
202  {
203  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("VAAPI supports decoding %1").arg(desc));
204  (*Context)->pix_fmt = AV_PIX_FMT_VAAPI;
205  return success;
206  }
207 
208  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("VAAPI does NOT support %1").arg(desc));
209  return failure;
210 }
211 
212 AVPixelFormat MythVAAPIContext::GetFormat(AVCodecContext *Context, const AVPixelFormat *PixFmt)
213 {
214  while (*PixFmt != AV_PIX_FMT_NONE)
215  {
216  if (*PixFmt == AV_PIX_FMT_VAAPI)
218  return AV_PIX_FMT_VAAPI;
219  PixFmt++;
220  }
221  return AV_PIX_FMT_NONE;
222 }
223 
224 AVPixelFormat MythVAAPIContext::GetFormat2(AVCodecContext *Context, const AVPixelFormat *PixFmt)
225 {
226  while (*PixFmt != AV_PIX_FMT_NONE)
227  {
228  if (*PixFmt == AV_PIX_FMT_VAAPI)
229  if (InitialiseContext2(Context) >= 0)
230  return AV_PIX_FMT_VAAPI;
231  PixFmt++;
232  }
233  return AV_PIX_FMT_NONE;
234 }
235 
239 {
240  if (!Context || !gCoreContext->IsUIThread())
241  return -1;
242 
243  // We need a render device
245  if (!render)
246  return -1;
247 
248  // The interop must have a reference to the ui player so it can be deleted
249  // from the main thread.
250  MythPlayerUI* player = GetPlayerUI(Context);
251  if (!player)
252  return -1;
253 
254  // Check interop support
257  return -1;
258 
259  // Create interop
260  MythVAAPIInterop *interop = MythVAAPIInterop::Create(render, type);
261  if (!interop)
262  return -1;
263  if (!interop->GetDisplay())
264  {
265  interop->DecrRef();
266  return -1;
267  }
268 
269  // Set the player required to process interop release
270  interop->SetPlayer(player);
271 
272  // Create hardware device context
273  AVBufferRef* hwdeviceref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI);
274  if (!hwdeviceref || !hwdeviceref->data)
275  {
276  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VAAPI hardware device context");
277  return -1;
278  }
279 
280  auto* hwdevicecontext = reinterpret_cast<AVHWDeviceContext*>(hwdeviceref->data);
281  if (!hwdevicecontext || !hwdevicecontext->hwctx)
282  return -1;
283  auto *vaapidevicectx = reinterpret_cast<AVVAAPIDeviceContext*>(hwdevicecontext->hwctx);
284  if (!vaapidevicectx)
285  return -1;
286 
287  // Set the display
288  vaapidevicectx->display = interop->GetDisplay();
289 
290  // Initialise hardware device context
291  int res = av_hwdevice_ctx_init(hwdeviceref);
292  if (res < 0)
293  {
294  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to initialise VAAPI hardware context");
295  av_buffer_unref(&hwdeviceref);
296  interop->DecrRef();
297  return res;
298  }
299 
300  // Allocate the hardware frames context for FFmpeg
301  Context->hw_frames_ctx = av_hwframe_ctx_alloc(hwdeviceref);
302  if (!Context->hw_frames_ctx)
303  {
304  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VAAPI hardware frames context");
305  av_buffer_unref(&hwdeviceref);
306  interop->DecrRef();
307  return -1;
308  }
309 
310  // Setup the frames context
311  auto* hw_frames_ctx = reinterpret_cast<AVHWFramesContext*>(Context->hw_frames_ctx->data);
312  auto* vaapi_frames_ctx = reinterpret_cast<AVVAAPIFramesContext*>(hw_frames_ctx->hwctx);
313 
314  // Workarounds for specific drivers, surface formats and codecs
315  // NV12 seems to work best across GPUs and codecs with the exception of
316  // MPEG2 on Ironlake where it seems to return I420 labelled as NV12. I420 is
317  // buggy on Sandybridge (stride?) and produces a mixture of I420/NV12 frames
318  // for H.264 on Ironlake.
319  // This may need extending for AMD etc
320 
321  QString vendor = interop->GetVendor();
322  // Intel NUC
323  if (vendor.contains("iHD", Qt::CaseInsensitive) && vendor.contains("Intel", Qt::CaseInsensitive))
324  {
325  vaapi_frames_ctx->attributes = nullptr;
326  vaapi_frames_ctx->nb_attributes = 0;
327  }
328  // i965 series
329  else
330  {
331  int format = VA_FOURCC_NV12;
332  if (vendor.contains("ironlake", Qt::CaseInsensitive))
333  if (CODEC_IS_MPEG(Context->codec_id))
334  format = VA_FOURCC_I420;
335 
336  if (format != VA_FOURCC_NV12)
337  {
338  auto vaapiid = static_cast<MythCodecID>(kCodec_MPEG1_VAAPI + (mpeg_version(Context->codec_id) - 1));
339  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Forcing surface format for %1 and %2 with driver '%3'")
340  .arg(toString(vaapiid)).arg(MythOpenGLInterop::TypeToString(type)).arg(vendor));
341  }
342 
343  std::array<VASurfaceAttrib,3> prefs {{
344  { VASurfaceAttribPixelFormat, VA_SURFACE_ATTRIB_SETTABLE, { VAGenericValueTypeInteger, { format } } },
345  { VASurfaceAttribUsageHint, VA_SURFACE_ATTRIB_SETTABLE, { VAGenericValueTypeInteger, { VA_SURFACE_ATTRIB_USAGE_HINT_DISPLAY } } },
346  { VASurfaceAttribMemoryType, VA_SURFACE_ATTRIB_SETTABLE, { VAGenericValueTypeInteger, { VA_SURFACE_ATTRIB_MEM_TYPE_VA} } } }};
347  vaapi_frames_ctx->attributes = prefs.data();
348  vaapi_frames_ctx->nb_attributes = 3;
349  }
350 
351  hw_frames_ctx->sw_format = FramesFormat(Context->sw_pix_fmt);
352  int referenceframes = AvFormatDecoder::GetMaxReferenceFrames(Context);
353  hw_frames_ctx->initial_pool_size = static_cast<int>(VideoBuffers::GetNumBuffers(FMT_VAAPI, referenceframes, true));
354  hw_frames_ctx->format = AV_PIX_FMT_VAAPI;
355  hw_frames_ctx->width = Context->coded_width;
356  hw_frames_ctx->height = Context->coded_height;
357  // The frames context now holds the reference to MythVAAPIInterop
358  hw_frames_ctx->user_opaque = interop;
359  // Set the callback to ensure it is released
360  hw_frames_ctx->free = &MythCodecContext::FramesContextFinished;
361 
362  // Initialise hardwar frames context
363  res = av_hwframe_ctx_init(Context->hw_frames_ctx);
364  if (res < 0)
365  {
366  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to initialise VAAPI frames context");
367  av_buffer_unref(&hwdeviceref);
368  av_buffer_unref(&(Context->hw_frames_ctx));
369  return res;
370  }
371 
372  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("VAAPI FFmpeg buffer pool created with %1 %2x%3 surfaces (%4 references)")
373  .arg(vaapi_frames_ctx->nb_surfaces).arg(Context->coded_width).arg(Context->coded_height)
374  .arg(referenceframes));
375  av_buffer_unref(&hwdeviceref);
376 
378 
379  return 0;
380 }
381 
390 {
391  if (!Context)
392  return -1;
393 
394  AVBufferRef *device = MythCodecContext::CreateDevice(AV_HWDEVICE_TYPE_VAAPI, nullptr,
395  gCoreContext->GetSetting("VAAPIDevice"));
396  Context->hw_frames_ctx = av_hwframe_ctx_alloc(device);
397  if (!Context->hw_frames_ctx)
398  {
399  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VAAPI hardware frames context");
400  av_buffer_unref(&device);
401  return -1;
402  }
403 
404  int referenceframes = AvFormatDecoder::GetMaxReferenceFrames(Context);
405  auto* hw_frames_ctx = reinterpret_cast<AVHWFramesContext*>(Context->hw_frames_ctx->data);
406  auto* vaapi_frames_ctx = reinterpret_cast<AVVAAPIFramesContext*>(hw_frames_ctx->hwctx);
407  hw_frames_ctx->sw_format = FramesFormat(Context->sw_pix_fmt);
408  hw_frames_ctx->format = AV_PIX_FMT_VAAPI;
409  hw_frames_ctx->width = Context->coded_width;
410  hw_frames_ctx->height = Context->coded_height;
411  hw_frames_ctx->initial_pool_size = static_cast<int>(VideoBuffers::GetNumBuffers(FMT_VAAPI, referenceframes));
412  hw_frames_ctx->free = &MythCodecContext::FramesContextFinished;
413  if (av_hwframe_ctx_init(Context->hw_frames_ctx) < 0)
414  {
415  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to initialise VAAPI frames context");
416  av_buffer_unref(&device);
417  av_buffer_unref(&(Context->hw_frames_ctx));
418  return -1;
419  }
420 
421  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("VAAPI FFmpeg buffer pool created with %1 %2x%3 surfaces (%4 references)")
422  .arg(vaapi_frames_ctx->nb_surfaces).arg(Context->coded_width).arg(Context->coded_height)
423  .arg(referenceframes));
424  av_buffer_unref(&device);
425 
427 
428  return 0;
429 }
430 
438 QString MythVAAPIContext::HaveVAAPI(bool ReCheck /*= false*/)
439 {
440  static QString s_vendor;
441  static bool s_checked = false;
442  if (s_checked && !ReCheck)
443  return s_vendor;
444  s_checked = true;
445 
446  AVBufferRef *context = MythCodecContext::CreateDevice(AV_HWDEVICE_TYPE_VAAPI, nullptr,
447  gCoreContext->GetSetting("VAAPIDevice"));
448  if (context)
449  {
450  auto *hwdevice = reinterpret_cast<AVHWDeviceContext*>(context->data);
451  auto *hwctx = reinterpret_cast<AVVAAPIDeviceContext*>(hwdevice->hwctx);
452  s_vendor = QString(vaQueryVendorString(hwctx->display));
453  if (s_vendor.contains("vdpau", Qt::CaseInsensitive))
454  {
455  s_vendor = QString();
456  LOG(VB_GENERAL, LOG_INFO, LOC + "VAAPI is using a VDPAU backend - ignoring VAAPI");
457  }
458  else if (s_vendor.isEmpty())
459  {
460  LOG(VB_GENERAL, LOG_INFO, LOC + "Unknown VAAPI vendor - ignoring VAAPI");
461  }
462  else
463  {
464  LOG(VB_GENERAL, LOG_INFO, LOC + "Supported/available VAAPI decoders:");
465  const VAAPIProfiles& profiles = MythVAAPIContext::GetProfiles();
466  for (auto profile : qAsConst(profiles))
467  {
468  if (profile.first != MythCodecContext::MJPEG)
469  {
470  LOG(VB_GENERAL, LOG_INFO, LOC +
472  }
473  }
474  }
475  av_buffer_unref(&context);
476  }
477  else
478  {
479  LOG(VB_GENERAL, LOG_INFO, LOC + "VAAPI functionality checked failed");
480  }
481 
482  return s_vendor;
483 }
484 
486 {
487  static QMutex lock(QMutex::Recursive);
488  static bool s_initialised = false;
489  static VAAPIProfiles s_profiles;
490 
491  QMutexLocker locker(&lock);
492  if (s_initialised)
493  return s_profiles;
494  s_initialised = true;
495 
496  auto VAToMythProfile = [](VAProfile Profile)
497  {
498  switch (Profile)
499  {
500  case VAProfileMPEG2Simple: return MythCodecContext::MPEG2Simple;
501  case VAProfileMPEG2Main: return MythCodecContext::MPEG2Main;
502  case VAProfileMPEG4Simple: return MythCodecContext::MPEG4Simple;
503  case VAProfileMPEG4AdvancedSimple: return MythCodecContext::MPEG4AdvancedSimple;
504  case VAProfileMPEG4Main: return MythCodecContext::MPEG4Main;
505  case VAProfileH263Baseline: return MythCodecContext::H263;
506  case VAProfileH264ConstrainedBaseline: return MythCodecContext::H264ConstrainedBaseline;
507  case VAProfileH264Main: return MythCodecContext::H264Main;
508  case VAProfileH264High: return MythCodecContext::H264High;
509  case VAProfileVC1Simple: return MythCodecContext::VC1Simple;
510  case VAProfileVC1Main: return MythCodecContext::VC1Main;
511  case VAProfileVC1Advanced: return MythCodecContext::VC1Advanced;
512  case VAProfileVP8Version0_3: return MythCodecContext::VP8;
513  #if VA_CHECK_VERSION(0, 38, 0)
514  case VAProfileVP9Profile0: return MythCodecContext::VP9_0;
515  #endif
516  #if VA_CHECK_VERSION(0, 39, 0)
517  case VAProfileVP9Profile2: return MythCodecContext::VP9_2;
518  #endif
519  #if VA_CHECK_VERSION(0, 37, 0)
520  case VAProfileHEVCMain: return MythCodecContext::HEVCMain;
521  case VAProfileHEVCMain10: return MythCodecContext::HEVCMain10;
522  #endif
523  case VAProfileJPEGBaseline: return MythCodecContext::MJPEG;
524  default: break;
525  }
527  };
528 
529  AVBufferRef *hwdevicectx = MythCodecContext::CreateDevice(AV_HWDEVICE_TYPE_VAAPI, nullptr,
530  gCoreContext->GetSetting("VAAPIDevice"));
531  if(!hwdevicectx)
532  return s_profiles;
533 
534  auto *device = reinterpret_cast<AVHWDeviceContext*>(hwdevicectx->data);
535  auto *hwctx = reinterpret_cast<AVVAAPIDeviceContext*>(device->hwctx);
536 
537  int profilecount = vaMaxNumProfiles(hwctx->display);
538  auto *profilelist = static_cast<VAProfile*>(av_malloc_array(static_cast<size_t>(profilecount), sizeof(VAProfile)));
539  if (vaQueryConfigProfiles(hwctx->display, profilelist, &profilecount) == VA_STATUS_SUCCESS)
540  {
541  for (int i = 0; i < profilecount; ++i)
542  {
543  VAProfile profile = profilelist[i];
544  if (profile == VAProfileNone || profile == VAProfileH264StereoHigh || profile == VAProfileH264MultiviewHigh)
545  continue;
546  int count = 0;
547  int entrysize = vaMaxNumEntrypoints(hwctx->display);
548  auto *entrylist = static_cast<VAEntrypoint*>(av_malloc_array(static_cast<size_t>(entrysize), sizeof(VAEntrypoint)));
549  if (vaQueryConfigEntrypoints(hwctx->display, profile, entrylist, &count) == VA_STATUS_SUCCESS)
550  {
551  for (int j = 0; j < count; ++j)
552  {
553  if (entrylist[j] != VAEntrypointVLD)
554  continue;
555 
556  QSize minsize;
557  QSize maxsize;
558  VAConfigID config = 0;
559  if (vaCreateConfig(hwctx->display, profile, VAEntrypointVLD, nullptr, 0, &config) != VA_STATUS_SUCCESS)
560  continue;
561 
562  uint attrcount = 0;
563  if (vaQuerySurfaceAttributes(hwctx->display, config, nullptr, &attrcount) == VA_STATUS_SUCCESS)
564  {
565  auto *attrlist = static_cast<VASurfaceAttrib*>(av_malloc(attrcount * sizeof(VASurfaceAttrib)));
566  if (vaQuerySurfaceAttributes(hwctx->display, config, attrlist, &attrcount) == VA_STATUS_SUCCESS)
567  {
568  for (uint k = 0; k < attrcount; ++k)
569  {
570  if (attrlist[k].type == VASurfaceAttribMaxWidth)
571  maxsize.setWidth(attrlist[k].value.value.i);
572  if (attrlist[k].type == VASurfaceAttribMaxHeight)
573  maxsize.setHeight(attrlist[k].value.value.i);
574  if (attrlist[k].type == VASurfaceAttribMinWidth)
575  minsize.setWidth(attrlist[k].value.value.i);
576  if (attrlist[k].type == VASurfaceAttribMinHeight)
577  minsize.setHeight(attrlist[k].value.value.i);
578  }
579  }
580  av_freep(&attrlist);
581  }
582  vaDestroyConfig(hwctx->display, config);
583  s_profiles.append(VAAPIProfile(VAToMythProfile(profile), QPair<QSize,QSize>(minsize, maxsize)));
584  }
585  }
586  av_freep(&entrylist);
587  }
588  }
589  av_freep(&profilelist);
590  av_buffer_unref(&hwdevicectx);
591 
592  // Once only check for EGL support for best performance
594  if (!s_profiles.isEmpty() && render)
595  {
596  if (render->IsEGL())
597  {
598  LOG(VB_GENERAL, LOG_INFO, LOC + "EGL DMABUF available for best VAAPI performance");
599  }
600  else
601  {
602  LOG(VB_GENERAL, LOG_WARNING, LOC + "No EGL support. VAAPI performance will be reduced");
603  LOG(VB_GENERAL, LOG_WARNING, LOC + "Consider setting MYTHTV_FORCE_EGL=1 to try and enable");
604  }
605  }
606  return s_profiles;
607 }
608 
609 void MythVAAPIContext::GetDecoderList(QStringList &Decoders)
610 {
611  const VAAPIProfiles& profiles = MythVAAPIContext::GetProfiles();
612  if (profiles.isEmpty())
613  return;
614  Decoders.append("VAAPI:");
615  for (auto profile : qAsConst(profiles))
616  if (profile.first != MythCodecContext::MJPEG)
617  Decoders.append(MythCodecContext::GetProfileDescription(profile.first, profile.second.second));
618 }
619 
620 void MythVAAPIContext::InitVideoCodec(AVCodecContext *Context, bool SelectedStream, bool &DirectRendering)
621 {
623  {
624  Context->get_buffer2 = MythCodecContext::GetBuffer;
625  Context->get_format = MythVAAPIContext::GetFormat;
626  Context->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
627  return;
628  }
630  {
632  Context->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
633  DirectRendering = false;
634  return;
635  }
636 
637  MythCodecContext::InitVideoCodec(Context, SelectedStream, DirectRendering);
638 }
639 
640 bool MythVAAPIContext::RetrieveFrame(AVCodecContext* /*unused*/, MythVideoFrame *Frame, AVFrame *AvFrame)
641 {
642  if (AvFrame->format != AV_PIX_FMT_VAAPI)
643  return false;
645  return RetrieveHWFrame(Frame, AvFrame);
646  return false;
647 }
648 
658 {
659  int ret = 0;
660 
661  while (true)
662  {
663  if (m_filterGraph && ((m_filterWidth != Context->coded_width) || (m_filterHeight != Context->coded_height)))
664  {
665  LOG(VB_GENERAL, LOG_WARNING, LOC + "Input changed - deleting filter");
667  }
668 
669  if (m_filterGraph)
670  {
671  ret = av_buffersink_get_frame(m_filterSink, Frame);
672  if (ret >= 0)
673  {
675  {
676  Frame->pts = m_filterPriorPTS[1] + (m_filterPriorPTS[1] - m_filterPriorPTS[0]) / 2;
677  Frame->scte_cc_len = 0;
678  Frame->atsc_cc_len = 0;
679  av_frame_remove_side_data(Frame, AV_FRAME_DATA_A53_CC);
680  }
681  else
682  {
683  Frame->pts = m_filterPriorPTS[1];
685  }
686  }
687  if (ret != AVERROR(EAGAIN))
688  break;
689  }
690 
691  // EAGAIN or no filter graph
692  ret = avcodec_receive_frame(Context, Frame);
693  if (ret == 0)
694  {
695  // preserve interlaced flags
696  m_lastInterlaced = Frame->interlaced_frame;
697  m_lastTopFieldFirst = (Frame->top_field_first != 0);
698  }
699 
700  if (ret < 0)
701  break;
702 
703  // some streams with missing timestamps break frame timing when doublerate
704  // so replace with dts if available
705  int64_t pts = Frame->pts;
706  if (pts == AV_NOPTS_VALUE && Frame->pkt_dts != AV_NOPTS_VALUE && m_deinterlacer2x)
707  pts = Frame->pkt_dts;
709  m_filterPriorPTS[1] = pts;
710 
711  if (!m_filterGraph)
712  break;
713 
714  ret = av_buffersrc_add_frame(m_filterSource, Frame);
715  if (ret < 0)
716  break;
717  }
718 
719  return ret;
720 }
721 
723 {
724  if (!Frame || !codec_is_vaapi_dec(m_codecID) || !Context->hw_frames_ctx)
725  return;
726 
727  // if VAAPI driver deints are errored or not available (older boards), then
728  // allow CPU/GLSL
729  if (m_filterError)
730  {
731  Frame->m_deinterlaceAllowed = Frame->m_deinterlaceAllowed & ~DEINT_DRIVER;
732  return;
733  }
736  {
737  // enabling VPP deinterlacing with these codecs breaks decoding for some reason.
738  // HEVC interlacing is not currently detected by FFmpeg and I can't find
739  // any interlaced VP8/9 material. Shaders and/or CPU deints will be available
740  // as appropriate
741  m_filterError = true;
742  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Disabling VAAPI VPP deinterlacer for %1")
743  .arg(toString(m_codecID)));
744  return;
745  }
746 
747  // if this frame has already been deinterlaced, then flag the deinterlacer and
748  // that the frame has already been deinterlaced.
749  // the FFmpeg vaapi deint filter will mark frames as progressive, so restore the
750  // interlaced flags to ensure auto deinterlacing continues to work
751  if (m_deinterlacer)
752  {
753  Frame->m_interlaced = m_lastInterlaced;
754  Frame->m_topFieldFirst = m_lastTopFieldFirst;
755  Frame->m_deinterlaceInuse = m_deinterlacer | DEINT_DRIVER;
756  Frame->m_deinterlaceInuse2x = m_deinterlacer2x;
757  Frame->m_alreadyDeinterlaced = true;
758  }
759 
760  // N.B. this picks up the scan tracking in MythPlayer. So we can
761  // auto enable deinterlacing etc and override Progressive/Interlaced - but
762  // no reversed interlaced.
763  MythDeintType vaapideint = DEINT_NONE;
764  MythDeintType singlepref = Frame->GetSingleRateOption(DEINT_DRIVER);
765  MythDeintType doublepref = Frame->GetDoubleRateOption(DEINT_DRIVER);
766  bool doublerate = true;
767  bool other = false;
768 
769  // For decode only, a CPU or shader deint may also be used/preferred
770  if (doublepref)
771  vaapideint = doublepref;
772  else if (Frame->GetDoubleRateOption(DEINT_CPU | DEINT_SHADER))
773  other = true;
774 
775  if (!vaapideint && !other && singlepref)
776  {
777  doublerate = false;
778  vaapideint = singlepref;
779  }
780 
781  // nothing to see
782  if (vaapideint == DEINT_NONE)
783  {
784  if (m_deinterlacer)
786  return;
787  }
788 
789  // already setup
790  if ((m_deinterlacer == vaapideint) && (m_deinterlacer2x == doublerate))
791  return;
792 
793  // Start from scratch
795  m_framesCtx = av_buffer_ref(Context->hw_frames_ctx);
796  if (!MythVAAPIInterop::SetupDeinterlacer(vaapideint, doublerate, Context->hw_frames_ctx,
797  Context->coded_width, Context->coded_height,
799  {
800  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to create deinterlacer %1 - disabling")
801  .arg(MythVideoFrame::DeinterlacerName(vaapideint | DEINT_DRIVER, doublerate, FMT_VAAPI)));
803  m_filterError = true;
804  }
805  else
806  {
807  m_deinterlacer = vaapideint;
808  m_deinterlacer2x = doublerate;
809  m_filterWidth = Context->coded_width;
810  m_filterHeight = Context->coded_height;
811  }
812 }
813 
814 bool MythVAAPIContext::IsDeinterlacing(bool &DoubleRate, bool StreamChange)
815 {
816  // the VAAPI deinterlacer can be turned on and off, so on stream changes
817  // return false to ensure auto deint works for the new format (the deinterlacer
818  // refers to the current format)
819  if (m_deinterlacer && !StreamChange)
820  {
821  DoubleRate = m_deinterlacer2x;
822  return true;
823  }
824  DoubleRate = false;
825  return false;
826 }
827 
829 {
830  // HEVC appears to be OK
831  return kCodec_H264_VAAPI == m_codecID;
832 }
833 
835 {
836  // Only MPEG2 tested so far
838 }
839 
841 {
842  if (m_filterGraph)
843  LOG(VB_GENERAL, LOG_INFO, LOC + "Destroying VAAPI deinterlacer");
844  avfilter_graph_free(&m_filterGraph);
845  m_filterGraph = nullptr;
846  m_filterSink = nullptr;
847  m_filterSource = nullptr;
848  m_filterPTSUsed = 0;
849  m_filterPriorPTS.fill(0);
850  m_filterWidth = 0;
851  m_filterHeight = 0;
852  if (m_framesCtx)
853  av_buffer_unref(&m_framesCtx);
855  m_deinterlacer2x = false;
856 }
MythVAAPIContext::InitVideoCodec
void InitVideoCodec(AVCodecContext *Context, bool SelectedStream, bool &DirectRendering) override
Definition: mythvaapicontext.cpp:620
MythCodecContext::VC1Simple
@ VC1Simple
Definition: mythcodeccontext.h:102
DEINT_DRIVER
@ DEINT_DRIVER
Definition: mythframe.h:70
MythCodecContext::MPEG4Simple
@ MPEG4Simple
Definition: mythcodeccontext.h:66
MythVAAPIContext::PostProcessFrame
void PostProcessFrame(AVCodecContext *Context, MythVideoFrame *Frame) override
Definition: mythvaapicontext.cpp:722
MythCodecContext::MPEG2Simple
@ MPEG2Simple
Definition: mythcodeccontext.h:59
mythvaapiinterop.h
MythCodecContext::m_codecID
MythCodecID m_codecID
Definition: mythcodeccontext.h:167
MythCodecContext::VC1Advanced
@ VC1Advanced
Definition: mythcodeccontext.h:105
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
mythplayerui.h
mpeg_version
uint mpeg_version(int codec_id)
Definition: mythcodecid.cpp:455
MythCodecContext::VP9_0
@ VP9_0
Definition: mythcodeccontext.h:108
DEINT_SHADER
@ DEINT_SHADER
Definition: mythframe.h:69
MythCodecContext::HEVCMain10
@ HEVCMain10
Definition: mythcodeccontext.h:96
MythVAAPIContext::m_filterError
bool m_filterError
Definition: mythvaapicontext.h:63
MythVAAPIContext::DestroyDeinterlacer
void DestroyDeinterlacer(void)
Definition: mythvaapicontext.cpp:840
MythCodecContext::NoProfile
@ NoProfile
Definition: mythcodeccontext.h:56
MythVAAPIInterop::Create
static MythVAAPIInterop * Create(MythRenderOpenGL *Context, Type InteropType)
Definition: mythvaapiinterop.cpp:56
MythCodecContext::MPEG4AdvancedSimple
@ MPEG4AdvancedSimple
Definition: mythcodeccontext.h:81
MythVAAPIContext::~MythVAAPIContext
~MythVAAPIContext() override
Definition: mythvaapicontext.cpp:37
MythCodecContext::CodecProfile
CodecProfile
Definition: mythcodeccontext.h:55
Frame
Definition: zmdefines.h:94
VAAPIProfiles
QVector< VAAPIProfile > VAAPIProfiles
Definition: mythvaapicontext.h:21
MythCodecContext::NewHardwareFramesContext
static void NewHardwareFramesContext(void)
Track the number of concurrent frames contexts.
Definition: mythcodeccontext.cpp:418
MythCodecContext::VC1Main
@ VC1Main
Definition: mythcodeccontext.h:103
DEINT_NONE
@ DEINT_NONE
Definition: mythframe.h:64
arg
arg(title).arg(filename).arg(doDelete))
LOC
#define LOC
Definition: mythvaapicontext.cpp:22
MythCoreContext::IsUIThread
bool IsUIThread(void)
Definition: mythcorecontext.cpp:1353
Context
QHash< QString, Action * > Context
Definition: action.h:77
MythCodecContext::InitVideoCodec
virtual void InitVideoCodec(AVCodecContext *Context, bool SelectedStream, bool &DirectRendering)
Definition: mythcodeccontext.cpp:292
MythDate::Format
Format
Definition: mythdate.h:13
kCodec_HEVC_VAAPI_DEC
@ kCodec_HEVC_VAAPI_DEC
Definition: mythcodecid.h:94
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythCodecContext::FramesContextFinished
static void FramesContextFinished(AVHWFramesContext *Context)
Definition: mythcodeccontext.cpp:425
MythCodecContext::MPEG4Main
@ MPEG4Main
Definition: mythcodeccontext.h:69
MythVAAPIContext::m_filterPriorPTS
std::array< int64_t, 2 > m_filterPriorPTS
Definition: mythvaapicontext.h:65
MythCodecContext::VP9_2
@ VP9_2
Definition: mythcodeccontext.h:110
MythCodecContext::FFmpegToMythProfile
static CodecProfile FFmpegToMythProfile(AVCodecID CodecID, int Profile)
Definition: mythcodeccontext.cpp:660
MythVAAPIContext::GetFormat
static enum AVPixelFormat GetFormat(AVCodecContext *Context, const AVPixelFormat *PixFmt)
Definition: mythvaapicontext.cpp:212
kCodec_VP9_VAAPI_DEC
@ kCodec_VP9_VAAPI_DEC
Definition: mythcodecid.h:93
MythVAAPIInterop::SetupDeinterlacer
static bool SetupDeinterlacer(MythDeintType Deinterlacer, bool DoubleRate, AVBufferRef *FramesContext, int Width, int Height, AVFilterGraph *&Graph, AVFilterContext *&Source, AVFilterContext *&Sink)
Definition: mythvaapiinterop.cpp:170
MythCodecContext::H264ConstrainedBaseline
@ H264ConstrainedBaseline
Definition: mythcodeccontext.h:85
MythVAAPIContext::GetSupportedCodec
static MythCodecID GetSupportedCodec(AVCodecContext **Context, AVCodec **Codec, const QString &Decoder, uint StreamType)
Confirm whether VAAPI support is available given Decoder and Context.
Definition: mythvaapicontext.cpp:131
kCodec_MPEG2_VAAPI_DEC
@ kCodec_MPEG2_VAAPI_DEC
Definition: mythcodecid.h:86
mythvaapicontext.h
MythVAAPIContext::GetDecoderList
static void GetDecoderList(QStringList &Decoders)
Definition: mythvaapicontext.cpp:609
MythVAAPIContext::InitialiseContext
static int InitialiseContext(AVCodecContext *Context)
Create a VAAPI hardware context with appropriate OpenGL interop.
Definition: mythvaapicontext.cpp:238
kCodec_MPEG1_VAAPI
@ kCodec_MPEG1_VAAPI
Definition: mythcodecid.h:69
DEINT_CPU
@ DEINT_CPU
Definition: mythframe.h:68
MythVAAPIInterop
Definition: mythvaapiinterop.h:37
videobuffers.h
MythCodecID
MythCodecID
Definition: mythcodecid.h:11
AVFrame
struct AVFrame AVFrame
Definition: BorderDetector.h:15
mythrenderopengl.h
toString
QString toString(MarkTypes type)
Definition: programtypes.cpp:26
MythPlayerUI
Definition: mythplayerui.h:12
MythVAAPIContext::DecoderWillResetOnFlush
bool DecoderWillResetOnFlush(void) override
Definition: mythvaapicontext.cpp:828
Decoder
Definition: decoder.h:66
MythVAAPIContext::FilteredReceiveFrame
int FilteredReceiveFrame(AVCodecContext *Context, AVFrame *Frame) override
Retrieve decoded frame and optionally deinterlace.
Definition: mythvaapicontext.cpp:657
MythOpenGLInterop::SetPlayer
void SetPlayer(MythPlayerUI *Player)
Definition: mythopenglinterop.cpp:278
mythlogging.h
hardwareprofile.scan.profile
profile
Definition: scan.py:99
MythVAAPIInterop::GetDisplay
VADisplay GetDisplay(void)
Definition: mythvaapiinterop.cpp:91
MythOpenGLInterop::Unsupported
@ Unsupported
Definition: mythopenglinterop.h:31
AvFormatDecoder::GetMaxReferenceFrames
static int GetMaxReferenceFrames(AVCodecContext *Context)
Definition: avformatdecoder.cpp:1424
MythVAAPIContext::IsDeinterlacing
bool IsDeinterlacing(bool &DoubleRate, bool StreamChange=false) override
Definition: mythvaapicontext.cpp:814
CODEC_IS_MPEG
#define CODEC_IS_MPEG(id)
Definition: mythcodecid.h:359
kCodec_MPEG1
@ kCodec_MPEG1
Definition: mythcodecid.h:21
MythCodecContext::GetBuffer
static int GetBuffer(struct AVCodecContext *Context, AVFrame *Frame, int Flags)
A generic hardware buffer initialisation method when using AVHWFramesContext.
Definition: mythcodeccontext.cpp:312
MythCodecContext::H264Main
@ H264Main
Definition: mythcodeccontext.h:86
MythVAAPIContext::HaveVAAPI
static QString HaveVAAPI(bool ReCheck=false)
Check whether VAAPI is available and not emulated via VDPAU.
Definition: mythvaapicontext.cpp:438
MythOpenGLInterop::GetInteropType
static Type GetInteropType(VideoFrameType Format, MythPlayerUI *Player)
Check whether we support direct rendering for the given VideoFrameType.
Definition: mythopenglinterop.cpp:74
MythVAAPIContext::m_filterSource
AVFilterContext * m_filterSource
Definition: mythvaapicontext.h:61
MythVAAPIContext::GetFormat2
static enum AVPixelFormat GetFormat2(AVCodecContext *Context, const AVPixelFormat *PixFmt)
Definition: mythvaapicontext.cpp:224
MythVAAPIContext::MythVAAPIContext
MythVAAPIContext(DecoderBase *Parent, MythCodecID CodecID)
Definition: mythvaapicontext.cpp:32
MythEGL::IsEGL
bool IsEGL(void)
Definition: mythegl.cpp:29
VAAPIProfile
QPair< MythCodecContext::CodecProfile, QPair< QSize, QSize > > VAAPIProfile
Definition: mythvaapicontext.h:20
VA_FOURCC_I420
#define VA_FOURCC_I420
Definition: mythvaapiinterop.h:22
MythCodecContext::RetrieveHWFrame
virtual bool RetrieveHWFrame(MythVideoFrame *Frame, AVFrame *AvFrame)
Definition: mythcodeccontext.cpp:605
MythVAAPIContext::m_filterGraph
AVFilterGraph * m_filterGraph
Definition: mythvaapicontext.h:62
MythCodecContext::H263
@ H263
Definition: mythcodeccontext.h:82
MythVAAPIContext::DecoderWillResetOnAspect
bool DecoderWillResetOnAspect(void) override
Definition: mythvaapicontext.cpp:834
uint
unsigned int uint
Definition: compat.h:140
kCodec_VP8_VAAPI_DEC
@ kCodec_VP8_VAAPI_DEC
Definition: mythcodecid.h:92
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:56
MythVAAPIContext::InitialiseContext2
static int InitialiseContext2(AVCodecContext *Context)
Create a VAAPI hardware context without OpenGL interop.
Definition: mythvaapicontext.cpp:389
MythOpenGLInterop::Type
Type
Definition: mythopenglinterop.h:30
MythVAAPIContext::m_filterWidth
int m_filterWidth
Definition: mythvaapicontext.h:67
MythVAAPIContext::m_deinterlacer2x
bool m_deinterlacer2x
Definition: mythvaapicontext.h:57
MythRenderOpenGL
Definition: mythrenderopengl.h:98
kCodec_MPEG2_VAAPI
@ kCodec_MPEG2_VAAPI
Definition: mythcodecid.h:70
MythVAAPIContext::m_filterHeight
int m_filterHeight
Definition: mythvaapicontext.h:68
MythCodecContext::CreateDevice
static AVBufferRef * CreateDevice(AVHWDeviceType Type, MythOpenGLInterop *Interop, const QString &Device=QString())
Definition: mythcodeccontext.cpp:536
MythDeintType
MythDeintType
Definition: mythframe.h:63
MythCodecContext::MPEG2Main
@ MPEG2Main
Definition: mythcodeccontext.h:60
MythVAAPIContext::GetProfiles
static const VAAPIProfiles & GetProfiles(void)
Definition: mythvaapicontext.cpp:485
MythVAAPIInterop::GetVendor
QString GetVendor(void)
Definition: mythvaapiinterop.cpp:96
codec_is_vaapi_dec
#define codec_is_vaapi_dec(id)
Definition: mythcodecid.h:313
codec_is_vaapi
#define codec_is_vaapi(id)
Definition: mythcodecid.h:311
avformatdecoder.h
MythVAAPIContext::m_filterPTSUsed
int64_t m_filterPTSUsed
Definition: mythvaapicontext.h:66
MythVideoFrame::DeinterlacerName
static QString DeinterlacerName(MythDeintType Deint, bool DoubleRate, VideoFrameType Format=FMT_NONE)
Definition: mythframe.cpp:447
kCodec_H264_VAAPI
@ kCodec_H264_VAAPI
Definition: mythcodecid.h:73
MythVAAPIContext::RetrieveFrame
bool RetrieveFrame(AVCodecContext *Context, MythVideoFrame *Frame, AVFrame *AvFrame) override
Definition: mythvaapicontext.cpp:640
MythRenderOpenGL::GetOpenGLRender
static MythRenderOpenGL * GetOpenGLRender(void)
Definition: mythrenderopengl.cpp:66
mythcontext.h
MythCodecContext::MJPEG
@ MJPEG
Definition: mythcodeccontext.h:120
MythVAAPIContext::FramesFormat
static AVPixelFormat FramesFormat(AVPixelFormat Format)
Definition: mythvaapicontext.cpp:117
MythVAAPIContext::m_filterSink
AVFilterContext * m_filterSink
Definition: mythvaapicontext.h:60
MythVAAPIContext::VAAPIProfileForCodec
static VAProfile VAAPIProfileForCodec(const AVCodecContext *Codec)
Definition: mythvaapicontext.cpp:42
MythVAAPIContext::m_lastTopFieldFirst
bool m_lastTopFieldFirst
Definition: mythvaapicontext.h:59
MythOpenGLInterop::TypeToString
static QString TypeToString(Type InteropType)
Definition: mythopenglinterop.cpp:35
MythCodecContext
Definition: mythcodeccontext.h:52
MythCodecContext::H264High
@ H264High
Definition: mythcodeccontext.h:88
MythCodecContext::GetProfileDescription
static QString GetProfileDescription(CodecProfile Profile, QSize Size, VideoFrameType Format=FMT_NONE, uint ColorDepth=0)
Definition: mythcodeccontext.cpp:763
MythVAAPIContext::m_framesCtx
AVBufferRef * m_framesCtx
Definition: mythvaapicontext.h:64
FMT_VAAPI
@ FMT_VAAPI
Definition: mythframe.h:53
MythVideoFrame
Definition: mythframe.h:83
mythmainwindow.h
MythVAAPIContext::m_lastInterlaced
int m_lastInterlaced
Definition: mythvaapicontext.h:58
MythCodecContext::HEVCMain
@ HEVCMain
Definition: mythcodeccontext.h:95
VideoBuffers::GetNumBuffers
static uint GetNumBuffers(int PixelFormat, int MaxReferenceFrames=16, bool Decoder=false)
Definition: videobuffers.cpp:135
MythCodecContext::InitialiseDecoder
static int InitialiseDecoder(AVCodecContext *Context, CreateHWDecoder Callback, const QString &Debug)
Initialise a hardware decoder that is expected to use AVHWFramesContext.
Definition: mythcodeccontext.cpp:503
DecoderBase
Definition: decoderbase.h:121
MythCodecContext::GetPlayerUI
static MythPlayerUI * GetPlayerUI(AVCodecContext *Context)
Definition: mythcodeccontext.cpp:493
MythVAAPIContext::m_deinterlacer
MythDeintType m_deinterlacer
Definition: mythvaapicontext.h:56
MythCodecContext::VP8
@ VP8
Definition: mythcodeccontext.h:106
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:915
kCodec_MPEG1_VAAPI_DEC
@ kCodec_MPEG1_VAAPI_DEC
Definition: mythcodecid.h:85