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