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