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