MythTV  master
videooutbase.cpp
Go to the documentation of this file.
1 #include <cmath>
2 #include <cstdlib>
3 
4 #include <QRunnable>
5 
6 #include "osd.h"
7 #include "mythplayer.h"
8 #include "videodisplayprofile.h"
9 #include "decoderbase.h"
10 
11 #include "mythcorecontext.h"
12 #include "mythlogging.h"
13 #include "mythmainwindow.h"
14 #include "mythuihelper.h"
15 #include "mythpainter_yuva.h"
16 #include "util-osd.h"
17 #include "mythxdisplay.h"
18 #include "mythavutil.h"
19 #include "mthreadpool.h"
20 #include "mythcodeccontext.h"
21 
22 #ifdef USING_XV
23 #include "videoout_xv.h"
24 #endif
25 
26 #ifdef _WIN32
27 #include "videoout_d3d.h"
28 #endif
29 
30 #ifdef USING_OPENGL_VIDEO
31 #include "videoout_opengl.h"
32 #endif
33 
34 #ifdef USING_VDPAU
35 #include "videoout_vdpau.h"
36 #include "videoout_nullvdpau.h"
37 #endif
38 
39 #ifdef USING_VAAPI
40 #include "videoout_nullvaapi.h"
41 #endif
42 #ifdef USING_GLVAAPI
43 #include "videoout_openglvaapi.h"
44 #endif
45 
46 #ifdef USING_OPENMAX
47 #include "videoout_omx.h"
48 #endif
49 
50 #include "videoout_null.h"
51 #include "dithertable.h"
52 
53 extern "C" {
54 #include "libavcodec/avcodec.h"
55 #include "libswscale/swscale.h"
56 #include "libavutil/imgutils.h"
57 }
58 
59 #include "filtermanager.h"
60 
61 #include "videooutbase.h"
62 
63 #define LOC QString("VideoOutput: ")
64 
65 static QString to_comma_list(const QStringList &list);
66 
68 {
69  FilterManager fm;
70  QStringList cpudeints;
71  cpudeints += "onefield";
72  cpudeints += "linearblend";
73  cpudeints += "kerneldeint";
74  cpudeints += "kerneldoubleprocessdeint";
75  if (fm.GetFilterInfo("greedyhdeint"))
76  cpudeints += "greedyhdeint";
77  if (fm.GetFilterInfo("greedyhdoubleprocessdeint"))
78  cpudeints += "greedyhdoubleprocessdeint";
79  cpudeints += "yadifdeint";
80  cpudeints += "yadifdoubleprocessdeint";
81  cpudeints += "fieldorderdoubleprocessdeint";
82  cpudeints += "none";
83 
85 
86 #ifdef _WIN32
88 #endif
89 
90 #ifdef USING_XV
92 #endif // USING_XV
93 
94 #ifdef USING_OPENGL_VIDEO
96 #endif // USING_OPENGL_VIDEO
97 
98 #ifdef USING_VDPAU
101 #endif // USING_VDPAU
102 
103 #ifdef USING_VAAPI
105 #endif // USING_VAAPI
106 #ifdef USING_GLVAAPI
108 #endif // USING_GLVAAPI
109 
110 #ifdef USING_OPENMAX
112 #endif // USING_OPENMAX
113 }
114 
121  const QString &decoder, MythCodecID codec_id, void *codec_priv,
122  PIPState pipState, const QSize &video_dim_buf,
123  const QSize &video_dim_disp, float video_aspect,
124  QWidget *parentwidget, const QRect &embed_rect, float video_prate,
125  uint playerFlags, QString &codecName)
126 {
127  (void) codec_priv;
128  QStringList renderers;
129 #ifdef USING_XV
130  QStringList xvlist;
131 #endif
132 
133  // select the best available output
134  if (playerFlags & kVideoIsNull)
135  {
136  // plain null output
137  renderers += "null";
138 
139  if (playerFlags & kDecodeAllowGPU)
140  {
141 #ifdef USING_VDPAU
142  renderers += VideoOutputNullVDPAU::GetAllowedRenderers(codec_id);
143 #endif // USING_VDPAU
144 #ifdef USING_VAAPI
145  renderers += VideoOutputNullVAAPI::GetAllowedRenderers(codec_id);
146 #endif
147  }
148  }
149  else
150  {
151 #ifdef _WIN32
152  renderers += VideoOutputD3D::
153  GetAllowedRenderers(codec_id, video_dim_disp);
154 #endif
155 
156 #ifdef USING_XV
157  xvlist = VideoOutputXv::
158  GetAllowedRenderers(codec_id, video_dim_disp);
159  renderers += xvlist;
160 #endif // USING_XV
161 
162 #ifdef USING_OPENGL_VIDEO
163  renderers += VideoOutputOpenGL::
164  GetAllowedRenderers(codec_id, video_dim_disp);
165 #endif // USING_OPENGL_VIDEO
166 
167 #ifdef USING_VDPAU
168  renderers += VideoOutputVDPAU::
169  GetAllowedRenderers(codec_id, video_dim_disp);
170 #endif // USING_VDPAU
171 
172 #ifdef USING_GLVAAPI
173  renderers += VideoOutputOpenGLVAAPI::
174  GetAllowedRenderers(codec_id, video_dim_disp);
175 #endif // USING_GLVAAPI
176 
177 #ifdef USING_OPENMAX
178  renderers += VideoOutputOMX::
179  GetAllowedRenderers(codec_id, video_dim_disp);
180 #endif // USING_OPENMAX
181  }
182 
183  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Allowed renderers: " +
184  to_comma_list(renderers));
185 
186  renderers = VideoDisplayProfile::GetFilteredRenderers(decoder, renderers);
187 
188  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Allowed renderers (filt: " + decoder +
189  "): " + to_comma_list(renderers));
190 
191  QString renderer;
192 
194 
195  if (!renderers.empty())
196  {
197  vprof->SetInput(video_dim_disp, video_prate, codecName);
198  QString tmp = vprof->GetVideoRenderer();
199  if (vprof->IsDecoderCompatible(decoder) && renderers.contains(tmp))
200  {
201  renderer = tmp;
202  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Preferred renderer: " + renderer);
203  }
204  }
205 
206  if (renderer.isEmpty())
207  renderer = VideoDisplayProfile::GetBestVideoRenderer(renderers);
208 
209  while (!renderers.empty())
210  {
211  LOG(VB_PLAYBACK, LOG_INFO, LOC +
212  QString("Trying video renderer: '%1'").arg(renderer));
213  int index = renderers.indexOf(renderer);
214  if (index >= 0)
215  renderers.removeAt(index);
216  else
217  break;
218 
219  VideoOutput *vo = nullptr;
220 
221  /* these cases are mutually exlusive */
222  if (renderer == "null")
223  vo = new VideoOutputNull();
224 
225 #ifdef _WIN32
226  else if (renderer == "direct3d")
227  vo = new VideoOutputD3D();
228 #endif // _WIN32
229 
230 #ifdef USING_OPENGL_VIDEO
231  else if (renderer.contains("opengl") && (renderer != "openglvaapi"))
232  vo = new VideoOutputOpenGL(renderer);
233 #endif // USING_OPENGL_VIDEO
234 
235 #ifdef USING_VDPAU
236  else if (renderer == "vdpau")
237  vo = new VideoOutputVDPAU();
238  else if (renderer == "nullvdpau")
239  vo = new VideoOutputNullVDPAU();
240 #endif // USING_VDPAU
241 
242 #ifdef USING_VAAPI
243  else if (renderer == "nullvaapi")
244  vo = new VideoOutputNullVAAPI();
245 #endif // USING_VAAPI
246 
247 #ifdef USING_GLVAAPI
248  else if (renderer == "openglvaapi")
249  vo = new VideoOutputOpenGLVAAPI();
250 #endif // USING_GLVAAPI
251 
252 #ifdef USING_OPENMAX
253  else if (renderer == VideoOutputOMX::kName)
254  vo = new VideoOutputOMX();
255 #endif // USING_OPENMAX
256 
257 #ifdef USING_XV
258  else if (xvlist.contains(renderer))
259  vo = new VideoOutputXv();
260 #endif // USING_XV
261  if (vo)
262  vo->db_vdisp_profile = vprof;
263 
264  if (vo && !(playerFlags & kVideoIsNull))
265  {
266  // ensure we have a window to display into
267  QWidget *widget = parentwidget;
269  if (!widget && window)
270  widget = window->findChild<QWidget*>("video playback window");
271 
272  if (!widget)
273  {
274  LOG(VB_GENERAL, LOG_ERR, LOC + "No window for video output.");
275  delete vo;
276  vo = nullptr;
277  return nullptr;
278  }
279 
280  if (!widget->winId())
281  {
282  LOG(VB_GENERAL, LOG_ERR, LOC + "No window for video output.");
283  delete vo;
284  vo = nullptr;
285  return nullptr;
286  }
287 
288  // determine the display rectangle
289  QRect display_rect = QRect(0, 0, widget->width(), widget->height());
290  if (pipState == kPIPStandAlone)
291  display_rect = embed_rect;
292 
293  vo->SetPIPState(pipState);
294  vo->SetVideoFrameRate(video_prate);
295  if (vo->Init(
296  video_dim_buf, video_dim_disp, video_aspect,
297  widget->winId(), display_rect, codec_id))
298  {
299  vo->SetVideoScalingAllowed(true);
300  return vo;
301  }
302 
303  vo->db_vdisp_profile = nullptr;
304  delete vo;
305  vo = nullptr;
306  }
307  else if (vo && (playerFlags & kVideoIsNull))
308  {
309  if (vo->Init(video_dim_buf, video_dim_disp,
310  video_aspect, 0, QRect(), codec_id))
311  {
312  return vo;
313  }
314 
315  vo->db_vdisp_profile = nullptr;
316  delete vo;
317  vo = nullptr;
318  }
319 
320  renderer = VideoDisplayProfile::GetBestVideoRenderer(renderers);
321  }
322 
323  LOG(VB_GENERAL, LOG_ERR, LOC +
324  "Not compiled with any useable video output method.");
325  delete vprof;
326 
327  return nullptr;
328 }
329 
400  // DB Settings
401  db_display_dim(0,0),
402  db_aspectoverride(kAspect_Off), db_adjustfill(kAdjustFill_Off),
403  db_letterbox_colour(kLetterBoxColour_Black),
404 
405  // Video parameters
406  video_codec_id(kCodec_NONE), db_vdisp_profile(nullptr),
407 
408  // Picture-in-Picture stuff
409  pip_desired_display_size(160,128), pip_display_size(0,0),
410  pip_video_size(0,0),
411  pip_tmp_buf(nullptr), pip_tmp_buf2(nullptr),
412  pip_scaling_context(nullptr),
413 
414  // Video resizing (for ITV)
415  vsz_enabled(false),
416  vsz_desired_display_rect(0,0,0,0), vsz_display_size(0,0),
417  vsz_video_size(0,0),
418  vsz_tmp_buf(nullptr), vsz_scale_context(nullptr),
419 
420  // Deinterlacing
421  m_deinterlacing(false), m_deintfiltername("linearblend"),
422  m_deintFiltMan(nullptr), m_deintFilter(nullptr),
423  m_deinterlaceBeforeOSD(true),
424 
425  // Various state variables
426  errorState(kError_None), framesPlayed(0),
427 
428  // Custom display resolutions
429  display_res(nullptr),
430 
431  // Physical display
432  monitor_sz(640,480), monitor_dim(400,300),
433 
434  // OSD
435  osd_painter(nullptr), osd_image(nullptr),
436  invalid_osd_painter(nullptr),
437 
438  // Visualisation
439  m_visual(nullptr),
440 
441  // 3D TV
442  m_stereo(kStereoscopicModeNone)
443 {
444  memset(&pip_tmp_image, 0, sizeof(pip_tmp_image));
445  db_display_dim = QSize(gCoreContext->GetNumSetting("DisplaySizeWidth", 0),
446  gCoreContext->GetNumSetting("DisplaySizeHeight", 0));
447 
449  gCoreContext->GetNumSetting("AspectOverride", 0);
451  gCoreContext->GetNumSetting("AdjustFill", 0);
453  gCoreContext->GetNumSetting("LetterboxColour", 0);
454 
455  db_vdisp_profile = nullptr;
456 }
457 
463 {
464  if (osd_image)
465  osd_image->DecrRef();
466  delete osd_painter;
467  delete invalid_osd_painter;
468  invalid_osd_painter = nullptr;
469 
471 
473 
474  delete m_deintFilter;
475  delete m_deintFiltMan;
476  delete db_vdisp_profile;
477 
478  ResizeForGui();
479  if (display_res)
481 }
482 
488 bool VideoOutput::Init(const QSize &video_dim_buf,
489  const QSize &video_dim_disp,
490  float aspect, WId winid,
491  const QRect &win_rect, MythCodecID codec_id)
492 {
493  (void)winid;
494 
495  video_codec_id = codec_id;
496  bool wasembedding = window.IsEmbedding();
497  QRect oldrect;
498  if (wasembedding)
499  {
500  oldrect = window.GetEmbeddingRect();
501  StopEmbedding();
502  }
503 
504  bool mainSuccess = window.Init(video_dim_buf, video_dim_disp,
505  aspect, win_rect,
507 
508  if (db_vdisp_profile)
510 
511  if (wasembedding)
512  EmbedInWidget(oldrect);
513 
514  VideoAspectRatioChanged(aspect); // apply aspect ratio and letterbox mode
515 
516  return mainSuccess;
517 }
518 
520 {
522  osd->DisableFade();
523 }
524 
525 QString VideoOutput::GetFilters(void) const
526 {
527  if (db_vdisp_profile)
528  return db_vdisp_profile->GetFilters();
529  return QString();
530 }
531 
532 void VideoOutput::SetVideoFrameRate(float playback_fps)
533 {
534  if (db_vdisp_profile)
535  db_vdisp_profile->SetOutput(playback_fps);
536 }
537 
544 {
545  if (enable && m_deinterlacing)
546  return m_deinterlacing;
547 
548  // if enable and no deinterlacer allocated, attempt allocate one
549  if (enable && (!m_deintFiltMan || !m_deintFilter))
550  return SetupDeinterlace(enable);
551 
552  m_deinterlacing = enable;
553  return m_deinterlacing;
554 }
555 
563 bool VideoOutput::SetupDeinterlace(bool interlaced,
564  const QString& overridefilter)
565 {
566  PIPState pip_state = window.GetPIPState();
567 
568  if (pip_state > kPIPOff && pip_state < kPBPLeft)
569  return false;
570 
571  if (m_deinterlacing == interlaced)
572  {
573  if (!m_deinterlacing)
574  return false;
575  if (overridefilter.isEmpty() || overridefilter == m_deintfiltername)
576  return true;
577  }
578 
579  if (m_deintFiltMan)
580  {
581  delete m_deintFiltMan;
582  m_deintFiltMan = nullptr;
583  }
584  if (m_deintFilter)
585  {
586  delete m_deintFilter;
587  m_deintFilter = nullptr;
588  }
589 
590  m_deinterlacing = interlaced;
591 
592  if (m_deinterlacing)
593  {
594  m_deinterlaceBeforeOSD = true;
595 
596  VideoFrameType itmp = FMT_YV12;
597  VideoFrameType otmp = FMT_YV12;
598 
599  if (db_vdisp_profile)
601  db_vdisp_profile->GetFilteredDeint(overridefilter);
602  else
603  m_deintfiltername = "";
604 
605  m_deintFilter = nullptr;
606  m_deintFiltMan = nullptr;
607 
609  {
610  m_deinterlacing = false;
611  return false;
612  }
613 
615 
616  if (!m_deintfiltername.isEmpty())
617  {
619  {
620  LOG(VB_GENERAL, LOG_ERR,
621  QString("Failed to approve '%1' deinterlacer "
622  "as a software deinterlacer")
623  .arg(m_deintfiltername));
624  m_deintfiltername.clear();
625  }
626  else
627  {
628  int btmp;
629  int threads = db_vdisp_profile ?
631  const QSize video_dim = window.GetVideoDim();
632  int width = video_dim.width();
633  int height = video_dim.height();
635  m_deintfiltername, itmp, otmp,
636  width, height, btmp, threads);
637  window.SetVideoDim(QSize(width, height));
638  }
639  }
640 
641  if (m_deintFilter == nullptr)
642  {
643  LOG(VB_GENERAL, LOG_ERR, LOC +
644  QString("Couldn't load deinterlace filter %1")
645  .arg(m_deintfiltername));
646  m_deinterlacing = false;
647  m_deintfiltername = "";
648  }
649 
650  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Using deinterlace method %1")
651  .arg(m_deintfiltername));
652 
653  if (m_deintfiltername == "bobdeint")
654  m_deinterlaceBeforeOSD = false;
655  }
656 
657  return m_deinterlacing;
658 }
659 
664 {
665  SetupDeinterlace(false);
666  if (db_vdisp_profile)
668 }
669 
674 {
675  SetupDeinterlace(false);
676  SetupDeinterlace(true);
677 }
678 
689 {
690  return (m_deintfiltername.contains("doubleprocess")) && m_deinterlacing;
691 }
699 {
700  // Bob deinterlace requires doubling framerate
701  return ((m_deintfiltername.contains("bobdeint") ||
702  m_deintfiltername.contains("doublerate") ||
703  m_deintfiltername.contains("doubleprocess")) &&
705 }
706 
707 bool VideoOutput::IsBobDeint(void) const
708 {
709  return (m_deinterlacing && m_deintfiltername == "bobdeint");
710 }
711 
717 bool VideoOutput::ApproveDeintFilter(const QString& filtername) const
718 {
719  // Default to not supporting bob deinterlace
720  return (!filtername.contains("bobdeint") &&
721  !filtername.contains("doublerate") &&
722  !filtername.contains("opengl") &&
723  !filtername.contains("vdpau"));
724 }
725 
726 void VideoOutput::GetDeinterlacers(QStringList &deinterlacers)
727 {
728  if (!db_vdisp_profile)
729  return;
730  QString rend = db_vdisp_profile->GetActualVideoRenderer();
731  deinterlacers = VideoDisplayProfile::GetDeinterlacers(rend);
732 }
733 
741 {
743 }
744 
750 bool VideoOutput::InputChanged(const QSize &video_dim_buf,
751  const QSize &video_dim_disp,
752  float aspect,
753  MythCodecID myth_codec_id,
754  void *codec_private,
755  bool &/*aspect_only*/)
756 {
757  window.InputChanged(video_dim_buf, video_dim_disp,
758  aspect, myth_codec_id, codec_private);
759 
760  AVCodecID avCodecId = myth2av_codecid(myth_codec_id);
761  AVCodec *codec = avcodec_find_decoder(avCodecId);
762  QString codecName;
763  if (codec)
764  codecName = codec->name;
765  if (db_vdisp_profile)
767  video_codec_id = myth_codec_id;
768  BestDeint();
769 
770  DiscardFrames(true);
771 
772  return true;
773 }
777 void VideoOutput::ResizeDisplayWindow(const QRect &rect, bool save_visible_rect)
778 {
779  window.ResizeDisplayWindow(rect, save_visible_rect);
780 }
781 
786 void VideoOutput::EmbedInWidget(const QRect &rect)
787 {
788  window.EmbedInWidget(rect);
789 }
790 
797 {
799 }
800 
806 void VideoOutput::DrawSlice(VideoFrame *frame, int x, int y, int w, int h)
807 {
808  (void)frame;
809  (void)x;
810  (void)y;
811  (void)w;
812  (void)h;
813 }
814 
815 void VideoOutput::GetOSDBounds(QRect &total, QRect &visible,
816  float &visible_aspect,
817  float &font_scaling,
818  float themeaspect) const
819 {
820  total = GetTotalOSDBounds();
821  visible = GetVisibleOSDBounds(visible_aspect, font_scaling, themeaspect);
822 }
823 
831  float &visible_aspect, float &font_scaling, float themeaspect) const
832 {
833  if (!hasFullScreenOSD())
834  {
836  visible_aspect, font_scaling, themeaspect);
837  }
838 
839  QRect dvr = window.GetDisplayVisibleRect();
840 
841  // This rounding works for I420 video...
842  QSize dvr2 = QSize(dvr.width() & ~0x3,
843  dvr.height() & ~0x1);
844 
845  float dispPixelAdj = 1.0F;
846  if (dvr2.height() && dvr2.width())
847  dispPixelAdj = (GetDisplayAspect() * dvr2.height()) / dvr2.width();
848 
849  float ova = window.GetOverridenVideoAspect();
850  QRect vr = window.GetVideoRect();
851  float vs = vr.height() ? (float)vr.width() / vr.height() : 1.F;
852  visible_aspect = themeaspect * (ova ? vs / ova : 1.F) * dispPixelAdj;
853 
854  font_scaling = 1.0F;
855  return {QPoint(0,0), dvr2};
856 }
857 
863 {
864  if (!hasFullScreenOSD())
865  return window.GetTotalOSDBounds();
866 
867  QRect dvr = window.GetDisplayVisibleRect();
868  QSize dvr2 = QSize(dvr.width() & ~0x3,
869  dvr.height() & ~0x1);
870 
871  return {QPoint(0,0), dvr2};
872 }
873 
875 {
876  if (!hasFullScreenOSD())
877  return window.GetTotalOSDBounds();
878 
879  QRect dvr = window.GetDisplayVideoRect();
880  return {QPoint(dvr.left() & ~0x1, dvr.top() & ~0x1),
881  QSize(dvr.width() & ~0x1, dvr.height() & ~0x1)};
882 }
883 
885 {
886  return window.IsPreviewEPGAllowed();
887 }
888 
900 {
901  window.MoveResize();
902 }
903 
911 {
912  window.Zoom(direction);
913 }
914 
921 {
923 }
924 
930 {
932 }
933 
942 {
943  window.ToggleAspectOverride(aspectMode);
944 }
945 
954 {
955  window.ToggleAdjustFill(adjustFill);
956 }
957 
959  PictureAttribute attributeType, bool direction)
960 {
961  int curVal = GetPictureAttribute(attributeType);
962  if (curVal < 0)
963  return -1;
964 
965  int newVal = curVal + ((direction) ? +1 : -1);
966 
967  if (kPictureAttribute_Hue == attributeType)
968  newVal = newVal % 100;
969 
970  if ((kPictureAttribute_StudioLevels == attributeType) && newVal > 1)
971  newVal = 1;
972 
973  newVal = min(max(newVal, 0), 100);
974 
975  return SetPictureAttribute(attributeType, newVal);
976 }
977 
986 {
987  return videoColourSpace.SetPictureAttribute(attribute, newValue);
988 }
989 
991 {
992  return videoColourSpace.GetPictureAttribute(attributeType);
993 }
994 
998 QString VideoOutput::GetOSDRenderer(void) const
999 {
1000  return db_vdisp_profile->GetOSDRenderer();
1001 }
1002 
1003 /*
1004  * \brief Determines PIP Window size and Position.
1005  */
1007  PIPLocation location, MythPlayer *pipplayer, bool do_pixel_adj) const
1008 {
1009  return window.GetPIPRect(location, pipplayer, do_pixel_adj);
1010 }
1011 
1019 void VideoOutput::DoPipResize(int pipwidth, int pipheight)
1020 {
1021  QSize vid_size = QSize(pipwidth, pipheight);
1022  if (vid_size == pip_desired_display_size)
1023  return;
1024 
1026 
1027  pip_video_size = vid_size;
1029 
1030  int sz = buffersize(FMT_YV12,
1031  pip_display_size.width(), pip_display_size.height());
1032  pip_tmp_buf = (unsigned char*)av_malloc(sz);
1033  pip_tmp_buf2 = (unsigned char*)av_malloc(sz);
1034 
1035  pip_scaling_context = sws_getCachedContext(pip_scaling_context,
1036  pip_video_size.width(), pip_video_size.height(),
1037  AV_PIX_FMT_YUV420P,
1038  pip_display_size.width(),
1039  pip_display_size.height(),
1040  AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR,
1041  nullptr, nullptr, nullptr);
1042 }
1043 
1051 {
1052  if (pip_tmp_buf)
1053  {
1054  av_freep(&pip_tmp_buf);
1055  }
1056 
1057  if (pip_tmp_buf2)
1058  {
1059  av_freep(&pip_tmp_buf2);
1060  }
1061 
1062  if (pip_scaling_context)
1063  {
1064  sws_freeContext(pip_scaling_context);
1065  pip_scaling_context = nullptr;
1066  }
1067 
1068  pip_video_size = QSize(0,0);
1069  pip_display_size = QSize(0,0);
1070 }
1071 
1072 void VideoOutput::ShowPIPs(VideoFrame *frame, const PIPMap &pipPlayers)
1073 {
1074  PIPMap::const_iterator it = pipPlayers.begin();
1075  for (; it != pipPlayers.end(); ++it)
1076  ShowPIP(frame, it.key(), *it);
1077 }
1078 
1090  MythPlayer *pipplayer,
1091  PIPLocation loc)
1092 {
1093  if (!pipplayer)
1094  return;
1095 
1096  const float video_aspect = window.GetVideoAspect();
1097 // const QRect display_video_rect = window.GetDisplayVideoRect();
1098 // const QRect video_rect = window.GetVideoRect();
1099 // const QRect display_visible_rect = window.GetDisplayVisibleRect();
1100 // const QSize video_disp_dim = window.GetVideoDispDim();
1101 
1102  int pipw, piph;
1103  VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph);
1104  const bool pipActive = pipplayer->IsPIPActive();
1105  const bool pipVisible = pipplayer->IsPIPVisible();
1106  const float pipVideoAspect = pipplayer->GetVideoAspect();
1107 // const QSize pipVideoDim = pipplayer->GetVideoBufferSize();
1108 
1109  // If PiP is not initialized to values we like, silently ignore the frame.
1110  if ((video_aspect <= 0) || (pipVideoAspect <= 0) ||
1111  (frame->height <= 0) || (frame->width <= 0) ||
1112  !pipimage || !pipimage->buf || pipimage->codec != FMT_YV12)
1113  {
1114  pipplayer->ReleaseCurrentFrame(pipimage);
1115  return;
1116  }
1117 
1118  if (!pipVisible)
1119  {
1120  pipplayer->ReleaseCurrentFrame(pipimage);
1121  return;
1122  }
1123 
1124  QRect position = GetPIPRect(loc, pipplayer);
1125 
1126  pip_desired_display_size = position.size();
1127 
1128  // Scale the image if we have to...
1129  if (pipw != pip_desired_display_size.width() ||
1130  piph != pip_desired_display_size.height())
1131  {
1132  DoPipResize(pipw, piph);
1133 
1134  memset(&pip_tmp_image, 0, sizeof(pip_tmp_image));
1135 
1137  {
1138  AVFrame img_in, img_out;
1139  av_image_fill_arrays(
1140  img_out.data, img_out.linesize,
1141  pip_tmp_buf, AV_PIX_FMT_YUV420P,
1142  pip_display_size.width(), pip_display_size.height(),
1143  IMAGE_ALIGN);
1144 
1145  AVPictureFill(&img_in, pipimage);
1146 
1147  sws_scale(pip_scaling_context, img_in.data, img_in.linesize, 0,
1148  piph, img_out.data, img_out.linesize);
1149 
1150  pipw = pip_display_size.width();
1151  piph = pip_display_size.height();
1152 
1153  if (pipActive)
1154  {
1155  AVFrame img_padded;
1156  av_image_fill_arrays(img_padded.data, img_padded.linesize,
1157  pip_tmp_buf2,
1158  AV_PIX_FMT_YUV420P, pipw, piph, IMAGE_ALIGN);
1159 
1160  int color[3] = { 20, 0, 200 }; //deep red YUV format
1161  av_picture_pad((AVPicture*)(&img_padded),
1162  (AVPicture*)(&img_out), piph, pipw,
1163  AV_PIX_FMT_YUV420P, 4, 4, 4, 4, color);
1164 
1165  int offsets[3] = {0, int(img_padded.data[1] - img_padded.data[0]),
1166  int(img_padded.data[2] - img_padded.data[0]) };
1167  init(&pip_tmp_image, FMT_YV12, img_padded.data[0], pipw, piph,
1168  sizeof(int), img_padded.linesize, offsets);
1169  }
1170  else
1171  {
1172  int offsets[3] = {0, int(img_out.data[1] - img_out.data[0]),
1173  int(img_out.data[2] - img_out.data[0]) };
1174  init(&pip_tmp_image, FMT_YV12, img_out.data[0], pipw, piph,
1175  sizeof(int), img_out.linesize, offsets);
1176  }
1177  }
1178  }
1179 
1180  if ((position.left() >= 0) && (position.top() >= 0))
1181  {
1182  int xoff = position.left();
1183  int yoff = position.top();
1184  int xoff2[3] = { xoff, xoff>>1, xoff>>1 };
1185  int yoff2[3] = { yoff, yoff>>1, yoff>>1 };
1186 
1187  int pip_height = pip_tmp_image.height;
1188  int height[3] = { pip_height, pip_height>>1, pip_height>>1 };
1189  int pip_width = pip_tmp_image.width;
1190  int widths[3] = { pip_width, pip_width>>1, pip_width>>1 };
1191 
1192  for (int p = 0; p < 3; p++)
1193  {
1194  for (int h = pipActive ? 0 : 1; h < height[p]; h++)
1195  {
1196  memcpy((frame->buf + frame->offsets[p]) + (h + yoff2[p]) *
1197  frame->pitches[p] + xoff2[p],
1198  (pip_tmp_image.buf + pip_tmp_image.offsets[p]) + h *
1199  pip_tmp_image.pitches[p], widths[p]);
1200  }
1201  }
1202  }
1203 
1204  // we're done with the frame, release it
1205  pipplayer->ReleaseCurrentFrame(pipimage);
1206 }
1207 
1214 void VideoOutput::DoVideoResize(const QSize &inDim, const QSize &outDim)
1215 {
1216  if ((inDim == vsz_video_size) && (outDim == vsz_display_size))
1217  return;
1218 
1220 
1221  vsz_enabled = true;
1222  vsz_video_size = inDim;
1223  vsz_display_size = outDim;
1224 
1225  int sz = vsz_display_size.height() * vsz_display_size.width() * 3 / 2;
1226  vsz_tmp_buf = new unsigned char[sz];
1227 
1228  vsz_scale_context = sws_getCachedContext(vsz_scale_context,
1229  vsz_video_size.width(), vsz_video_size.height(),
1230  AV_PIX_FMT_YUV420P,
1231  vsz_display_size.width(),
1232  vsz_display_size.height(),
1233  AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR,
1234  nullptr, nullptr, nullptr);
1235 }
1236 
1238 {
1239  if (vsz_desired_display_rect.isNull() || frame->codec != FMT_YV12)
1240  return;
1241 
1242  QRect resize = vsz_desired_display_rect;
1243  QSize frameDim(frame->width, frame->height);
1244 
1245  // if resize is outside existing frame, abort
1246  bool abort =
1247  (resize.right() > frame->width || resize.bottom() > frame->height ||
1248  resize.width() > frame->width || resize.height() > frame->height);
1249  // if resize == existing frame, no need to carry on
1250  abort |= !resize.left() && !resize.top() && (resize.size() == frameDim);
1251 
1252  if (abort)
1253  {
1255  vsz_desired_display_rect = QRect();
1256  return;
1257  }
1258 
1259  DoVideoResize(frameDim, resize.size());
1260  if (!vsz_tmp_buf)
1261  {
1263  vsz_desired_display_rect = QRect();
1264  return;
1265  }
1266 
1268  {
1269  AVFrame img_in, img_out;
1270 
1271  av_image_fill_arrays(img_out.data, img_out.linesize,
1272  vsz_tmp_buf, AV_PIX_FMT_YUV420P,
1273  resize.width(), resize.height(),IMAGE_ALIGN);
1274  av_image_fill_arrays(img_in.data, img_in.linesize,
1275  frame->buf, AV_PIX_FMT_YUV420P,
1276  frame->width, frame->height,IMAGE_ALIGN);
1277  img_in.data[0] = frame->buf + frame->offsets[0];
1278  img_in.data[1] = frame->buf + frame->offsets[1];
1279  img_in.data[2] = frame->buf + frame->offsets[2];
1280  img_in.linesize[0] = frame->pitches[0];
1281  img_in.linesize[1] = frame->pitches[1];
1282  img_in.linesize[2] = frame->pitches[2];
1283  sws_scale(vsz_scale_context, img_in.data, img_in.linesize, 0,
1284  frame->height, img_out.data, img_out.linesize);
1285  }
1286 
1287  // Blanking the unused area can appear better but it costs CPU cycles
1288  //clear(frame);
1289 
1290  int xoff = resize.left();
1291  int yoff = resize.top();
1292  int resw = resize.width();
1293  int vidw = frame->pitches[0];
1294 
1295  unsigned char *yptr = frame->buf + frame->offsets[0];
1296  unsigned char *videoyptr = vsz_tmp_buf;
1297 
1298  // Copy Y (intensity values)
1299  yptr += yoff * vidw + xoff;
1300  for (int i = 0; i < resize.height(); i++)
1301  {
1302  memcpy(yptr, videoyptr, resw);
1303  yptr += vidw;
1304  videoyptr += resw;
1305  }
1306 
1307  // Copy U & V (half plane chroma values)
1308  xoff /= 2;
1309  yoff /= 2;
1310 
1311  unsigned char *uptr = frame->buf + frame->offsets[1];
1312  unsigned char *vptr = frame->buf + frame->offsets[2];
1313  vidw = frame->pitches[1];
1314  uptr += yoff * vidw + xoff;
1315  vptr += yoff * vidw + xoff;
1316 
1317  unsigned char *videouptr = vsz_tmp_buf + resw * resize.height();
1318  unsigned char *videovptr = vsz_tmp_buf + (resw * resize.height() * 5) / 4;
1319  resw /= 2;
1320  for (int i = 0; i < resize.height() / 2; i ++)
1321  {
1322  memcpy(uptr, videouptr, resw);
1323  uptr += vidw;
1324  videouptr += resw;
1325  memcpy(vptr, videovptr, resw);
1326  vptr += vidw;
1327  videovptr += resw;
1328  }
1329 }
1330 
1332 {
1333  return window.GetAspectOverride();
1334 }
1335 
1337 {
1338  return window.GetAdjustFill();
1339 }
1340 
1342 {
1343  return window.GetDisplayAspect();
1344 }
1345 
1347 {
1348  return window.IsVideoScalingAllowed();
1349 }
1350 
1352 {
1353  if (vsz_tmp_buf)
1354  {
1355  delete [] vsz_tmp_buf;
1356  vsz_tmp_buf = nullptr;
1357  }
1358 
1359  if (vsz_scale_context)
1360  {
1361  sws_freeContext(vsz_scale_context);
1362  vsz_scale_context = nullptr;
1363  }
1364 
1365  vsz_video_size = QSize(0,0);
1366  vsz_display_size = QSize(0,0);
1367  vsz_enabled = false;
1368 }
1369 
1371 {
1372  // used by render devices to ignore frame rendering
1373  if (frame)
1374  frame->dummy = 1;
1375  // will only clear frame in main memory
1376  clear(frame);
1377 }
1378 
1379 void VideoOutput::SetVideoResize(const QRect &videoRect)
1380 {
1381  if (!videoRect.isValid() ||
1382  videoRect.width() < 1 || videoRect.height() < 1)
1383  {
1385  vsz_desired_display_rect = QRect();
1386  }
1387  else
1388  {
1389  vsz_enabled = true;
1390  vsz_desired_display_rect = videoRect;
1391  }
1392 }
1393 
1398 {
1400 }
1401 
1402 #ifndef MMX
1403 #define THREADED_OSD_RENDER 1
1404 #endif
1405 
1406 #if THREADED_OSD_RENDER
1407 class OsdRender : public QRunnable
1408 {
1409  public:
1410  OsdRender(VideoFrame *frame, MythImage *osd_image, const QSize &dim, const QRect &vis) :
1411  m_frame(frame), m_osd_image(osd_image), m_video_dim(dim), m_vis(vis)
1412  { }
1413 
1414  void run() override // QRunnable
1415  {
1416  switch (m_frame->codec)
1417  {
1418  case FMT_YV12: yv12(); break;
1419  case FMT_AI44: i44(true); break;
1420  case FMT_IA44: i44(false); break;
1421  default: break;
1422  }
1423  }
1424 
1425  private:
1426  inline void yv12()
1427  {
1428 #define ROUNDUP( _x,_z) ((_x) + ((-(_x)) & ((_z) - 1)) )
1429 #define ROUNDDN( _x,_z) ((_x) & ~((_z) - 1))
1430  int left = m_vis.left();
1431  left = ROUNDUP(left, ALIGN_C);
1432  left = std::min(left, m_osd_image->width());
1433 
1434  int right = m_vis.left() + m_vis.width();
1435  right = ROUNDUP(right, ALIGN_C);
1436  right = std::min(right, m_osd_image->width());
1437 
1438  int top = m_vis.top();
1439  top = ROUNDDN(top, ALIGN_C);
1440 
1441  int bottom = m_vis.top() + m_vis.height();
1442  bottom = ROUNDDN(bottom, ALIGN_C);
1443 
1444  c_yuv888_to_yv12(m_frame, m_osd_image, left, top, right, bottom);
1445  }
1446 
1447  inline void i44(bool ifirst)
1448  {
1449  int left = std::min(m_vis.left(), m_osd_image->width());
1450  int top = std::min(m_vis.top(), m_osd_image->height());
1451  int right = std::min(left + m_vis.width(), m_osd_image->width());
1452  int bottom = std::min(top + m_vis.height(), m_osd_image->height());
1453 
1454  memset(m_frame->buf, 0, m_video_dim.width() * m_video_dim.height());
1455  yuv888_to_i44(m_frame->buf, m_osd_image, m_video_dim,
1456  left, top, right, bottom, ifirst);
1457  }
1458 
1459  private:
1460  VideoFrame * const m_frame;
1461  MythImage * const m_osd_image;
1462  QSize const m_video_dim;
1463  QRect const m_vis;
1464 };
1465 #endif
1466 
1478 {
1479  if (!osd || !frame)
1480  return false;
1481 
1482  if (vsz_enabled)
1483  ResizeVideo(frame);
1484 
1485  if (!osd_painter)
1486  {
1487  osd_painter = new MythYUVAPainter();
1488  if (!osd_painter)
1489  return false;
1490  }
1491 
1492  QSize osd_size = GetTotalOSDBounds().size();
1493  if (osd_image && (osd_image->size() != osd_size))
1494  {
1495  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("OSD size changed."));
1496  osd_image->DecrRef();
1497  osd_image = nullptr;
1498  }
1499 
1500  if (!osd_image)
1501  {
1503  if (osd_image)
1504  {
1505  QImage blank = QImage(osd_size,
1506  QImage::Format_ARGB32_Premultiplied);
1507  osd_image->Assign(blank);
1510  QRegion(QRect(QPoint(0,0), osd_size)));
1511  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Created YV12 OSD."));
1512  }
1513  else
1514  return false;
1515  }
1516 
1517  if (m_visual)
1518  {
1519  LOG(VB_GENERAL, LOG_ERR, LOC + "Visualiser not supported here");
1520  // Clear the audio buffer
1521  m_visual->Draw(QRect(), nullptr, nullptr);
1522  }
1523 
1524  switch (frame->codec)
1525  {
1526  case FMT_YV12:
1527  case FMT_AI44:
1528  case FMT_IA44:
1529  break;
1530  default:
1531  LOG(VB_GENERAL, LOG_ERR, LOC +
1532  "Display OSD: Frame format not supported.");
1533  return false;
1534  }
1535 
1536  QRegion dirty = QRegion();
1537  QRegion visible = osd->Draw(osd_painter, osd_image, osd_size, dirty,
1538  frame->codec == FMT_YV12 ? ALIGN_X_MMX : 0,
1539  frame->codec == FMT_YV12 ? ALIGN_C : 0);
1540  bool changed = !dirty.isEmpty();
1541  bool show = !visible.isEmpty();
1542 
1543  if (!show)
1544  return show;
1545 
1546  if (!changed && frame->codec != FMT_YV12)
1547  return show;
1548 
1549  QSize video_dim = window.GetVideoDim();
1550 
1551 #if THREADED_OSD_RENDER
1552  static MThreadPool s_pool("OsdRender");
1553 
1554  // Split visible region for greater concurrency
1555  QRect r = osd_image->rect();
1556  QPoint c = r.center();
1557  QVector<QRect> vis;
1558 #if QT_VERSION < QT_VERSION_CHECK(5, 8, 0)
1559  vis += visible.intersected(QRect(r.topLeft(),c)).rects();
1560  vis += visible.intersected(QRect(c,r.bottomRight())).rects();
1561  vis += visible.intersected(QRect(r.bottomLeft(),c).normalized()).rects();
1562  vis += visible.intersected(QRect(c,r.topRight()).normalized()).rects();
1563 #else
1564  for (const QRect &tmp : visible.intersected(QRect(r.topLeft(),c)))
1565  vis += tmp;
1566  for (const QRect &tmp : visible.intersected(QRect(c,r.bottomRight())))
1567  vis += tmp;
1568  for (const QRect &tmp : visible.intersected(QRect(r.bottomLeft(),c).normalized()))
1569  vis += tmp;
1570  for (const QRect &tmp : visible.intersected(QRect(c,r.topRight()).normalized()))
1571  vis += tmp;
1572 #endif
1573  for (int i = 0; i < vis.size(); i++)
1574  {
1575  OsdRender *job = new OsdRender(frame, osd_image, video_dim, vis[i]);
1576  job->setAutoDelete(true);
1577  s_pool.start(job, "OsdRender");
1578  }
1579  s_pool.waitForDone();
1580 #else
1581 #if QT_VERSION < QT_VERSION_CHECK(5, 8, 0)
1582  QVector<QRect> vis = visible.rects();
1583  for (int i = 0; i < vis.size(); i++)
1584  {
1585  const QRect& r2 = vis[i];
1586 #else
1587  for (const QRect& r2 : visible)
1588  {
1589 #endif
1590  int left = min(r2.left(), osd_image->width());
1591  int top = min(r2.top(), osd_image->height());
1592  int right = min(left + r2.width(), osd_image->width());
1593  int bottom = min(top + r2.height(), osd_image->height());
1594 
1595  if (FMT_YV12 == frame->codec)
1596  {
1597  yuv888_to_yv12(frame, osd_image, left, top, right, bottom);
1598  }
1599  else if (FMT_AI44 == frame->codec)
1600  {
1601  memset(frame->buf, 0, video_dim.width() * video_dim.height());
1602  yuv888_to_i44(frame->buf, osd_image, video_dim,
1603  left, top, right, bottom, true);
1604  }
1605  else if (FMT_IA44 == frame->codec)
1606  {
1607  memset(frame->buf, 0, video_dim.width() * video_dim.height());
1608  yuv888_to_i44(frame->buf, osd_image, video_dim,
1609  left, top, right, bottom, false);
1610  }
1611  }
1612 #endif
1613  return show;
1614 }
1615 
1617  const QString &name)
1618 {
1619  if (!enable)
1620  {
1622  return false;
1623  }
1624  return SetupVisualisation(audio, nullptr, name);
1625 }
1626 
1628 {
1629  return VideoVisual::CanVisualise(audio, render);
1630 }
1631 
1633  const QString &name)
1634 {
1636  m_visual = VideoVisual::Create(name, audio, render);
1637  return m_visual;
1638 }
1639 
1641 {
1642  if (m_visual)
1643  return m_visual->Name();
1644  return QString("");
1645 }
1646 
1648 {
1649  return QStringList();
1650 }
1651 
1653 {
1654  delete m_visual;
1655  m_visual = nullptr;
1656 }
1657 
1667 {
1668  if (to == nullptr || from == nullptr)
1669  return;
1670 
1671  to->frameNumber = from->frameNumber;
1672  to->disp_timecode = from->disp_timecode;
1673 
1674  copy(to, from);
1675 }
1676 
1677 QRect VideoOutput::GetImageRect(const QRect &rect, QRect *display)
1678 {
1679  float hscale, tmp;
1680  tmp = 0.0;
1681  QRect visible_osd = GetVisibleOSDBounds(tmp, tmp, tmp);
1682  QSize video_size = window.GetVideoDispDim();
1683  int image_height = video_size.height();
1684  int image_width = (image_height > 720) ? 1920 :
1685  (image_height > 576) ? 1280 : 720;
1686  float image_aspect = (float)image_width / (float)image_height;
1687  float pixel_aspect = (float)video_size.width() /
1688  (float)video_size.height();
1689 
1690  QRect rect1 = rect;
1691  if (display && display->isValid())
1692  {
1693  QMatrix m0;
1694  m0.scale((float)image_width / (float)display->width(),
1695  (float)image_height / (float)display->height());
1696  rect1 = m0.mapRect(rect1);
1697  rect1.translate(display->left(), display->top());
1698  }
1699  QRect result = rect1;
1700 
1701  if (hasFullScreenOSD())
1702  {
1703  QRect dvr_rec = window.GetDisplayVideoRect();
1704  QRect vid_rec = window.GetVideoRect();
1705 
1706  hscale = image_aspect / pixel_aspect;
1707  if (hscale < 0.99F || hscale > 1.01F)
1708  {
1709  vid_rec.setLeft(lroundf((float)vid_rec.left() * hscale));
1710  vid_rec.setWidth(lroundf((float)vid_rec.width() * hscale));
1711  }
1712 
1713  float vscale = (float)dvr_rec.width() / (float)image_width;
1714  hscale = (float)dvr_rec.height() / (float)image_height;
1715  QMatrix m1;
1716  m1.translate(dvr_rec.left(), dvr_rec.top());
1717  m1.scale(vscale, hscale);
1718 
1719  vscale = (float)image_width / (float)vid_rec.width();
1720  hscale = (float)image_height / (float)vid_rec.height();
1721  QMatrix m2;
1722  m2.scale(vscale, hscale);
1723  m2.translate(-vid_rec.left(), -vid_rec.top());
1724 
1725  result = m2.mapRect(result);
1726  result = m1.mapRect(result);
1727  return result;
1728  }
1729 
1730  hscale = pixel_aspect / image_aspect;
1731  if (hscale < 0.99F || hscale > 1.01F)
1732  {
1733  result.setLeft(lroundf((float)rect1.left() * hscale));
1734  result.setWidth(lroundf((float)rect1.width() * hscale));
1735  }
1736 
1737  result.translate(-visible_osd.left(), -visible_osd.top());
1738  return result;
1739 }
1740 
1748 {
1749  static const float safeMargin = 0.05F;
1750  float dummy;
1751  QRect result = GetVisibleOSDBounds(dummy, dummy, 1.0F);
1752  int safex = (int)((float)result.width() * safeMargin);
1753  int safey = (int)((float)result.height() * safeMargin);
1754  return {result.left() + safex, result.top() + safey,
1755  result.width() - (2 * safex), result.height() - (2 * safey)};
1756 }
1757 
1759 {
1760  window.SetPIPState(setting);
1761 }
1762 
1763 
1764 static QString to_comma_list(const QStringList &list)
1765 {
1766  QString ret = "";
1767  for (QStringList::const_iterator it = list.begin(); it != list.end(); ++it)
1768  ret += *it + ",";
1769 
1770  if (ret.length())
1771  return ret.left(ret.length()-1);
1772 
1773  return "";
1774 }
1775 
1777 {
1778  return window.IsEmbedding();
1779 }
1780 
1782 {
1783  window.SetNeedRepaint(true);
1784 }
1785 
1792 {
1793  if (display_res)
1795 }
1796 
1809 {
1810  if (!display_res)
1811  return;
1812 
1813  if (!width || !height)
1814  {
1815  width = window.GetVideoDispDim().width();
1816  height = window.GetVideoDispDim().height();
1817  if (!width || !height)
1818  return;
1819  }
1820 
1821 #if 0
1822  // width and height should already be the properly cropped
1823  // versions, and therefore height should not need this manual
1824  // truncation. Delete this code if no problems crop up.
1825  if ((width == 1920 || width == 1440) && height == 1088)
1826  height = 1080; // ATSC 1920x1080
1827 #endif
1828 
1829  float rate = db_vdisp_profile ? db_vdisp_profile->GetOutput() : 0.0F;
1830  if (display_res && display_res->SwitchToVideo(width, height, rate))
1831  {
1832  // Switching to custom display resolution succeeded
1833  // Make a note of the new size
1837 
1838  bool fullscreen = !window.UsingGuiSize();
1839 
1840  // if width && height are zero users expect fullscreen playback
1841  if (!fullscreen)
1842  {
1843  int gui_width = 0, gui_height = 0;
1844  gCoreContext->GetResolutionSetting("Gui", gui_width, gui_height);
1845  fullscreen |= (0 == gui_width && 0 == gui_height);
1846  }
1847 
1848  if (fullscreen)
1849  {
1850  QSize sz(display_res->GetWidth(), display_res->GetHeight());
1851  const QRect display_visible_rect =
1852  QRect(GetMythMainWindow()->geometry().topLeft(), sz);
1853  window.SetDisplayVisibleRect(display_visible_rect);
1854  MoveResize();
1855  // Resize X window to fill new resolution
1856  MoveResizeWindow(display_visible_rect);
1857  }
1858  }
1859 }
1860 
1865 void VideoOutput::InitDisplayMeasurements(uint width, uint height, bool resize)
1866 {
1868  QString source = "Actual";
1869 
1870  // The very first Resize needs to be the maximum possible
1871  // desired res, because X will mask off anything outside
1872  // the initial dimensions
1873  QSize sz1 = disp.m_res;
1874  QSize sz2 = window.GetScreenGeometry().size();
1875  QSize max_size = sz1.expandedTo(sz2);
1876 
1877  if (window.UsingGuiSize())
1878  max_size = GetMythMainWindow()->geometry().size();
1879 
1880  if (display_res)
1881  {
1882  max_size.setWidth(display_res->GetMaxWidth());
1883  max_size.setHeight(display_res->GetMaxHeight());
1884  }
1885 
1886  if (resize)
1887  {
1888  MoveResizeWindow(QRect(GetMythMainWindow()->geometry().x(),
1889  GetMythMainWindow()->geometry().y(),
1890  max_size.width(), max_size.height()));
1891  }
1892 
1893  // get the physical dimensions (in mm) of the display. If using
1894  // DisplayRes, this will be overridden when we call ResizeForVideo
1895  if (db_display_dim.isEmpty())
1896  {
1897  window.SetDisplayDim(disp.m_size);
1898  }
1899  else
1900  {
1902  source = "Database";
1903  }
1904 
1905  // Set the display mode if required
1906  if (display_res)
1907  ResizeForVideo(width, height);
1908 
1909  // Determine window and screen dimensions in pixels
1910  QSize screen_size = disp.m_res;
1911  QSize window_size = window.GetDisplayVisibleRect().size();
1912 
1913  float pixel_aspect = (float)screen_size.width() /
1914  (float)screen_size.height();
1915 
1916  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1917  QString("Pixel dimensions: Screen %1x%2, window %3x%4")
1918  .arg(screen_size.width()).arg(screen_size.height())
1919  .arg(window_size.width()).arg(window_size.height()));
1920 
1921  // Check the display dimensions
1922  QSize disp_dim = window.GetDisplayDim();
1923  float disp_aspect;
1924 
1925  // If we are using Xinerama the display dimensions cannot be trusted.
1926  // We need to use the Xinerama monitor aspect ratio from the DB to set
1927  // the physical screen width. This assumes the height is correct, which
1928  // is more or less true in the typical side-by-side monitor setup.
1929  if (window.UsingXinerama())
1930  {
1931  source = "Xinerama";
1932  disp_aspect = gCoreContext->GetFloatSettingOnHost(
1933  "XineramaMonitorAspectRatio",
1934  gCoreContext->GetHostName(), pixel_aspect);
1935  if (disp_dim.height() <= 0)
1936  disp_dim.setHeight(300);
1937  disp_dim.setWidth(lroundf(disp_dim.height() * disp_aspect));
1938  }
1939 
1940  if (disp_dim.isEmpty())
1941  {
1942  source = "Guessed!";
1943  LOG(VB_GENERAL, LOG_WARNING, LOC + "Physical size of display unknown."
1944  "\n\t\t\tAssuming 17\" monitor with square pixels.");
1945  disp_dim = QSize(lroundf(300 * pixel_aspect), 300);
1946  }
1947 
1948  disp_aspect = (float) disp_dim.width() / (float) disp_dim.height();
1949  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1950  QString("%1 display dimensions: %2x%3 mm Aspect: %4")
1951  .arg(source).arg(disp_dim.width()).arg(disp_dim.height())
1952  .arg(disp_aspect));
1953 
1954  // Save the unscaled size and dimensions for window resizing
1955  monitor_sz = screen_size;
1956  monitor_dim = disp_dim;
1957 
1958  // We must now scale the display measurements to our window size and save
1959  // them. If we are running fullscreen this is a no-op.
1960  disp_dim = QSize((disp_dim.width() * window_size.width()) /
1961  screen_size.width(),
1962  (disp_dim.height() * window_size.height()) /
1963  screen_size.height());
1964  disp_aspect = (float) disp_dim.width() / (float) disp_dim.height();
1965  window.SetDisplayDim(disp_dim);
1966  window.SetDisplayAspect(disp_aspect);
1967 
1968  // If we are using XRandR, use the aspect ratio from it
1969  if (display_res)
1971 
1972  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1973  QString("Estimated window dimensions: %1x%2 mm Aspect: %3")
1974  .arg(window.GetDisplayDim().width())
1975  .arg(window.GetDisplayDim().height())
1976  .arg(window.GetDisplayAspect()));
1977 }
1978 
1979 int VideoOutput::CalcHueBase(const QString &adaptor_name)
1980 {
1981  int hue_adj = 50;
1982 
1983  // XVideo adjustments
1984  if ((adaptor_name == "ATI Radeon Video Overlay") ||
1985  (adaptor_name == "XA G3D Textured Video") || /* ATI in VMWare*/
1986  (adaptor_name == "Radeon Textured Video") || /* ATI */
1987  (adaptor_name == "AMD Radeon AVIVO Video") || /* ATI */
1988  (adaptor_name == "XV_SWOV" /* VIA 10K & 12K */) ||
1989  (adaptor_name == "Savage Streams Engine" /* S3 Prosavage DDR-K */) ||
1990  (adaptor_name == "SIS 300/315/330 series Video Overlay") ||
1991  adaptor_name.toLower().contains("xvba") /* VAAPI */ ||
1992  adaptor_name.toLower().startsWith("intel i965 driver"))
1993  {
1994  hue_adj = 50;
1995  }
1996  else if (adaptor_name.startsWith("NV17")) /* nVidia */
1997  {
1998  hue_adj = 0;
1999  }
2000  else
2001  {
2002  LOG(VB_GENERAL, LOG_INFO, LOC +
2003  QString("CalcHueBase(%1): Unknown adaptor, hue may be wrong.")
2004  .arg(adaptor_name));
2005  LOG(VB_GENERAL, LOG_INFO, LOC +
2006  "Please open a ticket if you need to adjust the hue.");
2007  }
2008 
2009  return hue_adj;
2010 }
2011 
2013 {
2014  // TODO: support cropping in the horizontal dimension
2015  if (!frame)
2016  return;
2017  if (FMT_YV12 != frame->codec)
2018  return;
2019  if (frame->pitches[1] != frame->pitches[2])
2020  return;
2021  int crop = window.GetVideoDim().height() -
2022  window.GetVideoDispDim().height();
2023  if (crop <= 0 || crop >= 16)
2024  return; // something may be amiss, so don't crop
2025 
2026  uint64_t *ybuf = (uint64_t*) (frame->buf + frame->offsets[0]);
2027  uint64_t *ubuf = (uint64_t*) (frame->buf + frame->offsets[1]);
2028  uint64_t *vbuf = (uint64_t*) (frame->buf + frame->offsets[2]);
2029  const uint64_t Y_black = 0x0000000000000000LL; // 8 bytes
2030  const uint64_t UV_black = 0x8080808080808080LL; // 8 bytes
2031  int y;
2032  int sz = (frame->pitches[0] * frame->height) >> 3; // div 8 bytes
2033  // Luma bottom
2034  y = ((frame->height - crop) >> 4) * frame->pitches[0] << 1;
2035  y = y + (sz - y) * (16 - crop) / 16;
2036  for (; y < sz; y++)
2037  {
2038  ybuf[y] = Y_black;
2039  }
2040  // Chroma bottom
2041  sz = (frame->pitches[1] * (frame->height >> 1)) >> 3; // div 8 bytes
2042  y = ((frame->height - crop) >> 4) * frame->pitches[1];
2043  y = y + (sz - y) * (16 - crop) / 16;
2044  for (; y < sz; y++)
2045  {
2046  ubuf[y] = UV_black;
2047  vbuf[y] = UV_black;
2048  }
2049 }
virtual void ResizeForVideo(uint width=0, uint height=0)
Sets display parameters based on video resolution.
int pitches[3]
Y, U, & V pitches.
Definition: mythframe.h:63
virtual int SetPictureAttribute(PictureAttribute, int newValue)
Sets a specified picture attribute.
MythPainter * invalid_osd_painter
Definition: videooutbase.h:374
QString m_deintfiltername
Definition: videooutbase.h:351
void ToggleAspectOverride(AspectOverrideMode aspectMode=kAspect_Toggle)
Enforce different aspect ration than detected, then calls VideoAspectRatioChanged(float) to apply the...
float GetVideoAspect(void) const
Definition: mythplayer.h:175
unsigned char * pip_tmp_buf2
Definition: videooutbase.h:337
void SetDisplayAspect(float displayAspect)
A dummy video class that uses VDPAU to decode video frames.
virtual bool CanVisualise(AudioPlayer *audio, MythRender *render)
int GetMaxHeight(void) const
Returns maximum height in pixels supported by display.
Definition: DisplayRes.h:130
virtual void ResizeForGui(void)
If we are using DisplayRes support, return the screen size and refresh rate to those used for the GUI...
QMap< MythPlayer *, PIPLocation > PIPMap
Definition: videooutbase.h:37
bool UsingXinerama(void) const
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
static bool isCodecDeinterlacer(const QString &decodername)
virtual bool DisplayOSD(VideoFrame *frame, OSD *osd)
If the OSD has changed, this will convert the OSD buffer to the OSDSurface's color format.
QRect GetTotalOSDBounds(void) const
Returns total OSD bounds.
void DestroyVisualisation(void)
QString GetFilters(void) const
double GetAspectRatio(void) const
Returns current screen aspect ratio.
Definition: DisplayRes.h:119
LetterBoxColour db_letterbox_colour
Definition: videooutbase.h:325
virtual bool IsBobDeint(void) const
MythImage * osd_image
Definition: videooutbase.h:372
virtual QString Name(void)=0
static int crop(VideoFilter *f, VideoFrame *frame, int field)
Definition: filter_crop.c:41
bool m_deinterlacing
Definition: videooutbase.h:350
virtual bool NeedsDoubleFramerate(void) const
Should Prepare() and Show() be called twice for every ProcessFrame().
virtual void DiscardFrames(bool kf)
Releases all frames not being actively displayed from any queue onto the queue of frames ready for de...
Definition: videooutbase.h:227
virtual void SetVideoFrameRate(float)
MythCodecID
Definition: mythcodecid.h:10
static bool CanVisualise(AudioPlayer *audio, MythRender *render)
Definition: videovisual.cpp:7
VideoColourSpace videoColourSpace
Definition: videooutbase.h:322
VideoOutput()
This constructor for VideoOutput must be followed by an Init(int,int,float,WId,int,...
#define ROUNDUP(_x, _z)
int DecrRef(void) override
Decrements reference count and deletes on 0.
Definition: mythimage.cpp:55
AdjustFillMode GetAdjustFill(void) const
Returns current adjust fill mode.
struct AVFrame AVFrame
static void GetRenderOptions(render_opts &opts, QStringList &cpudeints)
float GetOutput(void) const
QRect GetPIPRect(PIPLocation location, MythPlayer *pipplayer=nullptr, bool do_pixel_adj=true) const
QString GetFilteredDeint(const QString &override)
virtual bool IsExtraProcessingRequired(void) const
Should Prepare() and Show() and ProcessFrame be called twice for every Frameloop().
QRect GetVideoRect(void) const
static VideoVisual * Create(const QString &name, AudioPlayer *audio, MythRender *render)
Definition: videovisual.cpp:28
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.
void c_yuv888_to_yv12(VideoFrame *frame, MythImage *osd_image, int left, int top, int right, int bottom)
Definition: util-osd.cpp:236
virtual float GetDisplayAspect(void) const
Returns current display aspect ratio.
double GetFloatSettingOnHost(const QString &key, const QString &host, double defaultval=0.0)
QRect GetTotalOSDBounds(void) const
Returns total OSD bounds.
void GetResolutionSetting(const QString &type, int &width, int &height, double &forced_aspect, double &refresh_rate, int index=-1)
VideoFrame * GetCurrentFrame(int &w, int &h)
QString GetFallbackDeinterlacer(void) const
virtual void SaveBottomLine(void)
Save current Manual Zoom settings as BottomLine adjustment.
virtual void SetPIPState(PIPState setting)
static QString to_comma_list(const QStringList &list)
void CropToDisplay(VideoFrame *frame)
QSize db_display_dim
Screen dimensions in millimeters from DB.
Definition: videooutbase.h:321
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
AspectOverrideMode GetAspectOverride(void) const
Returns current aspect override mode.
QRect GetMHEGBounds(void)
virtual void StopEmbedding(void)
Tells video output to stop embedding video in an existing window.
QSize pip_desired_display_size
Definition: videooutbase.h:333
enum FrameType_ VideoFrameType
QRect GetSafeRect(void)
Returns a QRect describing an area of the screen on which it is 'safe' to render the On Screen Displa...
virtual QString GetOSDRenderer(void) const
\ brief return OSD renderer type for this videoOutput
void waitForDone(void)
struct SwsContext * pip_scaling_context
Definition: videooutbase.h:338
static void Unlock(void)
Release any access restrictions.
Definition: DisplayRes.cpp:38
virtual void ToggleAspectOverride(AspectOverrideMode aspectMode=kAspect_Toggle)
Enforce different aspect ration than detected, then calls VideoAspectRatioChanged(float) to apply the...
static QStringList GetAllowedRenderers(MythCodecID myth_codec_id, const QSize &video_dim)
Generate a list of supported OpenGL profiles.
long long copy(QFile &dst, QFile &src, uint block_size)
Copies src file to dst file.
#define LOC
void SetOutput(float framerate)
VideoVisual * m_visual
Definition: videooutbase.h:377
VideoDisplayProfile * db_vdisp_profile
Definition: videooutbase.h:330
static guint32 * tmp
Definition: goom_core.c:35
void SetPIPState(PIPState setting)
unsigned char * pip_tmp_buf
Definition: videooutbase.h:336
void SetVideoScalingAllowed(bool change)
Disable or enable underscan/overscan.
void SetVideoDim(QSize dim)
QSize pip_display_size
Definition: videooutbase.h:334
bool AllowPreviewEPG(void) const
float GetDisplayAspect(void) const
Returns current display aspect ratio.
unsigned char r
Definition: ParseText.cpp:329
virtual void EmbedInWidget(const QRect &rect)
Tells video output to embed video in an existing window.
QSize vsz_video_size
Definition: videooutbase.h:345
virtual void ClearDummyFrame(VideoFrame *frame)
Clears the frame to black.
static QStringList GetDeinterlacers(const QString &video_renderer)
FilterChain * LoadFilters(const QString &filters, VideoFrameType &inpixfmt, VideoFrameType &outpixfmt, int &width, int &height, int &bufsize, int max_threads=1)
QSize m_res
Definition: mythdisplay.h:20
AdjustFillMode db_adjustfill
Definition: videooutbase.h:324
virtual void ShowPIPs(VideoFrame *frame, const PIPMap &pipPlayers)
int offsets[3]
Y, U, & V offsets.
Definition: mythframe.h:64
This class serves as the base class for all video output methods.
Definition: videooutbase.h:46
static QStringList GetAllowedRenderers(MythCodecID myth_codec_id)
void ExposeEvent(void)
Tells video output that a full repaint is needed.
VideoFrame pip_tmp_image
Definition: videooutbase.h:339
AspectOverrideMode
Definition: videoouttypes.h:46
static QStringList GetAllowedRenderers(MythCodecID myth_codec_id, const QSize &video_dim)
QString GetFilters(void) const
static void CopyFrame(VideoFrame *to, const VideoFrame *from)
Copies frame data from one VideoFrame to another.
bool UsingGuiSize(void) const
int GetWidth(void) const
Returns current screen width in pixels.
Definition: DisplayRes.h:101
static QString GetBestVideoRenderer(const QStringList &renderers)
static void GetRenderOptions(render_opts &opts)
int AVPictureFill(AVFrame *pic, const VideoFrame *frame, AVPixelFormat fmt)
AVPictureFill Initialise AVFrame pic with content from VideoFrame frame.
Definition: mythavutil.cpp:65
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
bool IsPreviewEPGAllowed(void) const
static void GetRenderOptions(render_opts &opts)
static void show(uint8_t *buf, int length)
Definition: ringbuffer.c:335
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:830
void Clear(QPaintDevice *device, const QRegion &region) override
void ReleaseCurrentFrame(VideoFrame *frame)
void SaveBottomLine(void)
#define ALIGN_X_MMX
Definition: util-osd.h:10
static void GetRenderOptions(render_opts &opts)
int height
Definition: mythframe.h:42
QRect GetScreenGeometry(void) const
MythCodecID video_codec_id
Definition: videooutbase.h:329
QRect GetEmbeddingRect(void) const
static void GetRenderOptions(render_opts &opts)
QRegion Draw(MythPainter *painter, QPaintDevice *device, QSize size, QRegion &changed, int alignx=0, int aligny=0)
Definition: osd.cpp:787
QSize vsz_display_size
Definition: videooutbase.h:344
void DisableFade(void)
Definition: osd.h:147
virtual void BestDeint(void)
Change to the best deinterlacing method.
virtual void MoveResizeWindow(QRect new_rect)=0
void SetNeedRepaint(bool needRepaint)
bool IsVideoScalingAllowed(void) const
check if video underscan/overscan is allowed
QString GetVisualiserName(void)
int GetHeight(void) const
Returns current screen width in pixels.
Definition: DisplayRes.h:104
void SetVideoScalingAllowed(bool change)
Disable or enable underscan/overscan.
void InitDisplayMeasurements(uint width, uint height, bool resize)
Init display measurements based on database settings and actual screen parameters.
bool IsEmbedding(void) const
Returns if videooutput is embedding.
int ChangePictureAttribute(PictureAttribute, bool direction)
const FilterInfo * GetFilterInfo(const QString &name) const
void yuv888_to_i44(unsigned char *dest, MythImage *osd_image, QSize dst_size, int left, int top, int right, int bottom, bool ifirst)
Definition: util-osd.cpp:312
long long frameNumber
Definition: mythframe.h:48
void DoPipResize(int pipwidth, int pipheight)
Sets up Picture in Picture image resampler.
PictureAttribute
Definition: videoouttypes.h:89
bool EnableVisualisation(AudioPlayer *audio, bool enable, const QString &name=QString(""))
QRect vsz_desired_display_rect
Definition: videooutbase.h:343
QRect GetVisibleOSDBounds(float &, float &, float) const
Returns visible portions of total OSD bounds.
QSize GetVideoDispDim(void) const
int GetPhysicalHeight(void) const
Returns current screen height in millimeters.
Definition: DisplayRes.h:110
QRect GetDisplayVideoRect(void) const
int GetPictureAttribute(PictureAttribute)
AVCodecID myth2av_codecid(MythCodecID codec_id, bool &vdpau)
void SetInput(const QSize &size, float framerate=0, const QString &codecName=QString())
bool IsVideoScalingAllowed(void) const
const char * name
Definition: ParseText.cpp:328
virtual void ResizeDisplayWindow(const QRect &, bool)
Resize Display Window.
void EmbedInWidget(const QRect &)
Tells video output to embed video in an existing window.
virtual void InitOSD(OSD *osd)
unsigned char * vsz_tmp_buf
Definition: videooutbase.h:346
void * av_malloc(unsigned int size)
bool vsz_enabled
Definition: videooutbase.h:342
QString GetActualVideoRenderer(void) const
static QString const kName
Definition: videoout_omx.h:30
void GetDeinterlacers(QStringList &deinterlacers)
virtual QStringList GetVisualiserList(void)
int GetPhysicalWidth(void) const
Returns current screen width in millimeters.
Definition: DisplayRes.h:107
static QStringList GetAllowedRenderers(MythCodecID, const QSize &)
static QStringList GetFilteredRenderers(const QString &decoder, const QStringList &renderers)
MythMainWindow * GetMythMainWindow(void)
PIPState GetPIPState(void) const
MythYUVAPainter * osd_painter
Definition: videooutbase.h:371
Supports common video output methods used with X11 Servers.
Definition: videoout_xv.h:28
DisplayRes * display_res
Definition: videooutbase.h:364
AdjustFillMode GetAdjustFill(void) const
Returns current adjust fill mode.
static void GetRenderOptions(render_opts &opts, QStringList &cpudeints)
virtual bool hasFullScreenOSD(void) const
Definition: videooutbase.h:309
void yuv888_to_yv12(VideoFrame *frame, MythImage *osd_image, int left, int top, int right, int bottom)
Definition: util-osd.cpp:16
PIPLocation
Definition: videoouttypes.h:19
static void GetRenderOptions(render_opts &opts, QStringList &cpudeints)
virtual void ToggleAdjustFill(AdjustFillMode adjustFillMode=kAdjustFill_Toggle)
Sets up letterboxing for various standard video frame and monitor dimensions, then calls MoveResize()...
AdjustFillMode
Definition: videoouttypes.h:57
virtual bool InputChanged(const QSize &video_dim_buf, const QSize &video_dim_disp, float aspect, MythCodecID myth_codec_id, void *codec_private, bool &aspect_changed)
Tells video output to discard decoded frames and wait for new ones.
virtual void ShutdownVideoResize(void)
QRect GetImageRect(const QRect &rect, QRect *display=nullptr)
translates caption/dvd button rectangle into 'screen' space
int GetNumSetting(const QString &key, int defaultval=0)
static int CalcHueBase(const QString &adaptor_name)
void ResizeDisplayWindow(const QRect &, bool)
Resize Display Window.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
bool SwitchToGUI(tmode next_mode=GUI)
Switches to the GUI resolution specified.
Definition: DisplayRes.cpp:188
virtual void ShowPIP(VideoFrame *frame, MythPlayer *pipplayer, PIPLocation loc)
Composites PiP image onto a video frame.
void start(QRunnable *runnable, const QString &debugName, int priority=0)
static QStringList GetAllowedRenderers(MythCodecID myth_codec_id, const QSize &video_dim)
int64_t disp_timecode
Definition: mythframe.h:50
QSize monitor_dim
Definition: videooutbase.h:368
void DoVideoResize(const QSize &inDim, const QSize &outDim)
Sets up Picture in Picture image resampler.
virtual bool ApproveDeintFilter(const QString &filtername) const
Approves bobdeint filter for XVideo and otherwise defers to VideoOutput::ApproveDeintFilter(const QSt...
static QStringList GetAllowedRenderers(MythCodecID myth_codec_id, const QSize &video_dim)
uint GetMaxCPUs(void) const
PIPState
Definition: videoouttypes.h:10
bool InputChanged(const QSize &input_size_buf, const QSize &input_size_disp, float aspect, MythCodecID myth_codec_id, void *codec_private)
Tells video output to discard decoded frames and wait for new ones.
static void GetRenderOptions(render_opts &opts, QStringList &cpudeints)
Definition: videoout_xv.cpp:80
QSize monitor_sz
Definition: videooutbase.h:367
QString GetOSDRenderer(void) const
virtual QRect GetPIPRect(PIPLocation location, MythPlayer *pipplayer=nullptr, bool do_pixel_adj=true) const
returns QRect of PIP based on PIPLocation
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().
void ToggleMoveBottomLine(void)
QRect GetVisibleOSDBounds(float &, float &, float) const
Returns visible portions of total OSD bounds.
void ResizeVideo(VideoFrame *frame)
virtual void MoveResize(void)
performs all the calculations for video framing and any resizing.
float GetOverridenVideoAspect(void) const
static void init(VideoFrame *vf, VideoFrameType _codec, unsigned char *_buf, int _width, int _height, int _size, const int *p=nullptr, const int *o=nullptr, float _aspect=-1.0F, double _rate=-1.0F, int _aligned=64)
Definition: mythframe.h:115
void VideoAspectRatioChanged(float aspect)
Calls SetVideoAspectRatio(float aspect), then calls MoveResize() to apply changes.
QSize pip_video_size
Definition: videooutbase.h:335
static void GetRenderOptions(render_opts &opts)
static void GetRenderOptions(render_opts &opts, QStringList &cpudeints)
Generate the list of available OpenGL profiles.
void SetDisplayDim(QSize displayDim)
void MoveResize(void)
performs all the calculations for video framing and any resizing.
LetterBoxColour
Definition: videoouttypes.h:72
Definition: osd.h:132
QSize m_size
Definition: mythdisplay.h:19
float GetVideoAspect(void) const
void ConvertToYUV(void)
Definition: mythimage.cpp:433
bool IsEmbedding(void)
Returns if videooutput is embedding.
virtual void Draw(const QRect &area, MythPainter *painter, QPaintDevice *device)=0
bool Init(const QSize &new_video_dim_buf, const QSize &new_video_dim_disp, float aspect, const QRect &new_display_visible_rect, AspectOverrideMode aspectoverride, AdjustFillMode adjustfill)
QRect GetDisplayVisibleRect(void) const
FilterChain * m_deintFilter
Definition: videooutbase.h:353
void ShutdownPipResize(void)
Shuts down Picture in Picture image resampler.
QString GetVideoRenderer(void) const
virtual void GetOSDBounds(QRect &total, QRect &visible, float &visible_aspect, float &font_scaling, float themeAspect) const
QSize GetVideoDim(void) const
static QStringList GetAllowedRenderers(MythCodecID myth_codec_id, const QSize &video_dim)
static VideoOutput * Create(const QString &decoder, MythCodecID codec_id, void *codec_priv, PIPState pipState, const QSize &video_dim_buf, const QSize &video_dim_disp, float video_aspect, QWidget *parentwidget, const QRect &embed_rect, float video_prate, uint playerFlags, QString &codecName)
Depending on compile-time configure settings and run-time renderer settings, create a relevant VideoO...
static QStringList GetAllowedRenderers(MythCodecID myth_codec_id)
static uint buffersize(VideoFrameType type, int width, int height, int _aligned=64)
Definition: mythframe.h:297
bool IsOSDFadeEnabled(void) const
bool IsPIPVisible(void) const
Definition: mythplayer.h:229
VideoOutWindow window
Definition: videooutbase.h:320
void Assign(const QImage &img)
Definition: mythimage.cpp:80
static DisplayInfo GetDisplayInfo(int video_rate=0)
Definition: mythdisplay.cpp:45
int GetPictureAttribute(PictureAttribute attribute)
bool m_deinterlaceBeforeOSD
Definition: videooutbase.h:354
FilterManager * m_deintFiltMan
Definition: videooutbase.h:352
bool SwitchToVideo(int iwidth, int iheight, double frate=0.0)
Switches to the resolution and refresh rate defined in the database for the specified video resolutio...
Definition: DisplayRes.cpp:126
void ToggleAdjustFill(AdjustFillMode adjustFillMode=kAdjustFill_Toggle)
Sets up letterboxing for various standard video frame and monitor dimensions, then calls MoveResize()...
#define ALIGN_C
Definition: util-osd.h:8
void SetVideoResize(const QRect &videoRect)
Tells the player to resize the video frame (used for ITV)
virtual void ToggleMoveBottomLine(void)
AspectOverrideMode db_aspectoverride
Definition: videooutbase.h:323
MythImage * GetFormatImage()
Returns a blank reference counted image in the format required for the Draw functions for this painte...
QString GetHostName(void)
virtual bool SetupDeinterlace(bool interlaced, const QString &overridefilter="")
Attempts to enable or disable deinterlacing.
unsigned char * buf
Definition: mythframe.h:39
ZoomDirection
Definition: videoouttypes.h:28
virtual bool SetupVisualisation(AudioPlayer *audio, MythRender *render, const QString &name)
virtual ~VideoOutput()
Shuts down video output.
void StopEmbedding(void)
Tells video output to stop embedding video in an existing window.
AspectOverrideMode GetAspectOverride(void) const
Returns current aspect override mode.
virtual bool SetDeinterlacingEnabled(bool)
Attempts to enable/disable deinterlacing using existing deinterlace method when enabling.
void SetDisplayVisibleRect(QRect rect)
struct SwsContext * vsz_scale_context
Definition: videooutbase.h:347
virtual void FallbackDeint(void)
Fallback to non-frame-rate-doubling deinterlacing method.
void Zoom(ZoomDirection direction)
Sets up zooming into to different parts of the video, the zoom is actually applied in MoveResize().
int SetPictureAttribute(PictureAttribute attribute, int value)
bool IsDecoderCompatible(const QString &decoder)
bool IsPIPActive(void) const
Definition: mythplayer.h:228
virtual void DrawSlice(VideoFrame *frame, int x, int y, int w, int h)
Informs video output of new data for frame, used for hardware accelerated decoding.
int GetMaxWidth(void) const
Returns maximum width in pixels supported by display.
Definition: DisplayRes.h:128
QSize GetDisplayDim(void) const
VideoFrameType codec
Definition: mythframe.h:38