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(0)
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
172  delete invalid_osd_painter;
174  }
175 
176  if (m_render)
177  {
178  if (m_decoder)
180 
181  m_render->DecrRef();
182  m_render = nullptr;
183  }
184 
186  m_osd_painter = nullptr;
187  m_decoder = 0;
188  m_render = nullptr;
189  m_pix_fmt = -1;
190 }
191 
193 {
194  QMutexLocker locker(&m_lock);
195  if (!m_render)
196  return false;
197 
199  const QSize video_dim = codec_is_std(video_codec_id) ?
201 
202  vbuffers.Init(buffer_size, false, 2, 1, 4, 1);
203 
204  bool ok = false;
206  {
207  ok = CreateVideoSurfaces(buffer_size);
208  if (ok)
209  {
210  for (int i = 0; i < m_video_surfaces.size(); i++)
211  ok &= vbuffers.CreateBuffer(video_dim.width(),
212  video_dim.height(), i,
214  FMT_VDPAU);
215  }
216  }
217  else if (codec_is_std(video_codec_id))
218  {
220  if (ok)
222  video_dim.width(), video_dim.height());
223  }
224 
225  if (!ok)
226  {
227  LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to create VDPAU buffers");
228  }
229  else
230  {
231  m_video_mixer = m_render->CreateVideoMixer(video_dim, 2,
233  ok = m_video_mixer;
235 
236  if (ok && (m_mixer_features & kVDPFeatSharpness))
239  m_sharpen);
240  if (ok && (m_mixer_features & kVDPFeatDenoise))
243  m_denoise);
244  if (ok && m_skip_chroma)
247 
250  kVDPAttribBackground, 0x7F7F7FFF);
251  }
252 
253  if (!ok)
254  {
255  LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to create VDPAU mixer");
256  DeleteBuffers();
257  }
258 
259  return ok;
260 }
261 
263 {
264  if (!m_render || num < 1)
265  return false;
266 
267  bool ret = true;
268  const QSize size = codec_is_std(video_codec_id) ?
270  for (uint i = 0; i < num; i++)
271  {
273  if (tmp)
274  {
275  m_video_surfaces.push_back(tmp);
277  }
278  else
279  {
280  ret = false;
281  break;
282  }
283  }
284  return ret;
285 }
286 
288 {
289  if (!m_render || m_video_surfaces.isEmpty())
290  return;
291 
292  for (int i = 0; i < m_video_surfaces.size(); i++)
294  m_video_surfaces.clear();
295 }
296 
298 {
299  QMutexLocker locker(&m_lock);
300  if (m_render && m_video_mixer)
302  m_video_mixer = 0;
304  DiscardFrames(true);
306  vbuffers.Reset();
308 }
309 
311 {
312  QMutexLocker locker(&m_lock);
313 
314  const QRect tmp_display_visible_rect =
316  if (window.GetPIPState() == kPIPStandAlone &&
317  !tmp_display_visible_rect.isEmpty())
318  {
319  window.SetDisplayVisibleRect(tmp_display_visible_rect);
320  }
321  const QRect display_visible_rect = window.GetDisplayVisibleRect();
322 
323  if (m_render)
324  m_render->DrawDisplayRect(display_visible_rect);
325 }
326 
328 {
329  if ((interlaced && m_deinterlacing) ||
330  (!interlaced && !m_deinterlacing))
331  return m_deinterlacing;
332 
333  return SetupDeinterlace(interlaced);
334 }
335 
337  const QString &overridefilter)
338 {
339  m_lock.lock();
340  if (!m_render)
341  return false;
342 
343  bool enable = interlaced;
344 
346  {
347  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Disabled deinterlacing for HEVC/H.265");
348  enable = false;
349  }
350 
351  if (enable)
352  {
354  if (m_deintfiltername.contains("vdpau"))
355  {
356  uint features = kVDPFeatNone;
357  bool spatial = m_deintfiltername.contains("advanced");
358  bool temporal = m_deintfiltername.contains("basic") || spatial;
359  m_need_deintrefs = spatial || temporal;
360 
361  if (temporal)
362  features += kVDPFeatTemporal;
363 
364  if (spatial)
365  features += kVDPFeatSpatial;
366 
367  enable = m_render->SetDeinterlacing(m_video_mixer, features);
368  if (enable)
369  {
370  m_deinterlacing = true;
371  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Enabled deinterlacing.");
372  }
373  else
374  {
375  enable = false;
376  LOG(VB_PLAYBACK, LOG_INFO, LOC +
377  "Failed to enable deinterlacing.");
378  }
379  }
380  else
381  {
382  enable = false;
383  }
384  }
385 
386  if (!enable)
387  {
390  m_deintfiltername = QString();
391  m_deinterlacing = false;
392  m_need_deintrefs = false;
393  }
394  m_lock.unlock();
395  return enable;
396 }
397 
398 bool VideoOutputVDPAU::ApproveDeintFilter(const QString &filtername) const
399 {
400  return filtername.contains("vdpau");
401 }
402 
404  FilterChain */*filterList*/,
405  const PIPMap &pipPlayers,
406  FrameScanType /*scan*/)
407 {
408  QMutexLocker locker(&m_lock);
409  CHECK_ERROR("ProcessFrame");
410 
413 
414  m_pip_ready = false;
415  ShowPIPs(frame, pipPlayers);
416 }
417 
419 {
420  if (frame && m_render && !codec_is_std(video_codec_id))
421  {
422  struct vdpau_render_state *render =
423  (struct vdpau_render_state *)frame->buf;
424  if (render)
426  }
428 }
429 
431  OSD *osd)
432 {
433  QMutexLocker locker(&m_lock);
434  CHECK_ERROR("PrepareFrame");
435 
436  if (!m_render)
437  return;
438 
441  {
444  }
445 
446  bool new_frame = false;
447  bool dummy = false;
448  if (frame)
449  {
450  // FIXME for 0.23. This should be triggered from AFD by a seek
451  if ((abs(frame->frameNumber - framesPlayed) > 8))
453  new_frame = (framesPlayed != frame->frameNumber + 1);
454  framesPlayed = frame->frameNumber + 1;
455  dummy = frame->dummy;
456  }
457 
458  uint video_surface = m_video_surfaces[0];
459  bool deint = (m_deinterlacing && m_need_deintrefs &&
460  frame && !dummy);
461 
462  if (deint)
463  {
464  if (new_frame)
465  UpdateReferenceFrames(frame);
467  deint = false;
468  }
469 
470  if (!codec_is_std(video_codec_id) && frame)
471  {
472  struct vdpau_render_state *render =
473  (struct vdpau_render_state *)frame->buf;
474  if (!render)
475  return;
476  video_surface = m_render->GetSurfaceOwner(render->surface);
477  }
478  else if (new_frame && frame && !dummy)
479  {
480  // FIXME - reference frames for software decode
481  if (deint)
482  video_surface = m_video_surfaces[(framesPlayed + 1) %
484 
485  uint32_t pitches[3] = {
486  (uint32_t)frame->pitches[0],
487  (uint32_t)frame->pitches[2],
488  (uint32_t)frame->pitches[1]
489  };
490  void* const planes[3] = {
491  frame->buf,
492  frame->buf + frame->offsets[2],
493  frame->buf + frame->offsets[1]
494  };
495 
496  if (!m_render->UploadYUVFrame(video_surface, planes, pitches))
497  return;
498  }
499  else if (!frame)
500  {
501  deint = false;
502  video_surface = m_pause_surface;
503  }
504 
505  VdpVideoMixerPictureStructure field =
506  VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
507 
508  if (scan == kScan_Interlaced && m_deinterlacing && frame)
509  {
510  field = frame->top_field_first ?
511  VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD :
512  VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
513  }
514  else if (scan == kScan_Intr2ndField && m_deinterlacing && frame)
515  {
516  field = frame->top_field_first ?
517  VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD :
518  VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
519  }
520  else if (!frame && m_deinterlacing)
521  {
522  field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
523  }
524 
526 
527  QSize size = window.GetDisplayVisibleRect().size();
528  if (size != m_render->GetSize())
529  LOG(VB_GENERAL, LOG_ERR, LOC + "Unexpected display size.");
530 
531  if (dummy)
532  {
533  m_render->DrawBitmap(0, 0, nullptr, nullptr, kVDPBlendNormal, 255);
534  }
535  else
536  {
537  if (!m_render->MixAndRend(m_video_mixer, field, video_surface, 0,
538  deint ? &m_reference_frames : nullptr,
541  QRect(QPoint(0,0), size),
544  0, 0))
545  {
546  LOG(VB_PLAYBACK, LOG_ERR, LOC + "Prepare frame failed.");
547  }
548  }
549 
550  if (m_pip_ready)
552  if (m_visual)
554 
555  if (osd && m_osd_painter && !window.IsEmbedding())
556  osd->DrawDirect(m_osd_painter, GetTotalOSDBounds().size(), true);
557 
558  if (!frame)
559  {
560  VideoFrame *buf = GetLastShownFrame();
561  if (buf)
562  buf->timecode = 0;
563  }
564 }
565 
567 {
568  if (!m_render)
569  return;
570 
571  QVector<uint>::iterator it;
572  for (it = m_video_surfaces.begin(); it != m_video_surfaces.end(); ++it)
575 }
576 
577 void VideoOutputVDPAU::DrawSlice(VideoFrame *frame, int /* x */, int /* y */, int /* w */, int /* h */)
578 {
579  CHECK_ERROR("DrawSlice");
580 
582  return;
583 
586 
587  struct vdpau_render_state *render =
588  (struct vdpau_render_state *)frame->priv[0];
589  const VdpPictureInfo *info = (const VdpPictureInfo *)frame->priv[1];
590 
591  if (frame->pix_fmt != m_pix_fmt)
592  {
593  if (m_decoder)
594  {
595  LOG(VB_GENERAL, LOG_ERR, LOC + "Picture format has changed.");
597  return;
598  }
599 
600  uint max_refs = MIN_REFERENCE_FRAMES;
602  {
603  max_refs = ((VdpPictureInfoH264*)info)->num_ref_frames;
604  if (max_refs < 1 || max_refs > MAX_REFERENCE_FRAMES)
605  {
606  uint32_t round_width = (frame->width + 15) & ~15;
607  uint32_t round_height = (frame->height + 15) & ~15;
608  uint32_t surf_size = (round_width * round_height * 3) / 2;
609  max_refs = (12 * 1024 * 1024) / surf_size;
610  }
611  if (max_refs > MAX_REFERENCE_FRAMES)
612  max_refs = MAX_REFERENCE_FRAMES;
613 
614  // Add extra buffers as necessary
615  int needed = max_refs - m_decoder_buffer_size;
616  if (needed > 0)
617  {
618  QMutexLocker locker(&m_lock);
619  const QSize size = window.GetActualVideoDim();
620  uint created = 0;
621  for (int i = 0; i < needed; i++)
622  {
624  if (tmp)
625  {
626  m_video_surfaces.push_back(tmp);
628  if (vbuffers.AddBuffer(size.width(), size.height(),
630  FMT_VDPAU))
631  {
632  created++;
633  }
634  }
635  }
636  m_decoder_buffer_size += created;
637  LOG(VB_GENERAL, LOG_INFO, LOC +
638  QString("Added %1 new buffers. New buffer size %2 "
639  "(%3 decode and %4 process)")
640  .arg(created).arg(vbuffers.Size())
642  .arg(m_process_buffer_size));
643  }
644  }
645 
646  VdpDecoderProfile vdp_decoder_profile;
647  switch (video_codec_id)
648  {
649  case kCodec_MPEG1_VDPAU:
650  vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG1;
651  break;
652  case kCodec_MPEG2_VDPAU:
653  vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG2_MAIN;
654  break;
655  case kCodec_MPEG4_VDPAU:
656  vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP;
657  break;
658  case kCodec_H264_VDPAU:
659  vdp_decoder_profile = VDP_DECODER_PROFILE_H264_HIGH;
660  break;
661  case kCodec_WMV3_VDPAU:
662  vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_MAIN;
663  break;
664  case kCodec_VC1_VDPAU:
665  vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_ADVANCED;
666  break;
667 #ifdef VDP_DECODER_PROFILE_HEVC_MAIN
668  case kCodec_HEVC_VDPAU:
669  vdp_decoder_profile = VDP_DECODER_PROFILE_HEVC_MAIN;
670  max_refs = 16;
671  break;
672 #endif
673  default:
674  LOG(VB_GENERAL, LOG_ERR, LOC +
675  "Codec is not supported.");
677  return;
678  }
679 
681  vdp_decoder_profile, max_refs);
682  if (m_decoder)
683  {
684  m_pix_fmt = frame->pix_fmt;
685  LOG(VB_PLAYBACK, LOG_INFO, LOC +
686  QString("Created VDPAU decoder (%1 ref frames)")
687  .arg(max_refs));
688  }
689  else
690  {
691  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create decoder.");
693  return;
694  }
695  }
696  else if (!m_decoder)
697  {
698  LOG(VB_GENERAL, LOG_ERR, LOC +
699  "Pix format already set but no VDPAU decoder.");
701  return;
702  }
703 
704  m_render->Decode(m_decoder, render, info);
705 }
706 
708 {
709  QMutexLocker locker(&m_lock);
710  CHECK_ERROR("Show");
711 
712  if (window.IsRepaintNeeded())
713  DrawUnusedRects(false);
714 
715  if (m_render)
716  m_render->Flip();
718 }
719 
721 {
722  m_lock.lock();
723  LOG(VB_PLAYBACK, LOG_INFO, LOC + "ClearAfterSeek()");
724  DiscardFrames(false);
725  m_lock.unlock();
726 }
727 
728 bool VideoOutputVDPAU::InputChanged(const QSize &video_dim_buf,
729  const QSize &video_dim_disp,
730  float aspect,
731  MythCodecID av_codec_id,
732  void */*codec_private*/,
733  bool &aspect_only)
734 {
735  LOG(VB_PLAYBACK, LOG_INFO, LOC +
736  QString("InputChanged(%1,%2,%3) '%4'->'%5'")
737  .arg(video_dim_disp.width()).arg(video_dim_disp.height())
738  .arg(aspect)
739  .arg(toString(video_codec_id)).arg(toString(av_codec_id)));
740 
741  QMutexLocker locker(&m_lock);
742 
743  // Ensure we don't lose embedding through program changes. This duplicates
744  // code in VideoOutput::Init but we need start here otherwise the embedding
745  // is lost during window re-initialistion.
746  bool wasembedding = window.IsEmbedding();
747  QRect oldrect;
748  if (wasembedding)
749  {
750  oldrect = window.GetEmbeddingRect();
751  StopEmbedding();
752  }
753 
754  bool cid_changed = (video_codec_id != av_codec_id);
755  bool res_changed = video_dim_disp != window.GetActualVideoDim();
756  bool asp_changed = aspect != window.GetVideoAspect();
757 
758  if (!res_changed && !cid_changed)
759  {
760  aspect_only = true;
761  if (asp_changed)
762  {
763  VideoAspectRatioChanged(aspect);
764  MoveResize();
765  }
766  if (wasembedding)
767  EmbedInWidget(oldrect);
768  return true;
769  }
770 
771  AdjustFillMode oldadjustfillmode = window.GetAdjustFill();
772 
773  TearDown();
774  QRect disp = window.GetDisplayVisibleRect();
775  if (Init(video_dim_buf, video_dim_disp,
776  aspect, m_win, disp, av_codec_id))
777  {
778  if (wasembedding)
779  EmbedInWidget(oldrect);
780  BestDeint();
781  window.ToggleAdjustFill(oldadjustfillmode);
782  return true;
783  }
784 
785  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to re-initialise video output.");
787 
788  return false;
789 }
790 
792 {
793  QMutexLocker locker(&m_lock);
794  VideoOutput::Zoom(direction);
795  MoveResize();
796 }
797 
799 {
800  QMutexLocker locker(&m_lock);
802 }
803 
804 void VideoOutputVDPAU::EmbedInWidget(const QRect &rect)
805 {
806  QMutexLocker locker(&m_lock);
807  if (!window.IsEmbedding())
808  {
810  MoveResize();
812  }
813 }
814 
816 {
817  if (!window.IsEmbedding())
818  return;
819  QMutexLocker locker(&m_lock);
821  MoveResize();
822 }
823 
825 {
826  m_lock.lock();
827  if (m_render)
828  m_render->MoveResizeWin(new_rect);
829  m_lock.unlock();
830 }
831 
833 {
834  m_lock.lock();
836  {
837  const QRect dvr = window.GetDisplayVisibleRect();
838  m_render->DrawDisplayRect(dvr, true);
839  window.SetNeedRepaint(false);
840  if (sync)
842  }
843  m_lock.unlock();
844 }
845 
846 void VideoOutputVDPAU::UpdatePauseFrame(int64_t &disp_timecode)
847 {
848  QMutexLocker locker(&m_lock);
849 
850  LOG(VB_PLAYBACK, LOG_INFO, LOC + "UpdatePauseFrame() " +
851  vbuffers.GetStatus());
852 
854 
856  {
858  disp_timecode = frame->disp_timecode;
860  {
862  uint32_t pitches[3] = { (uint32_t)frame->pitches[0],
863  (uint32_t)frame->pitches[2],
864  (uint32_t)frame->pitches[1] };
865  void* const planes[3] = { frame->buf,
866  frame->buf + frame->offsets[2],
867  frame->buf + frame->offsets[1] };
868  m_render->UploadYUVFrame(m_video_surfaces[0], planes, pitches);
869  }
870  else
871  {
872  struct vdpau_render_state *render =
873  (struct vdpau_render_state *)frame->buf;
874  if (render)
876  }
877  }
878  else
879  LOG(VB_PLAYBACK, LOG_WARNING, LOC +
880  "Could not update pause frame - no used frames.");
881 
882  vbuffers.end_lock();
883 }
884 
886 {
893 
894  m_lock.lock();
895  if (m_render && m_video_mixer)
896  {
897  if (m_colorspace < 0)
898  {
899  QSize size = window.GetVideoDim();
900  m_colorspace = (size.width() > 720 || size.height() > 576) ?
901  VDP_COLOR_STANDARD_ITUR_BT_709 :
902  VDP_COLOR_STANDARD_ITUR_BT_601;
903  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Using ITU %1 colorspace")
904  .arg((m_colorspace == VDP_COLOR_STANDARD_ITUR_BT_601) ?
905  "BT.601" : "BT.709"));
906  }
907 
908  if (m_colorspace != VDP_COLOR_STANDARD_ITUR_BT_601)
909  {
910  videoColourSpace.SetColourSpace((m_colorspace == VDP_COLOR_STANDARD_ITUR_BT_601)
912  }
914  }
915  m_lock.unlock();
916 }
917 
919  int newValue)
920 {
921  if (!m_render || !m_video_mixer)
922  return -1;
923 
924  m_lock.lock();
925  newValue = videoColourSpace.SetPictureAttribute(attribute, newValue);
926  if (newValue >= 0)
928  m_lock.unlock();
929  return newValue;
930 }
931 
933  MythCodecID myth_codec_id, const QSize & /* video_dim */)
934 {
935  QStringList list;
936  if ((codec_is_std(myth_codec_id) || codec_is_vdpau_hw(myth_codec_id)) &&
937  !getenv("NO_VDPAU"))
938  {
939  list += "vdpau";
940  }
941 
942  return list;
943 }
944 
946  uint width, uint height, const QString &decoder,
947  uint stream_type, bool no_acceleration)
948 {
949  bool use_cpu = no_acceleration || (decoder != "vdpau") || getenv("NO_VDPAU");
950  MythCodecID test_cid = (MythCodecID)(kCodec_MPEG1_VDPAU + (stream_type-1));
951 
952  if (!use_cpu)
953  {
954  use_cpu |= !MythRenderVDPAU::IsVDPAUAvailable();
955  use_cpu |= !codec_is_vdpau_hw(test_cid);
956  if (!use_cpu && test_cid == kCodec_MPEG4_VDPAU)
957  use_cpu |= !MythRenderVDPAU::IsMPEG4Available();
958  if (!use_cpu && test_cid == kCodec_H264_VDPAU)
959  use_cpu |= !MythRenderVDPAU::H264DecoderSizeSupported(width, height);
960  if (!use_cpu && test_cid == kCodec_HEVC_VDPAU)
961  use_cpu |= !MythRenderVDPAU::IsHEVCAvailable();
962  }
963 
964  if (use_cpu)
965  return (MythCodecID)(kCodec_MPEG1 + (stream_type-1));
966 
967  return test_cid;
968 }
969 
971 {
972  // this forces the check of VDPAU capabilities
975 }
976 
978 {
979  while (m_reference_frames.size() > (NUM_REFERENCE_FRAMES - 1))
980  m_reference_frames.pop_front();
981 
984  {
985  struct vdpau_render_state *render =
986  (struct vdpau_render_state *)frame->buf;
987  if (render)
988  ref = m_render->GetSurfaceOwner(render->surface);
989  }
990 
991  m_reference_frames.push_back(ref);
992 }
993 
995 {
996  if (!frame || codec_is_std(video_codec_id))
997  return false;
998 
999  uint ref = 0;
1000  struct vdpau_render_state *render = (struct vdpau_render_state *)frame->buf;
1001  if (render)
1002  ref = m_render->GetSurfaceOwner(render->surface);
1003  return m_reference_frames.contains(ref);
1004 }
1005 
1007 {
1008  m_lock.lock();
1009  m_reference_frames.clear();
1010  m_lock.unlock();
1011 }
1012 
1014 {
1015  if (!frame)
1016  return;
1017 
1018  m_lock.lock();
1019  if (FrameIsInUse(frame))
1021  else
1022  {
1024  }
1025  m_lock.unlock();
1026 }
1027 
1028 void VideoOutputVDPAU::DiscardFrames(bool next_frame_keyframe)
1029 {
1030  m_lock.lock();
1031  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DiscardFrames(%1)")
1032  .arg(next_frame_keyframe));
1033  CheckFrameStates();
1035  vbuffers.DiscardFrames(next_frame_keyframe);
1036  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DiscardFrames() 3: %1 -- done()")
1037  .arg(vbuffers.GetStatus()));
1038  m_lock.unlock();
1039 }
1040 
1042 {
1043  m_lock.lock();
1044  if (vbuffers.Contains(kVideoBuffer_used, frame))
1045  DiscardFrame(frame);
1046  CheckFrameStates();
1047  m_lock.unlock();
1048 }
1049 
1051 {
1052  m_lock.lock();
1055  while (it != vbuffers.end(kVideoBuffer_displayed))
1056  {
1057  VideoFrame* frame = *it;
1058  if (!FrameIsInUse(frame))
1059  {
1061  {
1062  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1063  QString("Frame %1 is in use by avlib and so is "
1064  "being held for later discarding.")
1065  .arg(DebugString(frame, true)));
1066  }
1067  else
1068  {
1070  vbuffers.end_lock();
1072  continue;
1073  }
1074  }
1075  ++it;
1076  }
1077  vbuffers.end_lock();
1078  m_lock.unlock();
1079 }
1080 
1082 {
1083  if (!m_render)
1084  return false;
1085 
1086  if (!m_pip_surface)
1088 
1089  if (!m_pip_layer && m_pip_surface)
1091 
1092  return (m_pip_surface && m_pip_layer);
1093 }
1094 
1096 {
1097  while (!m_pips.empty())
1098  {
1099  RemovePIP(m_pips.begin().key());
1100  m_pips.erase(m_pips.begin());
1101  }
1102 
1103  m_pip_ready = false;
1104 }
1105 
1107 {
1108  if (m_render)
1109  {
1110  if (m_pip_surface)
1111  {
1113  m_pip_surface = 0;
1114  }
1115 
1116  if (m_pip_layer)
1117  {
1119  m_pip_layer = 0;
1120  }
1121  }
1122 
1123  m_pip_ready = false;
1124 }
1125 
1126 void VideoOutputVDPAU::ShowPIP(VideoFrame * /* frame */, MythPlayer *pipplayer,
1127  PIPLocation loc)
1128 {
1129  if (!pipplayer || !m_render)
1130  return;
1131 
1132  int pipw, piph;
1133  VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph);
1134  const bool pipActive = pipplayer->IsPIPActive();
1135  const bool pipVisible = pipplayer->IsPIPVisible();
1136  const float pipVideoAspect = pipplayer->GetVideoAspect();
1137  const QSize pipVideoDim = pipplayer->GetVideoBufferSize();
1138 
1139  if ((pipVideoAspect <= 0) || !pipimage ||
1140  !pipimage->buf || pipimage->codec != FMT_YV12 || !pipVisible)
1141  {
1142  pipplayer->ReleaseCurrentFrame(pipimage);
1143  return;
1144  }
1145 
1147  {
1148  if (m_pips.contains(pipplayer) &&
1149  m_pips[pipplayer].videoSize != pipVideoDim)
1150  RemovePIP(pipplayer);
1151 
1152  if (!m_pips.contains(pipplayer))
1153  {
1154  uint mixer = m_render->CreateVideoMixer(pipVideoDim, 0, 0);
1155  uint surf = m_render->CreateVideoSurface(pipVideoDim);
1156  vdpauPIP tmp = { pipVideoDim, surf, mixer};
1157  m_pips.insert(pipplayer, tmp);
1158  if (!mixer || !surf)
1159  RemovePIP(pipplayer);
1160  else
1161  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Created pip %1x%2")
1162  .arg(pipVideoDim.width()).arg(pipVideoDim.height()));
1163  }
1164 
1165  if (m_pips.contains(pipplayer))
1166  {
1167  QRect rect = GetPIPRect(loc, pipplayer);
1168 
1169  if (!m_pip_ready)
1170  m_render->DrawBitmap(0, m_pip_surface, nullptr, nullptr,
1171  kVDPBlendNull);
1172 
1173  uint32_t pitches[] = {
1174  (uint32_t)pipimage->pitches[0],
1175  (uint32_t)pipimage->pitches[2],
1176  (uint32_t)pipimage->pitches[1] };
1177  void* const planes[] = {
1178  pipimage->buf,
1179  pipimage->buf + pipimage->offsets[2],
1180  pipimage->buf + pipimage->offsets[1] };
1181 
1182  bool ok;
1183  ok = m_render->UploadYUVFrame(m_pips[pipplayer].videoSurface,
1184  planes, pitches);
1185  ok &= m_render->MixAndRend(m_pips[pipplayer].videoMixer,
1186  VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME,
1187  m_pips[pipplayer].videoSurface,
1188  m_pip_surface, nullptr, false,
1189  QRect(QPoint(0,0), pipVideoDim),
1190  rect, rect);
1191  ok &= m_render->DrawBitmap(0, m_pip_surface, nullptr, &rect,
1192  kVDPBlendPiP, 255);
1193 
1194  if (pipActive)
1195  {
1196  // TODO this could be one rect rendered before the video frame
1197  QRect l = QRect(QPoint(rect.x() - 10, rect.y() - 10),
1198  QSize(10, rect.height() + 20));
1199  QRect t = QRect(QPoint(rect.x(), rect.y() - 10),
1200  QSize(rect.width(), 10));
1201  QRect b = QRect(QPoint(rect.x(), rect.y() + rect.height()),
1202  QSize(rect.width(), 10));
1203  QRect r = QRect(QPoint(rect.x() + rect.width(), rect.y() -10),
1204  QSize(10, rect.height() + 20));
1205  m_render->DrawBitmap(0, m_pip_surface, nullptr, &l, kVDPBlendNormal, 255, 127);
1206  m_render->DrawBitmap(0, m_pip_surface, nullptr, &t, kVDPBlendNormal, 255, 127);
1207  m_render->DrawBitmap(0, m_pip_surface, nullptr, &b, kVDPBlendNormal, 255, 127);
1208  m_render->DrawBitmap(0, m_pip_surface, nullptr, &r, kVDPBlendNormal, 255, 127);
1209  }
1210 
1211  m_pip_ready = ok;
1212  }
1213  }
1214  pipplayer->ReleaseCurrentFrame(pipimage);
1215 }
1216 
1218 {
1219  if (!m_pips.contains(pipplayer))
1220  return;
1221 
1222  if (m_pips[pipplayer].videoSurface && m_render)
1223  m_render->DestroyVideoSurface(m_pips[pipplayer].videoSurface);
1224 
1225  if (m_pips[pipplayer].videoMixer && m_render)
1226  m_render->DestroyVideoMixer(m_pips[pipplayer].videoMixer);
1227 
1228  m_pips.remove(pipplayer);
1229  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Removed 1 PIP");
1230 
1231  if (m_pips.empty())
1232  DeinitPIPLayer();
1233 }
1234 
1236 {
1237  m_skip_chroma = false;
1238  m_denoise = 0.0f;
1239  m_sharpen = 0.0f;
1240  m_colorspace = VDP_COLOR_STANDARD_ITUR_BT_601;
1242 
1247 
1248  QStringList list = GetFilters().split(",");
1249  if (list.empty())
1250  return;
1251 
1252  for (QStringList::Iterator i = list.begin(); i != list.end(); ++i)
1253  {
1254  QString name = (*i).section('=', 0, 0).toLower();
1255  QString opts = (*i).section('=', 1).toLower();
1256 
1257  if (!name.contains("vdpau"))
1258  continue;
1259 
1260  if (name.contains("vdpaubuffercount"))
1261  {
1262  uint num = opts.toUInt();
1263  if (MIN_PROCESS_BUFFER <= num && num <= MAX_PROCESS_BUFFER)
1264  {
1265  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1266  QString("VDPAU process buffer size set to %1 (was %2)")
1267  .arg(num).arg(m_process_buffer_size));
1268  m_process_buffer_size = num;
1269  }
1270  }
1271  else if (name.contains("vdpauivtc"))
1272  {
1273  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1274  "Enabling VDPAU inverse telecine "
1275  "(requires Basic or Advanced deinterlacer)");
1277  }
1278  else if (name.contains("vdpauskipchroma"))
1279  {
1280  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Enabling SkipChromaDeinterlace.");
1281  m_skip_chroma = true;
1282  }
1283  else if (name.contains("vdpaudenoise"))
1284  {
1285  float tmp = std::max(0.0f, std::min(1.0f, opts.toFloat()));
1286  if (tmp != 0.0f)
1287  {
1288  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1289  QString("VDPAU Denoise %1").arg(tmp,4,'f',2,'0'));
1290  m_denoise = tmp;
1292  }
1293  }
1294  else if (name.contains("vdpausharpen"))
1295  {
1296  float tmp = std::max(-1.0f, std::min(1.0f, opts.toFloat()));
1297  if (tmp != 0.0f)
1298  {
1299  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1300  QString("VDPAU Sharpen %1").arg(tmp,4,'f',2,'0'));
1301  m_sharpen = tmp;
1303  }
1304  }
1305  else if (name.contains("vdpaucolorspace"))
1306  {
1307  if (opts.contains("auto"))
1308  m_colorspace = -1;
1309  else if (opts.contains("601"))
1310  m_colorspace = VDP_COLOR_STANDARD_ITUR_BT_601;
1311  else if (opts.contains("709"))
1312  m_colorspace = VDP_COLOR_STANDARD_ITUR_BT_709;
1313 
1314  if (m_colorspace > -1)
1315  {
1316  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1317  QString("Forcing ITU BT.%1 colorspace")
1318  .arg((m_colorspace == VDP_COLOR_STANDARD_ITUR_BT_601) ?
1319  "BT.601" : "BT.709"));
1320  }
1321  }
1322  else if (name.contains("vdpauhqscaling"))
1323  {
1325  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1326  "Requesting high quality scaling.");
1327  }
1328  }
1329 }
1330 
1332 {
1333  return m_osd_painter;
1334 }
1335 
1336 bool VideoOutputVDPAU::GetScreenShot(int width, int height, QString filename)
1337 {
1338  if (m_render)
1339  return m_render->GetScreenShot(width, height, filename);
1340  return false;
1341 }
1342 
1344 {
1345  if (m_render)
1348 }
1349 
1351 {
1352  if (!m_render)
1353  {
1354  LOG(VB_PLAYBACK, LOG_ERR, QString("SetVideoFlip failed."));
1355  return;
1356  }
1358 }
1359 
1360 void* VideoOutputVDPAU::GetDecoderContext(unsigned char* /*buf*/, uint8_t*& /*id*/)
1361 {
1362  return m_context;
1363 }
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)
bool DrawBitmap(uint id, uint target, const QRect *src, const QRect *dst, VDPBlendType blendi=kVDPBlendNormal, int alpha=0, int red=0, int blue=0, int green=0)
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:114
void DestroyDecoder(uint id)
MythPainter * GetMythPainter(void)
QRect GetTotalOSDBounds(void) const
Returns total OSD bounds.
VideoFrame * GetCurrentFrame(int &w, int &h)
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:340
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:340
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:340
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:671
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:339
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:16
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:116
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:112
#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