MythTV  master
mythnvdeccontext.cpp
Go to the documentation of this file.
1 // MythTV
4 
5 #include "avformatdecoder.h"
7 #include "mythplayerui.h"
8 #include "mythvideoout.h"
10 
11 extern "C" {
12 #include "libavutil/log.h"
13 #define FFNV_LOG_FUNC(logctx, msg, ...) av_log(logctx, AV_LOG_ERROR, msg, __VA_ARGS__)
14 #define FFNV_DEBUG_LOG_FUNC(logctx, msg, ...) av_log(logctx, AV_LOG_DEBUG, msg, __VA_ARGS__)
15 #include <ffnvcodec/dynlink_loader.h>
16 }
17 
18 extern "C" {
19 #include "libavutil/hwcontext_cuda.h"
20 #include "libavutil/opt.h"
21 }
22 
23 #define LOC QString("NVDEC: ")
24 
25 
27  : MythCodecContext(Parent, CodecID)
28 {
29 }
30 
32 {
33  av_buffer_unref(&m_framesContext);
34 }
35 
42  const AVCodec **Codec,
43  const QString &Decoder,
44  AVStream *Stream,
45  uint StreamType)
46 {
47  bool decodeonly = Decoder == "nvdec-dec";
48  auto success = static_cast<MythCodecID>((decodeonly ? kCodec_MPEG1_NVDEC_DEC : kCodec_MPEG1_NVDEC) + (StreamType - 1));
49  auto failure = static_cast<MythCodecID>(kCodec_MPEG1 + (StreamType - 1));
50 
51  // no brainers
52  if (!Decoder.startsWith("nvdec") || qEnvironmentVariableIsSet("NO_NVDEC") || !HaveNVDEC() || IsUnsupportedProfile(*Context))
53  return failure;
54 
55  if (!decodeonly)
56  if (!FrameTypeIsSupported(*Context, FMT_NVDEC))
57  return failure;
58 
59  QString codecstr = avcodec_get_name((*Context)->codec_id);
60  QString profile = avcodec_profile_name((*Context)->codec_id, (*Context)->profile);
61  QString pixfmt = av_get_pix_fmt_name((*Context)->pix_fmt);
62 
63  cudaVideoCodec cudacodec = cudaVideoCodec_NumCodecs;
64  switch ((*Context)->codec_id)
65  {
66  case AV_CODEC_ID_MPEG1VIDEO: cudacodec = cudaVideoCodec_MPEG1; break;
67  case AV_CODEC_ID_MPEG2VIDEO: cudacodec = cudaVideoCodec_MPEG2; break;
68  case AV_CODEC_ID_MPEG4: cudacodec = cudaVideoCodec_MPEG4; break;
69  case AV_CODEC_ID_VC1: cudacodec = cudaVideoCodec_VC1; break;
70  case AV_CODEC_ID_H264: cudacodec = cudaVideoCodec_H264; break;
71  case AV_CODEC_ID_HEVC: cudacodec = cudaVideoCodec_HEVC; break;
72  case AV_CODEC_ID_VP8: cudacodec = cudaVideoCodec_VP8; break;
73  case AV_CODEC_ID_VP9: cudacodec = cudaVideoCodec_VP9; break;
74  default: break;
75  }
76 
77  cudaVideoChromaFormat cudaformat = cudaVideoChromaFormat_Monochrome;
79  uint depth = static_cast<uint>(MythVideoFrame::ColorDepth(type) - 8);
80  QString desc = QString("'%1 %2 %3 Depth:%4 %5x%6'")
81  .arg(codecstr, profile, pixfmt).arg(depth + 8)
82  .arg((*Context)->width).arg((*Context)->height);
83 
84  // N.B. on stream changes format is set to CUDA/NVDEC. This may break if the new
85  // stream has an unsupported chroma but the decoder should fail gracefully - just later.
87  cudaformat = cudaVideoChromaFormat_420;
89  cudaformat = cudaVideoChromaFormat_422;
91  cudaformat = cudaVideoChromaFormat_444;
92 
93  if ((cudacodec == cudaVideoCodec_NumCodecs) || (cudaformat == cudaVideoChromaFormat_Monochrome))
94  {
95  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "Unknown codec or format");
96  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("NVDEC does NOT support %1").arg(desc));
97  return failure;
98  }
99 
100  // iterate over known decoder capabilities
101  const auto & profiles = MythNVDECContext::GetProfiles();
102  auto capcheck = [&](const MythNVDECCaps& Cap)
103  { return Cap.Supports(cudacodec, cudaformat, depth, (*Context)->width, (*Context)->height); };
104  if (!std::any_of(profiles.cbegin(), profiles.cend(), capcheck))
105  {
106  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "No matching profile support");
107  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("NVDEC does NOT support %1").arg(desc));
108  return failure;
109  }
110 
111  auto *decoder = dynamic_cast<AvFormatDecoder*>(reinterpret_cast<DecoderBase*>((*Context)->opaque));
112  // and finally try and retrieve the actual FFmpeg decoder
113  QString name = QString((*Codec)->name) + "_cuvid";
114  if (name == "mpeg2video_cuvid")
115  name = "mpeg2_cuvid";
116  for (int i = 0; ; i++)
117  {
118  const AVCodecHWConfig *config = avcodec_get_hw_config(*Codec, i);
119  if (!config)
120  break;
121 
122  if ((config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) &&
123  (config->device_type == AV_HWDEVICE_TYPE_CUDA))
124  {
125  const AVCodec *codec = avcodec_find_decoder_by_name(name.toLocal8Bit());
126  if (codec)
127  {
128  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("NVDEC supports decoding %1").arg(desc));
129  *Codec = codec;
130  decoder->CodecMap()->FreeCodecContext(Stream);
131  *Context = decoder->CodecMap()->GetCodecContext(Stream, *Codec);
132  return success;
133  }
134  break;
135  }
136  }
137 
138  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to find decoder '%1'").arg(name));
139  return failure;
140 }
141 
142 int MythNVDECContext::InitialiseDecoder(AVCodecContext *Context)
143 {
144  if (!gCoreContext->IsUIThread() || !Context)
145  return -1;
146 
147  // We need a player to release the interop. As we are using direct rendering
148  // it must be a MythPlayerUI instance
149  auto * player = GetPlayerUI(Context);
150  if (!player)
151  return -1;
152 
153  // Retrieve OpenGL render context
154  auto * render = dynamic_cast<MythRenderOpenGL*>(player->GetRender());
155  if (!render)
156  return -1;
157  OpenGLLocker locker(render);
158 
159  // Create interop (and CUDA context)
160  auto * interop = MythNVDECInterop::CreateNVDEC(player, render);
161  if (!interop)
162  return -1;
163  if (!interop->IsValid())
164  {
165  interop->DecrRef();
166  return -1;
167  }
168 
169  // Allocate the device context
170  AVBufferRef* hwdeviceref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA);
171  if (!hwdeviceref)
172  {
173  interop->DecrRef();
174  return -1;
175  }
176 
177  // Set release method, interop and CUDA context
178  auto* hwdevicecontext = reinterpret_cast<AVHWDeviceContext*>(hwdeviceref->data);
179  hwdevicecontext->free = &MythCodecContext::DeviceContextFinished;
180  hwdevicecontext->user_opaque = interop;
181  auto *devicehwctx = reinterpret_cast<AVCUDADeviceContext*>(hwdevicecontext->hwctx);
182  devicehwctx->cuda_ctx = interop->GetCUDAContext();
183  devicehwctx->stream = nullptr;
184 
185  if (av_hwdevice_ctx_init(hwdeviceref) < 0)
186  {
187  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to init CUDA hw device");
188  av_buffer_unref(&hwdeviceref);
189  return -1;
190  }
191 
192  Context->hw_device_ctx = hwdeviceref;
193  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Created CUDA device context");
194  return 0;
195 }
196 
197 void MythNVDECContext::InitVideoCodec(AVCodecContext *Context, bool SelectedStream, bool &DirectRendering)
198 {
200  {
201  Context->get_format = MythNVDECContext::GetFormat;
202  DirectRendering = false;
203  return;
204  }
205 
206  MythCodecContext::InitVideoCodec(Context, SelectedStream, DirectRendering);
207 }
208 
209 int MythNVDECContext::HwDecoderInit(AVCodecContext *Context)
210 {
212  {
214  "Create NVDEC decoder");
215  }
217  {
218  AVBufferRef *context = MythCodecContext::CreateDevice(AV_HWDEVICE_TYPE_CUDA, nullptr,
219  gCoreContext->GetSetting("NVDECDevice"));
220  if (context)
221  {
222  Context->hw_device_ctx = context;
223  return 0;
224  }
225  }
226  return -1;
227 }
228 
235 void MythNVDECContext::SetDeinterlacing(AVCodecContext *Context,
236  MythVideoProfile *Profile, bool DoubleRate)
237 {
238  if (!Context)
239  return;
240 
241  // Don't enable for anything that cannot be interlaced
242  // We could use frame rate here but initial frame rate detection is not always accurate
243  // and we lose little by enabling deinterlacing. NVDEC will not deinterlace a
244  // progressive stream and any CUDA capable video card has memory to spare
245  // (assuming it even sets up deinterlacing for a progressive stream)
246  if (Context->height == 720) // 720P
247  return;
248 
249  MythDeintType deinterlacer = DEINT_NONE;
250  MythDeintType singlepref = DEINT_NONE;
251  MythDeintType doublepref = DEINT_NONE;
252  if (Profile)
253  {
255  if (DoubleRate)
257  }
258 
259  // Deinterlacers are not filtered (as we have no frame) - so mask appropriately
260  MythDeintType singledeint = singlepref & (DEINT_BASIC | DEINT_MEDIUM | DEINT_HIGH);
261  MythDeintType doubledeint = doublepref & (DEINT_BASIC | DEINT_MEDIUM | DEINT_HIGH);
262 
263  // With decode only/copy back, we can deinterlace here or the frames can use
264  // either CPU or shader deints. So only accept a driver deinterlacer preference.
265 
266  // When direct rendering, there is no CPU option but shaders can be used.
267  // Assume driver deints are higher quality so accept a driver preference or CPU
268  // if shader is not preferred
269  bool other = false;
271  {
272  if (DoubleRate)
273  {
274  if (doubledeint)
275  {
276  if (doublepref & (DEINT_DRIVER))
277  deinterlacer = doubledeint;
278  else if (doublepref & (DEINT_CPU | DEINT_SHADER))
279  other = true;
280  }
281  else
282  {
283  DoubleRate = false;
284  }
285  }
286 
287  if (!deinterlacer && !other && (singlepref & DEINT_DRIVER))
288  deinterlacer = singledeint;
289  }
290  else if (codec_is_nvdec(m_codecID))
291  {
292  if (DoubleRate)
293  {
294  if (doubledeint)
295  {
296  if (doublepref & (DEINT_DRIVER | DEINT_CPU))
297  deinterlacer = doubledeint;
298  else if (doublepref & DEINT_SHADER)
299  other = true;
300  }
301  else
302  {
303  DoubleRate = false;
304  }
305  }
306 
307  if (!deinterlacer && !other && singledeint)
308  {
309  if (singlepref & (DEINT_DRIVER | DEINT_CPU))
310  deinterlacer = singledeint;
311  else if (singlepref & DEINT_SHADER)
312  { }
313  }
314  }
315 
316  if (deinterlacer == DEINT_NONE)
317  return;
318 
319  QString mode = "adaptive";
320  if (DEINT_BASIC == deinterlacer)
321  mode = "bob";
322  int result = av_opt_set(Context->priv_data, "deint", mode.toLocal8Bit(), 0);
323  if (result == 0)
324  {
325  if (av_opt_set_int(Context->priv_data, "drop_second_field", static_cast<int>(!DoubleRate), 0) == 0)
326  {
327  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Setup decoder deinterlacer '%1'")
328  .arg(MythVideoFrame::DeinterlacerName(deinterlacer | DEINT_DRIVER, DoubleRate, FMT_NVDEC)));
329  m_deinterlacer = deinterlacer;
330  m_deinterlacer2x = DoubleRate;
331  }
332  }
333 }
334 
335 void MythNVDECContext::PostProcessFrame(AVCodecContext* /*Context*/, MythVideoFrame *Frame)
336 {
337  // Remove interlacing flags and set deinterlacer if necessary
338  if (Frame && m_deinterlacer)
339  {
340  Frame->m_interlaced = false;
341  Frame->m_interlacedReverse = false;
342  Frame->m_topFieldFirst = false;
343  Frame->m_deinterlaceInuse = m_deinterlacer | DEINT_DRIVER;
344  Frame->m_deinterlaceInuse2x = m_deinterlacer2x;
345  Frame->m_alreadyDeinterlaced = true;
346  }
347 }
348 
350 {
351  return codec_is_nvdec(m_codecID);
352 }
353 
354 bool MythNVDECContext::IsDeinterlacing(bool &DoubleRate, bool /*unused*/)
355 {
356  if (m_deinterlacer != DEINT_NONE)
357  {
358  DoubleRate = m_deinterlacer2x;
359  return true;
360  }
361  DoubleRate = false;
362  return false;
363 }
364 
365 enum AVPixelFormat MythNVDECContext::GetFormat(AVCodecContext* Context, const AVPixelFormat *PixFmt)
366 {
367  while (*PixFmt != AV_PIX_FMT_NONE)
368  {
369  if (*PixFmt == AV_PIX_FMT_CUDA)
370  {
371  auto * decoder = reinterpret_cast<AvFormatDecoder*>(Context->opaque);
372  if (decoder)
373  {
374  auto * me = dynamic_cast<MythNVDECContext*>(decoder->GetMythCodecContext());
375  if (me)
376  me->InitFramesContext(Context);
377  }
378  return AV_PIX_FMT_CUDA;
379  }
380  PixFmt++;
381  }
382  return AV_PIX_FMT_NONE;
383 }
384 
385 bool MythNVDECContext::RetrieveFrame(AVCodecContext *Context, MythVideoFrame *Frame, AVFrame *AvFrame)
386 {
387  if (AvFrame->format != AV_PIX_FMT_CUDA)
388  return false;
390  return RetrieveHWFrame(Frame, AvFrame);
392  return GetBuffer(Context, Frame, AvFrame, 0);
393  return false;
394 }
395 
401 bool MythNVDECContext::GetBuffer(struct AVCodecContext *Context, MythVideoFrame *Frame,
402  AVFrame *AvFrame, int /*Flags*/)
403 {
404  if ((AvFrame->format != AV_PIX_FMT_CUDA) || !AvFrame->data[0])
405  {
406  LOG(VB_GENERAL, LOG_ERR, LOC + "Not a valid CUDA hw frame");
407  return false;
408  }
409 
410  if (!Context || !Frame)
411  return false;
412 
413  auto *decoder = static_cast<AvFormatDecoder*>(Context->opaque);
414 
415  for (int i = 0; i < 3; i++)
416  {
417  Frame->m_pitches[i] = AvFrame->linesize[i];
418  Frame->m_offsets[i] = AvFrame->data[i] ? (static_cast<int>(AvFrame->data[i] - AvFrame->data[0])) : 0;
419  Frame->m_priv[i] = nullptr;
420  }
421 
422  Frame->m_width = AvFrame->width;
423  Frame->m_height = AvFrame->height;
424  Frame->m_pixFmt = Context->pix_fmt;
425  Frame->m_directRendering = true;
426 
427  AvFrame->opaque = Frame;
428 
429  // set the pixel format - normally NV12 but P010 for 10bit etc. Set here rather than guessing later.
430  if (AvFrame->hw_frames_ctx)
431  {
432  auto *context = reinterpret_cast<AVHWFramesContext*>(AvFrame->hw_frames_ctx->data);
433  if (context)
434  Frame->m_swPixFmt = context->sw_format;
435  }
436 
437  // NVDEC 'fixes' 10/12/16bit colour values
438  Frame->m_colorshifted = true;
439 
440  // Frame->data[0] holds CUdeviceptr for the frame data - offsets calculated above
441  Frame->m_buffer = AvFrame->data[0];
442 
443  // Retain the buffer so it is not released before we display it
444  Frame->m_priv[0] = reinterpret_cast<unsigned char*>(av_buffer_ref(AvFrame->buf[0]));
445 
446  // We need the CUDA device context in the interop class and it also holds the reference
447  // to the interop class itself
448  Frame->m_priv[1] = reinterpret_cast<unsigned char*>(av_buffer_ref(Context->hw_device_ctx));
449 
450  // Set the release method
451  AvFrame->buf[1] = av_buffer_create(reinterpret_cast<uint8_t*>(Frame), 0,
452  MythCodecContext::ReleaseBuffer, decoder, 0);
453  return true;
454 }
455 
456 MythNVDECContext::MythNVDECCaps::MythNVDECCaps(cudaVideoCodec Codec, uint Depth, cudaVideoChromaFormat Format,
457  QSize Minimum, QSize Maximum, uint MacroBlocks)
458  : m_codec(Codec),
459  m_depth(Depth),
460  m_format(Format),
461  m_minimum(Minimum),
462  m_maximum(Maximum),
463  m_macroBlocks(MacroBlocks)
464 {
465  auto ToMythProfile = [](cudaVideoCodec CudaCodec)
466  {
467  switch (CudaCodec)
468  {
469  case cudaVideoCodec_MPEG1: return MythCodecContext::MPEG1;
470  case cudaVideoCodec_MPEG2: return MythCodecContext::MPEG2;
471  case cudaVideoCodec_MPEG4: return MythCodecContext::MPEG4;
472  case cudaVideoCodec_VC1: return MythCodecContext::VC1;
473  case cudaVideoCodec_H264: return MythCodecContext::H264;
474  case cudaVideoCodec_HEVC: return MythCodecContext::HEVC;
475  case cudaVideoCodec_VP8: return MythCodecContext::VP8;
476  case cudaVideoCodec_VP9: return MythCodecContext::VP9;
477  default: break;
478  }
480  };
481 
482  auto ToMythFormat = [](cudaVideoChromaFormat CudaFormat)
483  {
484  switch (CudaFormat)
485  {
486  case cudaVideoChromaFormat_420: return FMT_YV12;
487  case cudaVideoChromaFormat_422: return FMT_YUV422P;
488  case cudaVideoChromaFormat_444: return FMT_YUV444P;
489  default: break;
490  }
491  return FMT_NONE;
492  };
493  m_profile = ToMythProfile(m_codec);
494  m_type = ToMythFormat(m_format);
495 }
496 
497 bool MythNVDECContext::MythNVDECCaps::Supports(cudaVideoCodec Codec, cudaVideoChromaFormat Format,
498  uint Depth, int Width, int Height) const
499 {
500  uint mblocks = static_cast<uint>((Width * Height) / 256);
501 
502  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
503  QString("Trying to match: Codec %1 Format %2 Depth %3 Width %4 Height %5 MBs %6")
504  .arg(Codec).arg(Format).arg(Depth).arg(Width).arg(Height).arg(mblocks));
505  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
506  QString("to this profile: Codec %1 Format %2 Depth %3 Width %4<->%5 Height %6<->%7 MBs %8")
507  .arg(m_codec).arg(m_format).arg(m_depth)
508  .arg(m_minimum.width()).arg(m_maximum.width())
509  .arg(m_minimum.height()).arg(m_maximum.height()).arg(m_macroBlocks));
510 
511  bool result = (Codec == m_codec) && (Format == m_format) && (Depth == m_depth) &&
512  (m_maximum.width() >= Width) && (m_maximum.height() >= Height) &&
513  (m_minimum.width() <= Width) && (m_minimum.height() <= Height) &&
514  (m_macroBlocks >= mblocks);
515 
516  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("%1 Match").arg(result ? "" : "NO"));
517  return result;
518 }
519 
520 bool MythNVDECContext::HaveNVDEC(bool Reinit /*=false*/)
521 {
522  static QRecursiveMutex lock;
523  QMutexLocker locker(&lock);
524  static bool s_checked = false;
525  static bool s_available = false;
526  if (!s_checked || Reinit)
527  {
528  if (gCoreContext->IsUIThread())
529  {
530  const std::vector<MythNVDECCaps>& profiles = MythNVDECContext::GetProfiles();
531  if (profiles.empty())
532  {
533  LOG(VB_GENERAL, LOG_INFO, LOC + "No NVDEC decoders found");
534  }
535  else
536  {
537  s_available = true;
538  LOG(VB_GENERAL, LOG_INFO, LOC + "Supported/available NVDEC decoders:");
539  for (const auto& profile : profiles)
540  {
541  QString desc = MythCodecContext::GetProfileDescription(profile.m_profile,profile.m_maximum,
542  profile.m_type, profile.m_depth + 8);
543  LOG(VB_GENERAL, LOG_INFO, LOC + desc + QString(" MBs: %1").arg(profile.m_macroBlocks));
544  }
545  }
546  }
547  else
548  {
549  LOG(VB_GENERAL, LOG_WARNING, LOC + "HaveNVDEC must be initialised from the main thread");
550  }
551  }
552  s_checked = true;
553  return s_available;
554 }
555 
556 
557 void MythNVDECContext::GetDecoderList(QStringList &Decoders)
558 {
559  const std::vector<MythNVDECCaps>& profiles = MythNVDECContext::GetProfiles();
560  if (profiles.empty())
561  return;
562  Decoders.append("NVDEC:");
563  for (const auto& profile : profiles)
564  {
565  if (!(profile.m_depth % 2)) // Ignore 9/11bit etc
566  Decoders.append(MythCodecContext::GetProfileDescription(profile.m_profile, profile.m_maximum,
567  profile.m_type, profile.m_depth + 8));
568  }
569 }
570 
571 const std::vector<MythNVDECContext::MythNVDECCaps> &MythNVDECContext::GetProfiles(void)
572 {
573  static QRecursiveMutex lock;
574  static bool s_initialised = false;
575  static std::vector<MythNVDECContext::MythNVDECCaps> s_profiles;
576 
577  QMutexLocker locker(&lock);
578  if (s_initialised)
579  return s_profiles;
580  s_initialised = true;
581 
583  CUcontext context = nullptr;
584  CudaFunctions *cuda = nullptr;
585  if (MythNVDECInterop::CreateCUDAContext(opengl, cuda, context))
586  {
587  OpenGLLocker gllocker(opengl);
588  CuvidFunctions *cuvid = nullptr;
589  CUcontext dummy = nullptr;
590  cuda->cuCtxPushCurrent(context);
591 
592  if (cuvid_load_functions(&cuvid, nullptr) == 0)
593  {
594  // basic check passed
595  if (!cuvid->cuvidGetDecoderCaps)
596  LOG(VB_GENERAL, LOG_WARNING, LOC + "Old driver - cannot check decoder capabilities");
597 
598  // now iterate over codecs, depths and formats to check support
599  for (int codec = cudaVideoCodec_MPEG1; codec < cudaVideoCodec_NumCodecs; ++codec)
600  {
601  auto cudacodec = static_cast<cudaVideoCodec>(codec);
602  if (cudacodec == cudaVideoCodec_JPEG)
603  continue;
604  for (int format = cudaVideoChromaFormat_420; format < cudaVideoChromaFormat_444; ++format)
605  {
606  auto cudaformat = static_cast<cudaVideoChromaFormat>(format);
607  for (uint depth = 0; depth < 9; ++depth)
608  {
609  CUVIDDECODECAPS caps;
610  caps.eCodecType = cudacodec;
611  caps.eChromaFormat = cudaformat;
612  caps.nBitDepthMinus8 = depth;
613  // N.B. cuvidGetDecoderCaps was not available on older drivers
614  if (cuvid->cuvidGetDecoderCaps && (cuvid->cuvidGetDecoderCaps(&caps) == CUDA_SUCCESS) &&
615  caps.bIsSupported)
616  {
617  s_profiles.emplace_back(
618  cudacodec, depth, cudaformat,
619  QSize(caps.nMinWidth, caps.nMinHeight),
620  QSize(static_cast<int>(caps.nMaxWidth), static_cast<int>(caps.nMaxHeight)),
621  caps.nMaxMBCount);
622  }
623  else if (!cuvid->cuvidGetDecoderCaps)
624  {
625  // dummy - just support everything:)
626  s_profiles.emplace_back(cudacodec, depth, cudaformat,
627  QSize(32, 32), QSize(8192, 8192),
628  (8192 * 8192) / 256);
629  }
630  }
631  }
632  }
633  cuvid_free_functions(&cuvid);
634  }
635  cuda->cuCtxPopCurrent(&dummy);
636  }
637  MythNVDECInterop::CleanupContext(opengl, cuda, context);
638 
639  return s_profiles;
640 }
641 
642 void MythNVDECContext::InitFramesContext(AVCodecContext *Context)
643 {
644  if (!Context)
645  return;
646 
647  if (m_framesContext)
648  {
649  auto *frames = reinterpret_cast<AVHWFramesContext*>(m_framesContext->data);
650  if ((frames->sw_format == Context->sw_pix_fmt) && (frames->width == Context->coded_width) &&
651  (frames->height == Context->coded_height))
652  {
653  Context->hw_frames_ctx = av_buffer_ref(m_framesContext);
654  return;
655  }
656  }
657 
658  // If this is a 'spontaneous' callback from FFmpeg (i.e. not on a stream change)
659  // then we must release any direct render buffers.
661  m_parent->GetPlayer()->DiscardVideoFrames(true, true);
662 
663  av_buffer_unref(&m_framesContext);
664 
665  AVBufferRef* framesref = av_hwframe_ctx_alloc(Context->hw_device_ctx);
666  auto *frames = reinterpret_cast<AVHWFramesContext*>(framesref->data);
668  frames->user_opaque = nullptr;
669  frames->sw_format = Context->sw_pix_fmt;
670  frames->format = AV_PIX_FMT_CUDA;
671  frames->width = Context->coded_width;
672  frames->height = Context->coded_height;
673  if (av_hwframe_ctx_init(framesref) < 0)
674  {
675  av_buffer_unref(&framesref);
676  }
677  else
678  {
679  Context->hw_frames_ctx = framesref;
680  m_framesContext = av_buffer_ref(framesref);
682  }
683 }
kCodec_MPEG1_NVDEC
@ kCodec_MPEG1_NVDEC
Definition: mythcodecid.h:150
MythNVDECContext::m_deinterlacer2x
bool m_deinterlacer2x
Definition: mythnvdeccontext.h:75
MythNVDECContext::InitialiseDecoder
static int InitialiseDecoder(AVCodecContext *Context)
Definition: mythnvdeccontext.cpp:142
MythNVDECContext::PostProcessFrame
void PostProcessFrame(AVCodecContext *Context, MythVideoFrame *Frame) override
Definition: mythnvdeccontext.cpp:335
MythCodecContext::m_codecID
MythCodecID m_codecID
Definition: mythcodeccontext.h:169
MythNVDECContext::RetrieveFrame
bool RetrieveFrame(AVCodecContext *Context, MythVideoFrame *Frame, AVFrame *AvFrame) override
Definition: mythnvdeccontext.cpp:385
mythvideoout.h
mythplayerui.h
MythNVDECContext::~MythNVDECContext
~MythNVDECContext() override
Definition: mythnvdeccontext.cpp:31
MythVideoFrame::ParseDeinterlacer
static MythDeintType ParseDeinterlacer(const QString &Deinterlacer)
Definition: mythframe.cpp:544
MythCodecID
MythCodecID
Definition: mythcodecid.h:11
MythCodecContext::H264
@ H264
Definition: mythcodeccontext.h:84
codec_is_nvdec
static bool codec_is_nvdec(MythCodecID id)
Definition: mythcodecid.h:342
kCodec_MPEG1_NVDEC_DEC
@ kCodec_MPEG1_NVDEC_DEC
Definition: mythcodecid.h:166
MythCodecContext::MPEG1
@ MPEG1
Definition: mythcodeccontext.h:58
Frame
Definition: zmdefines.h:102
MythCodecContext::NewHardwareFramesContext
static void NewHardwareFramesContext(void)
Track the number of concurrent frames contexts.
Definition: mythcodeccontext.cpp:431
FMT_NVDEC
@ FMT_NVDEC
Definition: mythframe.h:62
MythNVDECContext::GetBuffer
static bool GetBuffer(AVCodecContext *Context, MythVideoFrame *Frame, AVFrame *AvFrame, int Flags)
Convert AVFrame data to MythFrame.
Definition: mythnvdeccontext.cpp:401
MythCoreContext::IsUIThread
bool IsUIThread(void)
Definition: mythcorecontext.cpp:1356
MythCodecContext::VC1
@ VC1
Definition: mythcodeccontext.h:102
MythCodecContext::InitVideoCodec
virtual void InitVideoCodec(AVCodecContext *Context, bool SelectedStream, bool &DirectRendering)
Definition: mythcodeccontext.cpp:307
MythDate::Format
Format
Definition: mythdate.h:15
MythNVDECContext::GetFormat
static enum AVPixelFormat GetFormat(AVCodecContext *Context, const AVPixelFormat *PixFmt)
Definition: mythnvdeccontext.cpp:365
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythCodecContext::VP9
@ VP9
Definition: mythcodeccontext.h:108
MythCodecContext::FramesContextFinished
static void FramesContextFinished(AVHWFramesContext *Context)
Definition: mythcodeccontext.cpp:438
FMT_NONE
@ FMT_NONE
Definition: mythframe.h:21
MythVideoFrame::FormatIs422
static bool FormatIs422(VideoFrameType Type)
Definition: mythframe.h:443
MythNVDECContext::GetDecoderList
static void GetDecoderList(QStringList &Decoders)
Definition: mythnvdeccontext.cpp:557
MythPlayer::DiscardVideoFrames
void DiscardVideoFrames(bool KeyFrame, bool Flushed)
Places frames in the available frames queue.
Definition: mythplayer.cpp:645
MythNVDECContext::MythNVDECCaps::Supports
bool Supports(cudaVideoCodec Codec, cudaVideoChromaFormat Format, uint Depth, int Width, int Height) const
Definition: mythnvdeccontext.cpp:497
MythDeintType
MythDeintType
Definition: mythframe.h:66
MythVideoProfile
Definition: mythvideoprofile.h:83
MythNVDECContext::InitVideoCodec
void InitVideoCodec(AVCodecContext *Context, bool SelectedStream, bool &DirectRendering) override
Definition: mythnvdeccontext.cpp:197
MythVideoProfile::GetDoubleRatePreferences
QString GetDoubleRatePreferences() const
Definition: mythvideoprofile.cpp:370
MythNVDECContext::MythNVDECCaps
Definition: mythnvdeccontext.h:51
MythNVDECContext::GetProfiles
static const std::vector< MythNVDECCaps > & GetProfiles(void)
Definition: mythnvdeccontext.cpp:571
MythCodecContext::NoProfile
@ NoProfile
Definition: mythcodeccontext.h:57
AVFrame
struct AVFrame AVFrame
Definition: BorderDetector.h:15
Decoder
Definition: decoder.h:70
mythlogging.h
MythCodecContext::DeviceContextFinished
static void DeviceContextFinished(AVHWDeviceContext *Context)
Definition: mythcodeccontext.cpp:448
hardwareprofile.scan.profile
profile
Definition: scan.py:97
FMT_YUV422P
@ FMT_YUV422P
Definition: mythframe.h:36
MythCodecContext::ReleaseBuffer
static void ReleaseBuffer(void *Opaque, uint8_t *Data)
Definition: mythcodeccontext.cpp:416
MythVideoProfile::GetSingleRatePreferences
QString GetSingleRatePreferences() const
Definition: mythvideoprofile.cpp:365
MythNVDECContext::m_deinterlacer
MythDeintType m_deinterlacer
Definition: mythnvdeccontext.h:74
MythCodecContext::MPEG2
@ MPEG2
Definition: mythcodeccontext.h:59
DEINT_DRIVER
@ DEINT_DRIVER
Definition: mythframe.h:74
DEINT_SHADER
@ DEINT_SHADER
Definition: mythframe.h:73
MythNVDECContext
Definition: mythnvdeccontext.h:25
codec_is_nvdec_dec
static bool codec_is_nvdec_dec(MythCodecID id)
Definition: mythcodecid.h:345
MythNVDECContext::MythNVDECCaps::m_format
cudaVideoChromaFormat m_format
Definition: mythnvdeccontext.h:63
VideoFrameType
VideoFrameType
Definition: mythframe.h:19
MythNVDECInterop::CreateCUDAContext
static bool CreateCUDAContext(MythRenderOpenGL *GLContext, CudaFunctions *&CudaFuncs, CUcontext &CudaContext)
Definition: mythnvdecinterop.cpp:380
DEINT_BASIC
@ DEINT_BASIC
Definition: mythframe.h:69
FMT_YV12
@ FMT_YV12
Definition: mythframe.h:23
MythVideoFrame::ColorDepth
static int ColorDepth(int Format)
Definition: mythframe.h:398
MythCodecContext::VP8
@ VP8
Definition: mythcodeccontext.h:107
MythCodecContext::RetrieveHWFrame
virtual bool RetrieveHWFrame(MythVideoFrame *Frame, AVFrame *AvFrame)
Definition: mythcodeccontext.cpp:628
AvFormatDecoder
A decoder for media files.
Definition: avformatdecoder.h:79
MythNVDECContext::DecoderWillResetOnFlush
bool DecoderWillResetOnFlush(void) override
Definition: mythnvdeccontext.cpp:349
MythCodecContext::m_parent
DecoderBase * m_parent
Definition: mythcodeccontext.h:168
DEINT_NONE
@ DEINT_NONE
Definition: mythframe.h:68
DEINT_HIGH
@ DEINT_HIGH
Definition: mythframe.h:71
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
DEINT_CPU
@ DEINT_CPU
Definition: mythframe.h:72
MythCodecContext::IsUnsupportedProfile
static bool IsUnsupportedProfile(AVCodecContext *Context)
Most hardware decoders do not support these codecs/profiles.
Definition: mythcodeccontext.cpp:598
MythVideoFrame::FormatIs444
static bool FormatIs444(VideoFrameType Type)
Definition: mythframe.h:449
MythAVUtil::PixelFormatToFrameType
static VideoFrameType PixelFormatToFrameType(AVPixelFormat Fmt)
Definition: mythavutil.cpp:72
FMT_YUV444P
@ FMT_YUV444P
Definition: mythframe.h:43
DEINT_MEDIUM
@ DEINT_MEDIUM
Definition: mythframe.h:70
MythVideoFrame::FormatIs420
static bool FormatIs420(VideoFrameType Type)
Definition: mythframe.h:437
MythRenderOpenGL
Definition: mythrenderopengl.h:96
MythNVDECContext::SetDeinterlacing
void SetDeinterlacing(AVCodecContext *Context, MythVideoProfile *Profile, bool DoubleRate) override
Enable NVDEC/CUDA deinterlacing if necessary.
Definition: mythnvdeccontext.cpp:235
kCodec_MPEG1
@ kCodec_MPEG1
Definition: mythcodecid.h:22
MythCodecContext::CreateDevice
static AVBufferRef * CreateDevice(AVHWDeviceType Type, MythInteropGPU *Interop, const QString &Device=QString())
Definition: mythcodeccontext.cpp:559
avformatdecoder.h
MythVideoFrame::DeinterlacerName
static QString DeinterlacerName(MythDeintType Deint, bool DoubleRate, VideoFrameType Format=FMT_NONE)
Definition: mythframe.cpp:462
MythNVDECContext::HaveNVDEC
static bool HaveNVDEC(bool Reinit=false)
Definition: mythnvdeccontext.cpp:520
mythnvdeccontext.h
MythCodecContext::FrameTypeIsSupported
static bool FrameTypeIsSupported(AVCodecContext *Context, VideoFrameType Format)
Definition: mythcodeccontext.cpp:515
LOC
#define LOC
Definition: mythnvdeccontext.cpp:23
MythRenderOpenGL::GetOpenGLRender
static MythRenderOpenGL * GetOpenGLRender(void)
Definition: mythrenderopengl.cpp:65
MythNVDECInterop::CreateNVDEC
static MythNVDECInterop * CreateNVDEC(MythPlayerUI *Player, MythRenderOpenGL *Context)
Definition: mythnvdecinterop.cpp:85
MythNVDECContext::HwDecoderInit
int HwDecoderInit(AVCodecContext *Context) override
Definition: mythnvdeccontext.cpp:209
MythNVDECContext::InitFramesContext
void InitFramesContext(AVCodecContext *Context)
Definition: mythnvdeccontext.cpp:642
MythNVDECInterop::CleanupContext
static void CleanupContext(MythRenderOpenGL *GLContext, CudaFunctions *&CudaFuncs, CUcontext &CudaContext)
Definition: mythnvdecinterop.cpp:404
MythCodecContext::InitialiseDecoder2
static int InitialiseDecoder2(AVCodecContext *Context, CreateHWDecoder Callback, const QString &Debug)
Initialise a hardware decoder that is NOT expected to use AVHWFramesContext.
Definition: mythcodeccontext.cpp:543
MythCodecContext::HEVC
@ HEVC
Definition: mythcodeccontext.h:95
MythNVDECContext::MythNVDECCaps::m_profile
MythCodecContext::CodecProfile m_profile
Definition: mythnvdeccontext.h:59
MythNVDECContext::MythNVDECCaps::m_codec
cudaVideoCodec m_codec
Definition: mythnvdeccontext.h:61
mythnvdecinterop.h
MythNVDECContext::MythNVDECCaps::MythNVDECCaps
MythNVDECCaps(cudaVideoCodec Codec, uint Depth, cudaVideoChromaFormat Format, QSize Minimum, QSize Maximum, uint MacroBlocks)
Definition: mythnvdeccontext.cpp:456
MythNVDECContext::IsDeinterlacing
bool IsDeinterlacing(bool &DoubleRate, bool StreamChange=false) override
Definition: mythnvdeccontext.cpp:354
MythCodecContext
Definition: mythcodeccontext.h:52
MythCodecContext::GetProfileDescription
static QString GetProfileDescription(CodecProfile Profile, QSize Size, VideoFrameType Format=FMT_NONE, uint ColorDepth=0)
Definition: mythcodeccontext.cpp:789
MythCodecContext::MPEG4
@ MPEG4
Definition: mythcodeccontext.h:66
MythVideoFrame
Definition: mythframe.h:87
MythNVDECContext::m_framesContext
AVBufferRef * m_framesContext
Definition: mythnvdeccontext.h:71
MythNVDECContext::MythNVDECContext
MythNVDECContext(DecoderBase *Parent, MythCodecID CodecID)
Definition: mythnvdeccontext.cpp:26
mythmainwindow.h
DecoderBase
Definition: decoderbase.h:121
MythCodecContext::GetPlayerUI
static MythPlayerUI * GetPlayerUI(AVCodecContext *Context)
Definition: mythcodeccontext.cpp:506
DecoderBase::GetPlayer
MythPlayer * GetPlayer()
Definition: decoderbase.h:153
uint
unsigned int uint
Definition: freesurround.h:24
MythNVDECContext::GetSupportedCodec
static MythCodecID GetSupportedCodec(AVCodecContext **CodecContext, const AVCodec **Codec, const QString &Decoder, AVStream *Stream, uint StreamType)
Determine whether NVDEC decoding is supported for this codec.
Definition: mythnvdeccontext.cpp:41
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:902
MythNVDECContext::MythNVDECCaps::m_type
VideoFrameType m_type
Definition: mythnvdeccontext.h:60
OpenGLLocker
Definition: mythrenderopengl.h:255