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