MythTV  master
videoout_vdpau.cpp
Go to the documentation of this file.
1 #include "mythcontext.h"
2 #include "mythplayer.h"
3 #include "videooutbase.h"
4 #include "videoout_vdpau.h"
5 #include "videodisplayprofile.h"
6 #include "osd.h"
7 #include "mythxdisplay.h"
8 #include "mythmainwindow.h"
9 #include "mythuihelper.h"
10 #include "mythpainter_vdpau.h"
11 
12 #define LOC QString("VidOutVDPAU: ")
13 
14 #define MIN_REFERENCE_FRAMES 2
15 #define MAX_REFERENCE_FRAMES 16
16 #define MIN_PROCESS_BUFFER 6
17 #define MAX_PROCESS_BUFFER 50
18 #define DEF_PROCESS_BUFFER 12
19 
20 #define CHECK_ERROR(Loc) \
21  if (m_render && m_render->IsErrored()) \
22  errorState = kError_Unknown; \
23  if (IsErrored()) \
24  { \
25  LOG(VB_GENERAL, LOG_ERR, LOC + QString("IsErrored() in %1").arg(Loc)); \
26  return; \
27  } while(false)
28 
30 {
31  opts.renderers->append("vdpau");
32  (*opts.osds)["vdpau"].append("vdpau");
33  if (opts.decoders->contains("vdpau"))
34  (*opts.safe_renderers)["vdpau"].append("vdpau");
35  if (opts.decoders->contains("ffmpeg"))
36  (*opts.safe_renderers)["ffmpeg"].append("vdpau");
37  if (opts.decoders->contains("crystalhd"))
38  (*opts.safe_renderers)["crystalhd"].append("vdpau");
39  (*opts.safe_renderers)["dummy"].append("vdpau");
40  (*opts.safe_renderers)["nuppel"].append("vdpau");
41 
42  opts.priorities->insert("vdpau", 120);
43  QStringList deints;
44  deints += "none";
45  deints += "vdpauonefield";
46  deints += "vdpaubobdeint";
47  deints += "vdpaubasic";
48  deints += "vdpauadvanced";
49  deints += "vdpaubasicdoublerate";
50  deints += "vdpauadvanceddoublerate";
51  opts.deints->insert("vdpau", deints);
52 }
53 
55  : m_win(0), m_render(nullptr),
56  m_decoder_buffer_size(MAX_REFERENCE_FRAMES),
57  m_process_buffer_size(DEF_PROCESS_BUFFER), m_pause_surface(0),
58  m_need_deintrefs(false), m_video_mixer(0), m_mixer_features(kVDPFeatNone),
59  m_checked_surface_ownership(false),
60  m_checked_output_surfaces(false),
61  m_decoder(0), m_pix_fmt(-1),
62  m_lock(QMutex::Recursive), m_pip_layer(0), m_pip_surface(0),
63  m_pip_ready(false), m_osd_painter(nullptr),
64  m_skip_chroma(false), m_denoise(0.0F),
65  m_sharpen(0.0F),
66  m_colorspace(VDP_COLOR_STANDARD_ITUR_BT_601)
67 {
68  if (gCoreContext->GetBoolSetting("UseVideoModes", false))
70  m_context = av_vdpau_alloc_context();
71  memset(m_context, 0, sizeof(AVVDPAUContext));
72 }
73 
75 {
76  QMutexLocker locker(&m_lock);
77  TearDown();
78  av_freep(&m_context);
79 }
80 
82 {
83  QMutexLocker locker(&m_lock);
84  DeinitPIPS();
86  DeleteBuffers();
88  DeleteRender();
89 }
90 
91 bool VideoOutputVDPAU::Init(const QSize &video_dim_buf,
92  const QSize &video_dim_disp,
93  float aspect,
94  WId winid, const QRect &win_rect,
95  MythCodecID codec_id)
96 {
97  if (!m_win) // Only if this is the first initialization
98  {
99  // Attempt to free up as much video memory as possible
100  // only works when using the VDPAU painter for the UI
101  MythPainter *painter = GetMythPainter();
102  if (painter)
103  painter->FreeResources();
104  }
105 
106  m_win = winid;
107  QMutexLocker locker(&m_lock);
108  window.SetNeedRepaint(true);
109  bool ok = VideoOutput::Init(video_dim_buf, video_dim_disp,
110  aspect, winid, win_rect, codec_id);
111  if (db_vdisp_profile)
113 
114  InitDisplayMeasurements(video_dim_disp.width(), video_dim_disp.height(),
115  true);
116  ParseOptions();
117  if (ok) ok = InitRender();
118  if (ok) ok = InitBuffers();
119  if (!ok)
120  {
121  TearDown();
122  return ok;
123  }
124 
126  MoveResize();
127  LOG(VB_PLAYBACK, LOG_INFO, LOC +
128  QString("Created VDPAU context (%1 decode)")
129  .arg(codec_is_std(video_codec_id) ? "software" : "GPU"));
130 
131  return ok;
132 }
133 
135 {
136  QMutexLocker locker(&m_lock);
137 
138  const QSize size = window.GetDisplayVisibleRect().size();
139 
140  m_render = new MythRenderVDPAU();
141  if (m_render->Create(size, m_win))
142  {
144  if (m_osd_painter)
145  {
147  LOG(VB_PLAYBACK, LOG_INFO, LOC +
148  QString("Created VDPAU osd (%1x%2)")
149  .arg(size.width()).arg(size.height()));
150  }
151  else
152  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VDPAU osd.");
153  return true;
154  }
155 
156  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to initialise VDPAU");
157 
158  return false;
159 }
160 
162 {
163  QMutexLocker locker(&m_lock);
164 
165  if (m_osd_painter)
166  {
167  // Hack to ensure that the osd painter is not
168  // deleted while image load thread is still busy
169  // loading images with that painter
171  delete invalid_osd_painter;
173  }
174 
175  if (m_render)
176  {
177  if (m_decoder)
179 
180  m_render->DecrRef();
181  m_render = nullptr;
182  }
183 
185  m_osd_painter = nullptr;
186  m_decoder = 0;
187  m_render = nullptr;
188  m_pix_fmt = -1;
189 }
190 
192 {
193  QMutexLocker locker(&m_lock);
194  if (!m_render)
195  return false;
196 
198  const QSize video_dim = codec_is_std(video_codec_id) ?
200 
201  vbuffers.Init(buffer_size, false, 2, 1, 4, 1);
202 
203  bool ok = false;
205  {
206  ok = CreateVideoSurfaces(buffer_size);
207  if (ok)
208  {
209  for (int i = 0; i < m_video_surfaces.size(); i++)
210  ok &= vbuffers.CreateBuffer(video_dim.width(),
211  video_dim.height(), i,
213  FMT_VDPAU);
214  }
215  }
216  else if (codec_is_std(video_codec_id))
217  {
219  if (ok)
221  video_dim.width(), video_dim.height());
222  }
223 
224  if (!ok)
225  {
226  LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to create VDPAU buffers");
227  }
228  else
229  {
230  m_video_mixer = m_render->CreateVideoMixer(video_dim, 2,
232  ok = m_video_mixer;
234 
235  if (ok && (m_mixer_features & kVDPFeatSharpness))
238  m_sharpen);
239  if (ok && (m_mixer_features & kVDPFeatDenoise))
242  m_denoise);
243  if (ok && m_skip_chroma)
246 
249  kVDPAttribBackground, 0x7F7F7FFF);
250  }
251 
252  if (!ok)
253  {
254  LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to create VDPAU mixer");
255  DeleteBuffers();
256  }
257 
258  return ok;
259 }
260 
262 {
263  if (!m_render || num < 1)
264  return false;
265 
266  bool ret = true;
267  const QSize size = codec_is_std(video_codec_id) ?
269  for (uint i = 0; i < num; i++)
270  {
272  if (tmp)
273  {
274  m_video_surfaces.push_back(tmp);
276  }
277  else
278  {
279  ret = false;
280  break;
281  }
282  }
283  return ret;
284 }
285 
287 {
288  if (!m_render || m_video_surfaces.isEmpty())
289  return;
290 
291  for (int i = 0; i < m_video_surfaces.size(); i++)
293  m_video_surfaces.clear();
294 }
295 
297 {
298  QMutexLocker locker(&m_lock);
299  if (m_render && m_video_mixer)
301  m_video_mixer = 0;
305  vbuffers.Reset();
307 }
308 
310 {
311  QMutexLocker locker(&m_lock);
312 
313  const QRect tmp_display_visible_rect =
315  if (window.GetPIPState() == kPIPStandAlone &&
316  !tmp_display_visible_rect.isEmpty())
317  {
318  window.SetDisplayVisibleRect(tmp_display_visible_rect);
319  }
320  const QRect display_visible_rect = window.GetDisplayVisibleRect();
321 
322  if (m_render)
323  m_render->DrawDisplayRect(display_visible_rect);
324 }
325 
327 {
328  if ((interlaced && m_deinterlacing) ||
329  (!interlaced && !m_deinterlacing))
330  return m_deinterlacing;
331 
332  return SetupDeinterlace(interlaced);
333 }
334 
336  const QString &overridefilter)
337 {
338  m_lock.lock();
339  if (!m_render)
340  return false;
341 
342  bool enable = interlaced;
343 
345  {
346  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Disabled deinterlacing for HEVC/H.265");
347  enable = false;
348  }
349 
350  if (enable)
351  {
353  if (m_deintfiltername.contains("vdpau"))
354  {
355  uint features = kVDPFeatNone;
356  bool spatial = m_deintfiltername.contains("advanced");
357  bool temporal = m_deintfiltername.contains("basic") || spatial;
358  m_need_deintrefs = spatial || temporal;
359 
360  if (temporal)
361  features += kVDPFeatTemporal;
362 
363  if (spatial)
364  features += kVDPFeatSpatial;
365 
366  enable = m_render->SetDeinterlacing(m_video_mixer, features);
367  if (enable)
368  {
369  m_deinterlacing = true;
370  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Enabled deinterlacing.");
371  }
372  else
373  {
374  enable = false;
375  LOG(VB_PLAYBACK, LOG_INFO, LOC +
376  "Failed to enable deinterlacing.");
377  }
378  }
379  else
380  {
381  enable = false;
382  }
383  }
384 
385  if (!enable)
386  {
389  m_deintfiltername = QString();
390  m_deinterlacing = false;
391  m_need_deintrefs = false;
392  }
393  m_lock.unlock();
394  return enable;
395 }
396 
397 bool VideoOutputVDPAU::ApproveDeintFilter(const QString &filtername) const
398 {
399  return filtername.contains("vdpau");
400 }
401 
403  FilterChain */*filterList*/,
404  const PIPMap &pipPlayers,
405  FrameScanType /*scan*/)
406 {
407  QMutexLocker locker(&m_lock);
408  CHECK_ERROR("ProcessFrame");
409 
412 
413  m_pip_ready = false;
414  ShowPIPs(frame, pipPlayers);
415 }
416 
418 {
419  if (frame && m_render && !codec_is_std(video_codec_id))
420  {
421  struct vdpau_render_state *render =
422  (struct vdpau_render_state *)frame->buf;
423  if (render)
425  }
427 }
428 
430  OSD *osd)
431 {
432  QMutexLocker locker(&m_lock);
433  CHECK_ERROR("PrepareFrame");
434 
435  if (!m_render)
436  return;
437 
440  {
443  }
444 
445  bool new_frame = false;
446  bool dummy = false;
447  if (frame)
448  {
449  // FIXME for 0.23. This should be triggered from AFD by a seek
450  if ((abs(frame->frameNumber - framesPlayed) > 8))
452  new_frame = (framesPlayed != frame->frameNumber + 1);
453  framesPlayed = frame->frameNumber + 1;
454  dummy = frame->dummy;
455  }
456 
457  uint video_surface = m_video_surfaces[0];
458  bool deint = (m_deinterlacing && m_need_deintrefs &&
459  frame && !dummy);
460 
461  if (deint)
462  {
463  if (new_frame)
464  UpdateReferenceFrames(frame);
466  deint = false;
467  }
468 
469  if (!codec_is_std(video_codec_id) && frame)
470  {
471  struct vdpau_render_state *render =
472  (struct vdpau_render_state *)frame->buf;
473  if (!render)
474  return;
475  video_surface = m_render->GetSurfaceOwner(render->surface);
476  }
477  else if (new_frame && frame && !dummy)
478  {
479  // FIXME - reference frames for software decode
480  if (deint)
481  video_surface = m_video_surfaces[(framesPlayed + 1) %
483 
484  uint32_t pitches[3] = {
485  (uint32_t)frame->pitches[0],
486  (uint32_t)frame->pitches[2],
487  (uint32_t)frame->pitches[1]
488  };
489  void* const planes[3] = {
490  frame->buf,
491  frame->buf + frame->offsets[2],
492  frame->buf + frame->offsets[1]
493  };
494 
495  if (!m_render->UploadYUVFrame(video_surface, planes, pitches))
496  return;
497  }
498  else if (!frame)
499  {
500  deint = false;
501  video_surface = m_pause_surface;
502  }
503 
504  VdpVideoMixerPictureStructure field =
505  VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
506 
507  if (scan == kScan_Interlaced && m_deinterlacing && frame)
508  {
509  field = frame->top_field_first ?
510  VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD :
511  VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
512  }
513  else if (scan == kScan_Intr2ndField && m_deinterlacing && frame)
514  {
515  field = frame->top_field_first ?
516  VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD :
517  VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
518  }
519  else if (!frame && m_deinterlacing)
520  {
521  field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
522  }
523 
525 
526  QSize size = window.GetDisplayVisibleRect().size();
527  if (size != m_render->GetSize())
528  LOG(VB_GENERAL, LOG_ERR, LOC + "Unexpected display size.");
529 
530  if (dummy)
531  {
532  m_render->DrawBitmap(0, 0, nullptr, nullptr, kVDPBlendNormal, 255);
533  }
534  else
535  {
536  if (!m_render->MixAndRend(m_video_mixer, field, video_surface, 0,
537  deint ? &m_reference_frames : nullptr,
540  QRect(QPoint(0,0), size),
543  0, 0))
544  {
545  LOG(VB_PLAYBACK, LOG_ERR, LOC + "Prepare frame failed.");
546  }
547  }
548 
549  if (m_pip_ready)
551  if (m_visual)
553 
554  if (osd && m_osd_painter && !window.IsEmbedding())
555  osd->DrawDirect(m_osd_painter, GetTotalOSDBounds().size(), true);
556 
557  if (!frame)
558  {
559  VideoFrame *buf = GetLastShownFrame();
560  if (buf)
561  buf->timecode = 0;
562  }
563 }
564 
566 {
567  if (!m_render)
568  return;
569 
570  QVector<uint>::iterator it;
571  for (it = m_video_surfaces.begin(); it != m_video_surfaces.end(); ++it)
574 }
575 
576 void VideoOutputVDPAU::DrawSlice(VideoFrame *frame, int /* x */, int /* y */, int /* w */, int /* h */)
577 {
578  CHECK_ERROR("DrawSlice");
579 
581  return;
582 
585 
586  struct vdpau_render_state *render =
587  (struct vdpau_render_state *)frame->priv[0];
588  const VdpPictureInfo *info = (const VdpPictureInfo *)frame->priv[1];
589 
590  if (frame->pix_fmt != m_pix_fmt)
591  {
592  if (m_decoder)
593  {
594  LOG(VB_GENERAL, LOG_ERR, LOC + "Picture format has changed.");
596  return;
597  }
598 
599  uint max_refs = MIN_REFERENCE_FRAMES;
601  {
602  max_refs = ((VdpPictureInfoH264*)info)->num_ref_frames;
603  if (max_refs < 1 || max_refs > MAX_REFERENCE_FRAMES)
604  {
605  uint32_t round_width = (frame->width + 15) & ~15;
606  uint32_t round_height = (frame->height + 15) & ~15;
607  uint32_t surf_size = (round_width * round_height * 3) / 2;
608  max_refs = (12 * 1024 * 1024) / surf_size;
609  }
610  if (max_refs > MAX_REFERENCE_FRAMES)
611  max_refs = MAX_REFERENCE_FRAMES;
612 
613  // Add extra buffers as necessary
614  int needed = max_refs - m_decoder_buffer_size;
615  if (needed > 0)
616  {
617  QMutexLocker locker(&m_lock);
618  const QSize size = window.GetActualVideoDim();
619  uint created = 0;
620  for (int i = 0; i < needed; i++)
621  {
623  if (tmp)
624  {
625  m_video_surfaces.push_back(tmp);
627  if (vbuffers.AddBuffer(size.width(), size.height(),
629  FMT_VDPAU))
630  {
631  created++;
632  }
633  }
634  }
635  m_decoder_buffer_size += created;
636  LOG(VB_GENERAL, LOG_INFO, LOC +
637  QString("Added %1 new buffers. New buffer size %2 "
638  "(%3 decode and %4 process)")
639  .arg(created).arg(vbuffers.Size())
641  .arg(m_process_buffer_size));
642  }
643  }
644 
645  VdpDecoderProfile vdp_decoder_profile;
646  switch (video_codec_id)
647  {
648  case kCodec_MPEG1_VDPAU:
649  vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG1;
650  break;
651  case kCodec_MPEG2_VDPAU:
652  vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG2_MAIN;
653  break;
654  case kCodec_MPEG4_VDPAU:
655  vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP;
656  break;
657  case kCodec_H264_VDPAU:
658  vdp_decoder_profile = VDP_DECODER_PROFILE_H264_HIGH;
659  break;
660  case kCodec_WMV3_VDPAU:
661  vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_MAIN;
662  break;
663  case kCodec_VC1_VDPAU:
664  vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_ADVANCED;
665  break;
666 #ifdef VDP_DECODER_PROFILE_HEVC_MAIN
667  case kCodec_HEVC_VDPAU:
668  vdp_decoder_profile = VDP_DECODER_PROFILE_HEVC_MAIN;
669  max_refs = 16;
670  break;
671 #endif
672  default:
673  LOG(VB_GENERAL, LOG_ERR, LOC +
674  "Codec is not supported.");
676  return;
677  }
678 
680  vdp_decoder_profile, max_refs);
681  if (m_decoder)
682  {
683  m_pix_fmt = frame->pix_fmt;
684  LOG(VB_PLAYBACK, LOG_INFO, LOC +
685  QString("Created VDPAU decoder (%1 ref frames)")
686  .arg(max_refs));
687  }
688  else
689  {
690  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create decoder.");
692  return;
693  }
694  }
695  else if (!m_decoder)
696  {
697  LOG(VB_GENERAL, LOG_ERR, LOC +
698  "Pix format already set but no VDPAU decoder.");
700  return;
701  }
702 
703  m_render->Decode(m_decoder, render, info);
704 }
705 
707 {
708  QMutexLocker locker(&m_lock);
709  CHECK_ERROR("Show");
710 
711  if (window.IsRepaintNeeded())
712  DrawUnusedRects(false);
713 
714  if (m_render)
715  m_render->Flip();
717 }
718 
720 {
721  m_lock.lock();
722  LOG(VB_PLAYBACK, LOG_INFO, LOC + "ClearAfterSeek()");
723  DiscardFrames(false);
724  m_lock.unlock();
725 }
726 
727 bool VideoOutputVDPAU::InputChanged(const QSize &video_dim_buf,
728  const QSize &video_dim_disp,
729  float aspect,
730  MythCodecID av_codec_id,
731  void */*codec_private*/,
732  bool &aspect_only)
733 {
734  LOG(VB_PLAYBACK, LOG_INFO, LOC +
735  QString("InputChanged(%1,%2,%3) '%4'->'%5'")
736  .arg(video_dim_disp.width()).arg(video_dim_disp.height())
737  .arg(aspect)
738  .arg(toString(video_codec_id)).arg(toString(av_codec_id)));
739 
740  QMutexLocker locker(&m_lock);
741 
742  // Ensure we don't lose embedding through program changes. This duplicates
743  // code in VideoOutput::Init but we need start here otherwise the embedding
744  // is lost during window re-initialistion.
745  bool wasembedding = window.IsEmbedding();
746  QRect oldrect;
747  if (wasembedding)
748  {
749  oldrect = window.GetEmbeddingRect();
750  StopEmbedding();
751  }
752 
753  bool cid_changed = (video_codec_id != av_codec_id);
754  bool res_changed = video_dim_disp != window.GetActualVideoDim();
755  bool asp_changed = aspect != window.GetVideoAspect();
756 
757  if (!res_changed && !cid_changed)
758  {
759  aspect_only = true;
760  if (asp_changed)
761  {
762  VideoAspectRatioChanged(aspect);
763  MoveResize();
764  }
765  if (wasembedding)
766  EmbedInWidget(oldrect);
767  return true;
768  }
769 
770  AdjustFillMode oldadjustfillmode = window.GetAdjustFill();
771 
772  TearDown();
773  QRect disp = window.GetDisplayVisibleRect();
774  if (Init(video_dim_buf, video_dim_disp,
775  aspect, m_win, disp, av_codec_id))
776  {
777  if (wasembedding)
778  EmbedInWidget(oldrect);
779  BestDeint();
780  window.ToggleAdjustFill(oldadjustfillmode);
781  return true;
782  }
783 
784  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to re-initialise video output.");
786 
787  return false;
788 }
789 
791 {
792  QMutexLocker locker(&m_lock);
793  VideoOutput::Zoom(direction);
794  MoveResize();
795 }
796 
798 {
799  QMutexLocker locker(&m_lock);
801 }
802 
803 void VideoOutputVDPAU::EmbedInWidget(const QRect &rect)
804 {
805  QMutexLocker locker(&m_lock);
806  if (!window.IsEmbedding())
807  {
809  MoveResize();
811  }
812 }
813 
815 {
816  if (!window.IsEmbedding())
817  return;
818  QMutexLocker locker(&m_lock);
820  MoveResize();
821 }
822 
824 {
825  m_lock.lock();
826  if (m_render)
827  m_render->MoveResizeWin(new_rect);
828  m_lock.unlock();
829 }
830 
832 {
833  m_lock.lock();
835  {
836  const QRect dvr = window.GetDisplayVisibleRect();
837  m_render->DrawDisplayRect(dvr, true);
838  window.SetNeedRepaint(false);
839  if (sync)
841  }
842  m_lock.unlock();
843 }
844 
845 void VideoOutputVDPAU::UpdatePauseFrame(int64_t &disp_timecode)
846 {
847  QMutexLocker locker(&m_lock);
848 
849  LOG(VB_PLAYBACK, LOG_INFO, LOC + "UpdatePauseFrame() " +
850  vbuffers.GetStatus());
851 
853 
855  {
857  disp_timecode = frame->disp_timecode;
859  {
861  uint32_t pitches[3] = { (uint32_t)frame->pitches[0],
862  (uint32_t)frame->pitches[2],
863  (uint32_t)frame->pitches[1] };
864  void* const planes[3] = { frame->buf,
865  frame->buf + frame->offsets[2],
866  frame->buf + frame->offsets[1] };
867  m_render->UploadYUVFrame(m_video_surfaces[0], planes, pitches);
868  }
869  else
870  {
871  struct vdpau_render_state *render =
872  (struct vdpau_render_state *)frame->buf;
873  if (render)
875  }
876  }
877  else
878  LOG(VB_PLAYBACK, LOG_WARNING, LOC +
879  "Could not update pause frame - no used frames.");
880 
881  vbuffers.end_lock();
882 }
883 
885 {
892 
893  m_lock.lock();
894  if (m_render && m_video_mixer)
895  {
896  if (m_colorspace < 0)
897  {
898  QSize size = window.GetVideoDim();
899  m_colorspace = (size.width() > 720 || size.height() > 576) ?
900  VDP_COLOR_STANDARD_ITUR_BT_709 :
901  VDP_COLOR_STANDARD_ITUR_BT_601;
902  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Using ITU %1 colorspace")
903  .arg((m_colorspace == VDP_COLOR_STANDARD_ITUR_BT_601) ?
904  "BT.601" : "BT.709"));
905  }
906 
907  if (m_colorspace != VDP_COLOR_STANDARD_ITUR_BT_601)
908  {
909  videoColourSpace.SetColourSpace((m_colorspace == VDP_COLOR_STANDARD_ITUR_BT_601)
911  }
913  }
914  m_lock.unlock();
915 }
916 
918  int newValue)
919 {
920  if (!m_render || !m_video_mixer)
921  return -1;
922 
923  m_lock.lock();
924  newValue = videoColourSpace.SetPictureAttribute(attribute, newValue);
925  if (newValue >= 0)
927  m_lock.unlock();
928  return newValue;
929 }
930 
932  MythCodecID myth_codec_id, const QSize & /* video_dim */)
933 {
934  QStringList list;
935  if ((codec_is_std(myth_codec_id) || codec_is_vdpau_hw(myth_codec_id)) &&
936  !getenv("NO_VDPAU"))
937  {
938  list += "vdpau";
939  }
940 
941  return list;
942 }
943 
945  uint width, uint height, const QString &decoder,
946  uint stream_type, bool no_acceleration)
947 {
948  bool use_cpu = no_acceleration || (decoder != "vdpau") || getenv("NO_VDPAU");
949  MythCodecID test_cid = (MythCodecID)(kCodec_MPEG1_VDPAU + (stream_type-1));
950 
951  if (!use_cpu)
952  {
953  use_cpu |= !MythRenderVDPAU::IsVDPAUAvailable();
954  use_cpu |= !codec_is_vdpau_hw(test_cid);
955  if (!use_cpu && test_cid == kCodec_MPEG4_VDPAU)
956  use_cpu |= !MythRenderVDPAU::IsMPEG4Available();
957  if (!use_cpu && test_cid == kCodec_H264_VDPAU)
958  use_cpu |= !MythRenderVDPAU::H264DecoderSizeSupported(width, height);
959  if (!use_cpu && test_cid == kCodec_HEVC_VDPAU)
960  use_cpu |= !MythRenderVDPAU::IsHEVCAvailable();
961  }
962 
963  if (use_cpu)
964  return (MythCodecID)(kCodec_MPEG1 + (stream_type-1));
965 
966  return test_cid;
967 }
968 
970 {
971  // this forces the check of VDPAU capabilities
974 }
975 
977 {
978  while (m_reference_frames.size() > (NUM_REFERENCE_FRAMES - 1))
979  m_reference_frames.pop_front();
980 
983  {
984  struct vdpau_render_state *render =
985  (struct vdpau_render_state *)frame->buf;
986  if (render)
987  ref = m_render->GetSurfaceOwner(render->surface);
988  }
989 
990  m_reference_frames.push_back(ref);
991 }
992 
994 {
995  if (!frame || codec_is_std(video_codec_id))
996  return false;
997 
998  uint ref = 0;
999  struct vdpau_render_state *render = (struct vdpau_render_state *)frame->buf;
1000  if (render)
1001  ref = m_render->GetSurfaceOwner(render->surface);
1002  return m_reference_frames.contains(ref);
1003 }
1004 
1006 {
1007  m_lock.lock();
1008  m_reference_frames.clear();
1009  m_lock.unlock();
1010 }
1011 
1013 {
1014  if (!frame)
1015  return;
1016 
1017  m_lock.lock();
1018  if (FrameIsInUse(frame))
1020  else
1021  {
1023  }
1024  m_lock.unlock();
1025 }
1026 
1027 void VideoOutputVDPAU::DiscardFrames(bool next_frame_keyframe)
1028 {
1029  m_lock.lock();
1030  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DiscardFrames(%1)")
1031  .arg(next_frame_keyframe));
1032  CheckFrameStates();
1034  vbuffers.DiscardFrames(next_frame_keyframe);
1035  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DiscardFrames() 3: %1 -- done()")
1036  .arg(vbuffers.GetStatus()));
1037  m_lock.unlock();
1038 }
1039 
1041 {
1042  m_lock.lock();
1043  if (vbuffers.Contains(kVideoBuffer_used, frame))
1044  DiscardFrame(frame);
1045  CheckFrameStates();
1046  m_lock.unlock();
1047 }
1048 
1050 {
1051  m_lock.lock();
1054  while (it != vbuffers.end(kVideoBuffer_displayed))
1055  {
1056  VideoFrame* frame = *it;
1057  if (!FrameIsInUse(frame))
1058  {
1060  {
1061  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1062  QString("Frame %1 is in use by avlib and so is "
1063  "being held for later discarding.")
1064  .arg(DebugString(frame, true)));
1065  }
1066  else
1067  {
1069  vbuffers.end_lock();
1071  continue;
1072  }
1073  }
1074  ++it;
1075  }
1076  vbuffers.end_lock();
1077  m_lock.unlock();
1078 }
1079 
1081 {
1082  if (!m_render)
1083  return false;
1084 
1085  if (!m_pip_surface)
1087 
1088  if (!m_pip_layer && m_pip_surface)
1090 
1091  return (m_pip_surface && m_pip_layer);
1092 }
1093 
1095 {
1096  while (!m_pips.empty())
1097  {
1098  RemovePIP(m_pips.begin().key());
1099  m_pips.erase(m_pips.begin());
1100  }
1101 
1102  m_pip_ready = false;
1103 }
1104 
1106 {
1107  if (m_render)
1108  {
1109  if (m_pip_surface)
1110  {
1112  m_pip_surface = 0;
1113  }
1114 
1115  if (m_pip_layer)
1116  {
1118  m_pip_layer = 0;
1119  }
1120  }
1121 
1122  m_pip_ready = false;
1123 }
1124 
1125 void VideoOutputVDPAU::ShowPIP(VideoFrame * /* frame */, MythPlayer *pipplayer,
1126  PIPLocation loc)
1127 {
1128  if (!pipplayer || !m_render)
1129  return;
1130 
1131  int pipw, piph;
1132  VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph);
1133  const bool pipActive = pipplayer->IsPIPActive();
1134  const bool pipVisible = pipplayer->IsPIPVisible();
1135  const float pipVideoAspect = pipplayer->GetVideoAspect();
1136  const QSize pipVideoDim = pipplayer->GetVideoBufferSize();
1137 
1138  if ((pipVideoAspect <= 0) || !pipimage ||
1139  !pipimage->buf || pipimage->codec != FMT_YV12 || !pipVisible)
1140  {
1141  pipplayer->ReleaseCurrentFrame(pipimage);
1142  return;
1143  }
1144 
1146  {
1147  if (m_pips.contains(pipplayer) &&
1148  m_pips[pipplayer].videoSize != pipVideoDim)
1149  RemovePIP(pipplayer);
1150 
1151  if (!m_pips.contains(pipplayer))
1152  {
1153  uint mixer = m_render->CreateVideoMixer(pipVideoDim, 0, 0);
1154  uint surf = m_render->CreateVideoSurface(pipVideoDim);
1155  vdpauPIP tmp = { pipVideoDim, surf, mixer};
1156  m_pips.insert(pipplayer, tmp);
1157  if (!mixer || !surf)
1158  RemovePIP(pipplayer);
1159  else
1160  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Created pip %1x%2")
1161  .arg(pipVideoDim.width()).arg(pipVideoDim.height()));
1162  }
1163 
1164  if (m_pips.contains(pipplayer))
1165  {
1166  QRect rect = GetPIPRect(loc, pipplayer);
1167 
1168  if (!m_pip_ready)
1169  m_render->DrawBitmap(0, m_pip_surface, nullptr, nullptr,
1170  kVDPBlendNull);
1171 
1172  uint32_t pitches[] = {
1173  (uint32_t)pipimage->pitches[0],
1174  (uint32_t)pipimage->pitches[2],
1175  (uint32_t)pipimage->pitches[1] };
1176  void* const planes[] = {
1177  pipimage->buf,
1178  pipimage->buf + pipimage->offsets[2],
1179  pipimage->buf + pipimage->offsets[1] };
1180 
1181  bool ok;
1182  ok = m_render->UploadYUVFrame(m_pips[pipplayer].videoSurface,
1183  planes, pitches);
1184  ok &= m_render->MixAndRend(m_pips[pipplayer].videoMixer,
1185  VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME,
1186  m_pips[pipplayer].videoSurface,
1187  m_pip_surface, nullptr, false,
1188  QRect(QPoint(0,0), pipVideoDim),
1189  rect, rect);
1190  ok &= m_render->DrawBitmap(0, m_pip_surface, nullptr, &rect,
1191  kVDPBlendPiP, 255);
1192 
1193  if (pipActive)
1194  {
1195  // TODO this could be one rect rendered before the video frame
1196  QRect l = QRect(QPoint(rect.x() - 10, rect.y() - 10),
1197  QSize(10, rect.height() + 20));
1198  QRect t = QRect(QPoint(rect.x(), rect.y() - 10),
1199  QSize(rect.width(), 10));
1200  QRect b = QRect(QPoint(rect.x(), rect.y() + rect.height()),
1201  QSize(rect.width(), 10));
1202  QRect r = QRect(QPoint(rect.x() + rect.width(), rect.y() -10),
1203  QSize(10, rect.height() + 20));
1204  m_render->DrawBitmap(0, m_pip_surface, nullptr, &l, kVDPBlendNormal, 255, 127);
1205  m_render->DrawBitmap(0, m_pip_surface, nullptr, &t, kVDPBlendNormal, 255, 127);
1206  m_render->DrawBitmap(0, m_pip_surface, nullptr, &b, kVDPBlendNormal, 255, 127);
1207  m_render->DrawBitmap(0, m_pip_surface, nullptr, &r, kVDPBlendNormal, 255, 127);
1208  }
1209 
1210  m_pip_ready = ok;
1211  }
1212  }
1213  pipplayer->ReleaseCurrentFrame(pipimage);
1214 }
1215 
1217 {
1218  if (!m_pips.contains(pipplayer))
1219  return;
1220 
1221  if (m_pips[pipplayer].videoSurface && m_render)
1222  m_render->DestroyVideoSurface(m_pips[pipplayer].videoSurface);
1223 
1224  if (m_pips[pipplayer].videoMixer && m_render)
1225  m_render->DestroyVideoMixer(m_pips[pipplayer].videoMixer);
1226 
1227  m_pips.remove(pipplayer);
1228  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Removed 1 PIP");
1229 
1230  if (m_pips.empty())
1231  DeinitPIPLayer();
1232 }
1233 
1235 {
1236  m_skip_chroma = false;
1237  m_denoise = 0.0F;
1238  m_sharpen = 0.0F;
1239  m_colorspace = VDP_COLOR_STANDARD_ITUR_BT_601;
1241 
1246 
1247  QStringList list = GetFilters().split(",");
1248  if (list.empty())
1249  return;
1250 
1251  for (QStringList::Iterator i = list.begin(); i != list.end(); ++i)
1252  {
1253  QString name = (*i).section('=', 0, 0).toLower();
1254  QString opts = (*i).section('=', 1).toLower();
1255 
1256  if (!name.contains("vdpau"))
1257  continue;
1258 
1259  if (name.contains("vdpaubuffercount"))
1260  {
1261  uint num = opts.toUInt();
1262  if (MIN_PROCESS_BUFFER <= num && num <= MAX_PROCESS_BUFFER)
1263  {
1264  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1265  QString("VDPAU process buffer size set to %1 (was %2)")
1266  .arg(num).arg(m_process_buffer_size));
1267  m_process_buffer_size = num;
1268  }
1269  }
1270  else if (name.contains("vdpauivtc"))
1271  {
1272  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1273  "Enabling VDPAU inverse telecine "
1274  "(requires Basic or Advanced deinterlacer)");
1276  }
1277  else if (name.contains("vdpauskipchroma"))
1278  {
1279  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Enabling SkipChromaDeinterlace.");
1280  m_skip_chroma = true;
1281  }
1282  else if (name.contains("vdpaudenoise"))
1283  {
1284  float tmp = std::max(0.0F, std::min(1.0F, opts.toFloat()));
1285  if (tmp != 0.0F)
1286  {
1287  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1288  QString("VDPAU Denoise %1").arg(tmp,4,'f',2,'0'));
1289  m_denoise = tmp;
1291  }
1292  }
1293  else if (name.contains("vdpausharpen"))
1294  {
1295  float tmp = std::max(-1.0F, std::min(1.0F, opts.toFloat()));
1296  if (tmp != 0.0F)
1297  {
1298  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1299  QString("VDPAU Sharpen %1").arg(tmp,4,'f',2,'0'));
1300  m_sharpen = tmp;
1302  }
1303  }
1304  else if (name.contains("vdpaucolorspace"))
1305  {
1306  if (opts.contains("auto"))
1307  m_colorspace = -1;
1308  else if (opts.contains("601"))
1309  m_colorspace = VDP_COLOR_STANDARD_ITUR_BT_601;
1310  else if (opts.contains("709"))
1311  m_colorspace = VDP_COLOR_STANDARD_ITUR_BT_709;
1312 
1313  if (m_colorspace > -1)
1314  {
1315  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1316  QString("Forcing ITU BT.%1 colorspace")
1317  .arg((m_colorspace == VDP_COLOR_STANDARD_ITUR_BT_601) ?
1318  "BT.601" : "BT.709"));
1319  }
1320  }
1321  else if (name.contains("vdpauhqscaling"))
1322  {
1324  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1325  "Requesting high quality scaling.");
1326  }
1327  }
1328 }
1329 
1331 {
1332  return m_osd_painter;
1333 }
1334 
1335 bool VideoOutputVDPAU::GetScreenShot(int width, int height, QString filename)
1336 {
1337  if (m_render)
1338  return m_render->GetScreenShot(width, height, filename);
1339  return false;
1340 }
1341 
1343 {
1344  if (m_render)
1347 }
1348 
1350 {
1351  if (!m_render)
1352  {
1353  LOG(VB_PLAYBACK, LOG_ERR, QString("SetVideoFlip failed."));
1354  return;
1355  }
1357 }
1358 
1359 void* VideoOutputVDPAU::GetDecoderContext(unsigned char* /*buf*/, uint8_t*& /*id*/)
1360 {
1361  return m_context;
1362 }
static DisplayRes * GetDisplayRes(bool lock=false)
Factory method that returns a DisplayRes singleton.
Definition: DisplayRes.cpp:18
int pitches[3]
Y, U, & V pitches.
Definition: mythframe.h:63
void ClearVideoSurface(uint id)
uint CreateVideoSurface(const QSize &size, VdpChromaType type=VDP_CHROMA_TYPE_420, uint existing=0)
void SetVideoFlip(void)
bool ApproveDeintFilter(const QString &filtername) const override
Approves bobdeint filter for XVideo and otherwise defers to VideoOutput::ApproveDeintFilter(const QSt...
void Reset(void)
Resets the class so that Init may be called again.
void CheckOutputSurfaces(void)
void DeinitPIPLayer(void)
MythPainter * invalid_osd_painter
Definition: videooutbase.h:374
QString m_deintfiltername
Definition: videooutbase.h:351
QMap< MythPlayer *, vdpauPIP > m_pips
void SetCSCMatrix(uint id, void *vals)
float GetVideoAspect(void) const
Definition: mythplayer.h:175
void SetVideoRenderer(const QString &video_renderer)
static bool IsHEVCAvailable(void)
void DoneDisplayingFrame(VideoFrame *frame)
Removes frame from used queue and adds it to the available list.
const QString & DebugString(const VideoFrame *frame, bool short_str)
static MythCodecID GetBestSupportedCodec(uint width, uint height, const QString &decoder, uint stream_type, bool no_acceleration)
def scan(profile, smoonURL, gate)
Definition: scan.py:43
uint CreateVideoMixer(const QSize &size, uint layers, uint features, VdpChromaType type=VDP_CHROMA_TYPE_420, uint existing=0)
bool SetDeinterlacing(uint id, uint deinterlacers=kVDPFeatNone)
void DiscardFrame(VideoFrame *) override
Releases frame from any queue onto the queue of frames ready for decoding onto.
bool InputChanged(const QSize &video_dim_buf, const QSize &video_dim_disp, float aspect, MythCodecID av_codec_id, void *codec_private, bool &aspect_only) override
Tells video output to discard decoded frames and wait for new ones.
QMap< MythPlayer *, PIPLocation > PIPMap
Definition: videooutbase.h:37
bool Create(const QSize &size, WId window, uint colorkey=VDPAU_COLORKEY)
bool IsRepaintNeeded(void) const
static bool IsMPEG4Available(void)
void MoveResizeWin(QRect &rect)
uint GetSurfaceOwner(VdpVideoSurface surface)
QString GetStatus(int n=-1) const
LetterBoxColour db_letterbox_colour
Definition: videooutbase.h:325
PictureAttributeSupported
QString toString(MarkTypes type)
bool m_deinterlacing
Definition: videooutbase.h:350
void Decode(uint id, struct vdpau_render_state *render)
MythCodecID
Definition: mythcodecid.h:10
void SafeEnqueue(BufferType, VideoFrame *frame)
void UpdateReferenceFrames(VideoFrame *frame)
VideoColourSpace videoColourSpace
Definition: videooutbase.h:322
void SetVideoFlip(void) override
Tells the player to flip the video frames for proper display.
void CheckFrameStates(void) override
void DrawUnusedRects(bool sync=true) override
Draws non-video portions of the screen.
bool SetupDeinterlace(bool interlaced, const QString &overridefilter="") override
Attempts to enable or disable deinterlacing.
RenderType Type(void) const
void DestroyVideoSurface(uint id)
QString GetFilteredDeint(const QString &override)
bool m_checked_output_surfaces
QRect GetVideoRect(void) const
virtual bool Init(const QSize &video_dim_buf, const QSize &video_dim_disp, float aspect, WId winid, const QRect &win_rect, MythCodecID codec_id)
Performs most of the initialization for VideoOutput.
#define codec_is_vdpau(id)
Definition: mythcodecid.h:129
void DestroyDecoder(uint id)
MythPainter * GetMythPainter(void)
QRect GetTotalOSDBounds(void) const
Returns total OSD bounds.
VideoFrame * GetCurrentFrame(int &w, int &h)
bool DrawBitmap(uint id, uint target, const QRect *src, const QRect *dst, VDPBlendType blendi=kVDPBlendNormal, int alpha=0, int red=0, int green=0, int blue=0)
void DiscardFrames(bool next_frame_keyframe) override
Releases all frames not being actively displayed from any queue onto the queue of frames ready for de...
FrameScanType
Definition: videoouttypes.h:80
QStringList GetVisualiserList(void) override
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
virtual void StopEmbedding(void)
Tells video output to stop embedding video in an existing window.
void ProcessFrame(VideoFrame *frame, OSD *osd, FilterChain *filterList, const PIPMap &pipPlayers, FrameScanType scan) override
long long timecode
Definition: mythframe.h:49
unsigned char * priv[4]
random empty storage
Definition: mythframe.h:52
VideoVisual * m_visual
Definition: videooutbase.h:377
#define LOC
VideoDisplayProfile * db_vdisp_profile
Definition: videooutbase.h:330
uint Size(BufferType type) const
static guint32 * tmp
Definition: goom_core.c:35
void * GetDecoderContext(unsigned char *buf, uint8_t *&id) override
void ClearDummyFrame(VideoFrame *frame) override
Clears the frame to black.
void DrawDisplayRect(const QRect &rect, bool use_colorkey=false)
void DestroyLayer(uint id)
unsigned char r
Definition: ParseText.cpp:329
virtual void EmbedInWidget(const QRect &rect)
Tells video output to embed video in an existing window.
bool InitPIPLayer(QSize size)
void * GetMatrix(void)
virtual void ClearDummyFrame(VideoFrame *frame)
Clears the frame to black.
QSize GetSize(void) const
#define MIN_REFERENCE_FRAMES
bool SetDeinterlacingEnabled(bool interlaced) override
Attempts to enable/disable deinterlacing using existing deinterlace method when enabling.
unsigned char b
Definition: ParseText.cpp:329
long long framesPlayed
Definition: videooutbase.h:361
bool m_checked_surface_ownership
bool CreateBuffers(VideoFrameType type, int width, int height, vector< unsigned char * > bufs, vector< YUVInfo > yuvinfo)
void DrawSlice(VideoFrame *, int x, int y, int w, int h) override
Informs video output of new data for frame, used for hardware accelerated decoding.
#define NUM_REFERENCE_FRAMES
void DestroyVideoMixer(uint id)
#define MAX_PROCESS_BUFFER
virtual void ShowPIPs(VideoFrame *frame, const PIPMap &pipPlayers)
int offsets[3]
Y, U, & V offsets.
Definition: mythframe.h:64
static bool IsVDPAUAvailable(void)
bool MixAndRend(uint id, VdpVideoMixerPictureStructure field, uint vid_surface, uint out_surface, const QVector< uint > *refs, bool top, QRect src, const QRect &dst, QRect dst_vid, uint layer1=0, uint layer2=0)
frame_queue_t::iterator end(BufferType)
QString GetFilters(void) const
void EmbedInWidget(const QRect &rect) override
Tells video output to embed video in an existing window.
void ChangeVideoSurfaceOwner(uint id)
void Teardown(void) override
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
virtual void FreeResources(void)
Definition: mythpainter.h:49
bool DrawLayer(uint id, uint target)
void DestroyOutputSurface(uint id)
VideoBuffers vbuffers
VideoBuffers instance used to track video output buffers.
Definition: videooutbase.h:357
void DoneDisplayingFrame(VideoFrame *frame) override
Releases frame returned from GetLastShownFrame() onto the queue of frames ready for decoding onto.
void ReleaseCurrentFrame(VideoFrame *frame)
deque< VideoFrame * >::iterator iterator
Definition: mythdeque.h:44
int height
Definition: mythframe.h:42
void RemovePIP(MythPlayer *pipplayer) override
MythCodecID video_codec_id
Definition: videooutbase.h:329
QRect GetEmbeddingRect(void) const
VideoErrorState errorState
Definition: videooutbase.h:360
bool FrameIsInUse(VideoFrame *frame)
union AVVDPAUPictureInfo info
picture parameter information for all supported codecs
virtual void BestDeint(void)
Change to the best deinterlacing method.
unsigned char t
Definition: ParseText.cpp:329
void RestoreDisplay(void)
QRect GetTmpDisplayVisibleRect(void) const
void SetSwapControl(bool swap)
void SetNeedRepaint(bool needRepaint)
void ClearReferenceFrames(void)
static bool gVDPAUNVIDIA
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
bool CreateBuffer(int width, int height, uint num, void *data, VideoFrameType fmt)
bool DrawDirect(MythPainter *painter, QSize size, bool repaint=false)
Definition: osd.cpp:672
void InitDisplayMeasurements(uint width, uint height, bool resize)
Init display measurements based on database settings and actual screen parameters.
bool GetScreenShot(int width=0, int height=0, QString filename="")
bool IsEmbedding(void) const
Returns if videooutput is embedding.
long long frameNumber
Definition: mythframe.h:48
void DeleteRender(void)
void end_lock()
Definition: videobuffers.h:100
uint AddBuffer(int width, int height, void *data, VideoFrameType fmt)
AVVDPAUContext * m_context
PictureAttribute
Definition: videoouttypes.h:89
int pix_fmt
Definition: mythframe.h:66
QRect vsz_desired_display_rect
Definition: videooutbase.h:343
bool InitBuffers(void)
void Zoom(ZoomDirection direction) override
Sets up zooming into to different parts of the video, the zoom is actually applied in MoveResize().
QRect GetDisplayVideoRect(void) const
int top_field_first
1 if top field is first.
Definition: mythframe.h:58
void ClearAfterSeek(void) override
Tells video output to toss decoded buffers due to a seek.
const char * name
Definition: ParseText.cpp:328
void UpdatePauseFrame(int64_t &disp_timecode) override
Updates frame displayed when video is paused.
int SetPictureAttribute(PictureAttribute attribute, int newValue) override
Sets a specified picture attribute.
QVector< uint > m_video_surfaces
void * GetRender(uint id)
bool vsz_enabled
Definition: videooutbase.h:342
virtual QStringList GetVisualiserList(void)
bool UploadYUVFrame(uint id, void *const planes[3], uint32_t pitches[3])
void SetColourSpace(VideoCStd csp=kCSTD_Unknown)
uint CreateDecoder(const QSize &size, VdpDecoderProfile profile, uint references, uint existing=0)
PIPState GetPIPState(void) const
DisplayRes * display_res
Definition: videooutbase.h:364
AdjustFillMode GetAdjustFill(void) const
Returns current adjust fill mode.
static bool H264DecoderSizeSupported(uint width, uint height)
PIPLocation
Definition: videoouttypes.h:19
AdjustFillMode
Definition: videoouttypes.h:57
QSize GetActualVideoDim(void) const
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
QSize GetVideoBufferSize(void) const
Definition: mythplayer.h:173
#define CHECK_ERROR(Loc)
int64_t disp_timecode
Definition: mythframe.h:50
bool GetBoolSetting(const QString &key, bool defaultval=false)
static QStringList GetAllowedRenderers(MythCodecID myth_codec_id, const QSize &video_dim)
void VideoAspectRatioChanged(float aspect) override
Calls SetVideoAspectRatio(float aspect), then calls MoveResize() to apply changes.
void InitPictureAttributes(void) override
void Show(FrameScanType) override
static QStringList GetVisualiserList(RenderType type)
Definition: videovisual.cpp:14
virtual QRect GetPIPRect(PIPLocation location, MythPlayer *pipplayer=nullptr, bool do_pixel_adj=true) const
returns QRect of PIP based on PIPLocation
VideoFrame * Head(BufferType)
virtual VideoFrame * GetLastShownFrame(void)
Returns frame from the head of the ready to be displayed queue, if StartDisplayingFrame has been call...
Definition: videooutbase.h:239
virtual void VideoAspectRatioChanged(float aspect)
Calls SetVideoAspectRatio(float aspect), then calls MoveResize() to apply changes.
virtual void Zoom(ZoomDirection direction)
Sets up zooming into to different parts of the video, the zoom is actually applied in MoveResize().
QVector< uint > m_reference_frames
void SetSupportedAttributes(PictureAttributeSupported supported)
static bool IsNVIDIA(void)
void StopEmbedding(void) override
Tells video output to stop embedding video in an existing window.
virtual void MoveResize(void)
performs all the calculations for video framing and any resizing.
MythPainter * GetOSDPainter(void) override
static void GetRenderOptions(render_opts &opts)
Definition: osd.h:132
void DeleteVideoSurfaces(void)
float GetVideoAspect(void) const
virtual void Draw(const QRect &area, MythPainter *painter, QPaintDevice *device)=0
QRect GetDisplayVisibleRect(void) const
#define codec_is_vdpau_hw(id)
Definition: mythcodecid.h:131
bool Contains(BufferType type, VideoFrame *) const
QSize GetVideoDim(void) const
bool GetScreenShot(int width=0, int height=0, QString filename="") override
void MoveResizeWindow(QRect new_rect) override
uint CreateLayer(uint surface, const QRect *src=nullptr, const QRect *dst=nullptr)
bool IsPIPVisible(void) const
Definition: mythplayer.h:229
VideoOutWindow window
Definition: videooutbase.h:320
void DeleteBuffers(void)
#define MAX_REFERENCE_FRAMES
void ClaimVideoSurfaces(void)
void Init(uint numdecode, bool extra_for_pause, uint need_free, uint needprebuffer_normal, uint needprebuffer_small, uint keepprebuffer)
Creates buffers and sets various buffer management parameters.
void ToggleAdjustFill(AdjustFillMode adjustFillMode=kAdjustFill_Toggle)
Sets up letterboxing for various standard video frame and monitor dimensions, then calls MoveResize()...
frame_queue_t::iterator begin_lock(BufferType)
MythRenderVDPAU * m_render
void ShowPIP(VideoFrame *frame, MythPlayer *pipplayer, PIPLocation loc) override
Composites PiP image onto a video frame.
void DiscardFrames(bool next_frame_keyframe)
Mark all used frames as ready to be reused, this is for seek.
unsigned char * buf
Definition: mythframe.h:39
ZoomDirection
Definition: videoouttypes.h:28
uint CreateOutputSurface(const QSize &size, VdpRGBAFormat fmt=VDP_RGBA_FORMAT_B8G8R8A8, uint existing=0)
void DeleteBuffers(void)
void SetDisplayVisibleRect(QRect rect)
#define MIN_PROCESS_BUFFER
void PrepareFrame(VideoFrame *, FrameScanType, OSD *osd) override
bool CreateVideoSurfaces(uint num)
bool Init(const QSize &video_dim_buf, const QSize &video_dim_disp, float aspect, WId winid, const QRect &win_rect, MythCodecID codec_id) override
Performs most of the initialization for VideoOutput.
int SetPictureAttribute(PictureAttribute attribute, int value)
#define codec_is_std(id)
Definition: mythcodecid.h:127
#define DEF_PROCESS_BUFFER
bool IsPIPActive(void) const
Definition: mythplayer.h:228
VdpVideoSurface surface
Used as rendered surface, never changed.
MythVDPAUPainter * m_osd_painter
int SetMixerAttribute(uint id, uint attrib, int value)
VideoFrameType codec
Definition: mythframe.h:38