MythTV  master
videoout_xv.cpp
Go to the documentation of this file.
1 #include "mythplayer.h"
2 
3 /* Based on xqcam.c by Paul Chinn <loomer@svpal.org> */
4 
5 // ANSI C headers
6 #include <cstdlib>
7 #include <cstring>
8 #include <cmath>
9 #include <ctime>
10 #include <cerrno>
11 
12 #if HAVE_MALLOC_H
13 #include <malloc.h>
14 #endif
15 #include <fcntl.h>
16 #include <unistd.h>
17 #include <sys/time.h>
18 #include <sys/ipc.h>
19 #include <sys/shm.h>
20 #include <X11/keysym.h>
21 
22 #include <algorithm>
23 #include <iostream>
24 using namespace std;
25 
26 #include "mythconfig.h"
27 
28 // MythTV OSD headers
29 #include "yuv2rgb.h"
30 #include "osd.h"
31 #include "osdchromakey.h"
32 
33 // MythTV X11 headers
34 #include "videoout_xv.h"
35 #include "mythxdisplay.h"
36 #include "util-xv.h"
37 
38 // MythTV General headers
39 #include "mythcorecontext.h"
40 #include "mythlogging.h"
41 #include "filtermanager.h"
42 #include "videodisplayprofile.h"
43 #define IGNORE_TV_PLAY_REC
44 #include "tv.h"
45 #include "fourcc.h"
46 #include "mythmainwindow.h"
47 #include "mythuihelper.h"
48 #include "mythavutil.h"
49 
50 #define LOC QString("VideoOutputXv: ")
51 
52 extern "C" {
53 #include <X11/extensions/xf86vmode.h>
54 #include <X11/extensions/Xinerama.h>
55 #ifndef _XSHM_H_
56  extern int XShmQueryExtension(Display*);
57  extern int XShmGetEventBase(Display*);
58 #endif // silences warning when these are already defined
59 
60 #include "libswscale/swscale.h"
61 #include "libavutil/imgutils.h"
62 }
63 
64 #if ! HAVE_ROUND
65 #define round(x) ((int) ((x) + 0.5))
66 #endif
67 
68 static QStringList allowed_video_renderers(
69  MythCodecID codec_id, MythXDisplay *display, Window curwin = 0);
70 
71 static void SetFromEnv(bool &useXV, bool &useShm);
72 static void SetFromHW(MythXDisplay *d, Window curwin,
73  bool &useXV, bool &useShm);
74 
75 const char *vr_str[] =
76 {
77  "unknown", "xlib", "xshm", "xv-blit",
78 };
79 
81  QStringList &cpudeints)
82 {
83  opts.renderers->append("xlib");
84  opts.renderers->append("xshm");
85  opts.renderers->append("xv-blit");
86 
87  opts.deints->insert("xlib", cpudeints);
88  opts.deints->insert("xshm", cpudeints);
89  opts.deints->insert("xv-blit", cpudeints);
90  (*opts.deints)["xv-blit"].append("bobdeint");
91 
92  (*opts.osds)["xlib"].append("softblend");
93  (*opts.osds)["xshm"].append("softblend");
94  (*opts.osds)["xv-blit"].append("softblend");
95  (*opts.osds)["xv-blit"].append("chromakey");
96 
97  (*opts.safe_renderers)["dummy"].append("xlib");
98  (*opts.safe_renderers)["dummy"].append("xshm");
99  (*opts.safe_renderers)["dummy"].append("xv-blit");
100  (*opts.safe_renderers)["nuppel"].append("xlib");
101  (*opts.safe_renderers)["nuppel"].append("xshm");
102  (*opts.safe_renderers)["nuppel"].append("xv-blit");
103 
104  (*opts.render_group)["x11"].append("xlib");
105  (*opts.render_group)["x11"].append("xshm");
106  (*opts.render_group)["x11"].append("xv-blit");
107 
108  opts.priorities->insert("xlib", 20);
109  opts.priorities->insert("xshm", 30);
110  opts.priorities->insert("xv-blit", 90);
111 
112  if (opts.decoders->contains("ffmpeg"))
113  {
114  (*opts.safe_renderers)["ffmpeg"].append("xlib");
115  (*opts.safe_renderers)["ffmpeg"].append("xshm");
116  (*opts.safe_renderers)["ffmpeg"].append("xv-blit");
117  }
118 
119  if (opts.decoders->contains("crystalhd"))
120  {
121  (*opts.safe_renderers)["crystalhd"].append("xlib");
122  (*opts.safe_renderers)["crystalhd"].append("xshm");
123  (*opts.safe_renderers)["crystalhd"].append("xv-blit");
124  }
125 }
126 
138  : VideoOutput(),
139  video_output_subtype(XVUnknown),
140  global_lock(QMutex::Recursive),
141 
142  XJ_win(0), XJ_curwin(0), disp(nullptr), XJ_letterbox_colour(0),
143  XJ_started(false),
144 
145  XJ_non_xv_image(nullptr), non_xv_frames_shown(0), non_xv_show_frame(1),
146  non_xv_fps(0), non_xv_av_format(AV_PIX_FMT_NB), non_xv_stop_time(0),
147 
148  xv_port(-1), xv_hue_base(0),
149  xv_colorkey(0), xv_draw_colorkey(false),
150  xv_chroma(0), xv_set_defaults(false),
151  xv_need_bobdeint_repaint(false),
152  xv_use_picture_controls(true),
153 
154  chroma_osd(nullptr)
155 {
156  LOG(VB_PLAYBACK, LOG_INFO, LOC + "ctor");
157  memset(&av_pause_frame, 0, sizeof(av_pause_frame));
158 
159  if (gCoreContext->GetBoolSetting("UseVideoModes", false))
161 }
162 
164 {
165  LOG(VB_PLAYBACK, LOG_INFO, LOC + "dtor");
166 
167  const QRect tmp_display_visible_rect =
169 
170  if (window.GetPIPState() == kPIPStandAlone &&
171  !tmp_display_visible_rect.isEmpty())
172  {
173  window.SetDisplayVisibleRect(tmp_display_visible_rect);
174  }
175 
176  if (XJ_started)
177  {
178  const QRect display_visible_rect = window.GetDisplayVisibleRect();
180  disp->FillRectangle(XJ_curwin, display_visible_rect);
181  m_deinterlacing = false;
182  }
183 
184  // Delete the video buffers
186 
187  // ungrab port...
188  if (xv_port >= 0 && XJ_started)
189  {
190  XLOCK(disp, XvStopVideo(disp->GetDisplay(), xv_port, XJ_curwin));
192  xv_port = -1;
193  }
194 
195  if (XJ_started)
196  {
197  XJ_started = false;
198  delete disp;
199  disp = nullptr;
200  }
201 }
202 
203 // this is documented in videooutbase.cpp
205 {
206  QMutexLocker locker(&global_lock);
207  VideoOutput::Zoom(direction);
208  MoveResize();
209 }
210 
211 // this is documented in videooutbase.cpp
213 {
214  QMutexLocker locker(&global_lock);
216  if (chroma_osd)
217  window.SetNeedRepaint(true);
218 }
219 
220 void VideoOutputXv::WindowResized(const QSize &new_size)
221 {
222  // This is causing problems in association with xrandr/display resolution
223  // switching. Disabling for 0.24 as this is the only videooutput class
224  // that implements this method
225  // see http://cvs.mythtv.org/trac/ticket/7408
226  QMutexLocker locker(&global_lock);
227 
228  window.SetDisplayVisibleRect(QRect(QPoint(0, 0), new_size));
229 
230  const QSize display_dim = QSize(
231  (monitor_dim.width() * new_size.width()) / monitor_sz.width(),
232  (monitor_dim.height() * new_size.height())/ monitor_sz.height());
233  window.SetDisplayDim(display_dim);
234 
236  ((float)display_dim.width()) / display_dim.height());
237 
238  MoveResize();
239 }
240 
241 // documented in videooutbase.cpp
242 bool VideoOutputXv::InputChanged(const QSize &video_dim_buf,
243  const QSize &video_dim_disp,
244  float aspect,
245  MythCodecID av_codec_id,
246  void *codec_private,
247  bool &aspect_only)
248 {
249  LOG(VB_PLAYBACK, LOG_INFO, LOC +
250  QString("InputChanged(%1,%2,%3) '%4'->'%5'")
251  .arg(video_dim_disp.width()).arg(video_dim_disp.height())
252  .arg(aspect)
253  .arg(toString(video_codec_id)).arg(toString(av_codec_id)));
254 
255  QMutexLocker locker(&global_lock);
256 
257  bool cid_changed = (video_codec_id != av_codec_id);
258  bool res_changed = video_dim_disp != window.GetActualVideoDim();
259  bool asp_changed = aspect != window.GetVideoAspect();
260 
261  if (!res_changed && !cid_changed)
262  {
263  aspect_only = true;
264  if (asp_changed)
265  {
266  VideoAspectRatioChanged(aspect);
267  MoveResize();
268  }
269  return true;
270  }
271 
272  VideoOutput::InputChanged(video_dim_buf, video_dim_disp,
273  aspect, av_codec_id, codec_private,
274  aspect_only);
275 
276  bool delete_pause_frame = cid_changed;
277  DeleteBuffers(VideoOutputSubType(), delete_pause_frame);
278 
279  const QSize video_disp_dim = window.GetVideoDispDim();
280  ResizeForVideo((uint) video_disp_dim.width(),
281  (uint) video_disp_dim.height());
282 
283  bool ok = true;
284  if (cid_changed)
285  {
286  // ungrab port...
287  if (xv_port >= 0)
288  {
290  xv_port = -1;
291  }
292 
293  ok = InitSetupBuffers();
294  }
295  else
296  {
298  }
299 
300  InitColorKey(true);
301  CreateOSD();
302 
303  MoveResize();
304 
305  if (!ok)
306  {
307  LOG(VB_GENERAL, LOG_ERR, LOC +
308  "InputChanged(): Failed to recreate buffers");
310  }
311 
312  return ok;
313 }
314 
316 {
317  if (disp)
318  disp->MoveResizeWin(XJ_win, new_rect);
319 }
320 
322 {
323  public:
324  XvAttributes() = default;
325  XvAttributes(const QString &a, uint b, uint c) :
326  description(a), xv_flags(b), feature_flags(c) {}
327 
328  public:
329  QString description;
332 
333  static const uint kFeatureNone = 0x00;
334  static const uint kFeatureChromakey = 0x01;
335  static const uint kFeaturePicCtrl = 0x02;
336 };
337 
342 {
343  if (!disp)
344  return;
345 
346  LOG(VB_PLAYBACK, LOG_INFO, LOC +
347  QString("Closing XVideo port %1").arg(port));
348  disp->Lock();
350  XvUngrabPort(disp->GetDisplay(), port, CurrentTime);
351  del_open_xv_port(port);
352  disp->Unlock();
353 }
354 
361  MythCodecID /*mcodecid*/,
362  uint width, uint height,
363  bool &xvsetdefaults,
364  QString *adaptor_name)
365 {
366  if (adaptor_name)
367  *adaptor_name = QString();
368 
369  // create list of requirements to check in order..
370  vector<XvAttributes> req;
371  req.push_back(XvAttributes(
372  "XVideo surface found on port %1",
373  XvInputMask | XvImageMask,
375 
376  // try to get an adapter with picture attributes
377  uint end = req.size();
378  for (uint i = 0; i < end; i++)
379  {
380  req.push_back(req[i]);
381  req[i].feature_flags |= XvAttributes::kFeaturePicCtrl;
382  }
383 
384  // figure out if we want chromakeying..
385  db_vdisp_profile->SetInput(QSize(width, height));
386  if (db_vdisp_profile->GetOSDRenderer() == "chromakey")
387  {
388  end = req.size();
389  for (uint i = 0; i < end; i++)
390  {
391  req.push_back(req[i]);
392  req[i].feature_flags |= XvAttributes::kFeatureChromakey;
393  }
394  }
395 
396  // get the list of Xv ports
397  XvAdaptorInfo *ai = nullptr;
398  uint p_num_adaptors = 0;
399  int ret = Success;
400  XLOCK(disp, ret = XvQueryAdaptors(disp->GetDisplay(), root,
401  &p_num_adaptors, &ai));
402  if (Success != ret)
403  {
404  LOG(VB_GENERAL, LOG_ERR, LOC +
405  "XVideo supported, but no free Xv ports found."
406  "\n\t\t\tYou may need to reload video driver.");
407  return -1;
408  }
409 
410  QString lastAdaptorName;
411  int port = -1;
412 
413  // find an Xv port
414  for (uint j = 0; j < req.size(); ++j)
415  {
416  LOG(VB_PLAYBACK, LOG_INFO, LOC +
417  QString("@ j=%1 Looking for flag[s]: %2 %3")
418  .arg(j).arg(xvflags2str(req[j].xv_flags))
419  .arg(req[j].feature_flags,0,16));
420 
421  for (int i = 0; i < (int)p_num_adaptors && (port == -1); ++i)
422  {
423  lastAdaptorName = ai[i].name;
424  LOG(VB_PLAYBACK, LOG_INFO, LOC +
425  QString("Adaptor#%1: %2 has flag[s]: %3")
426  .arg(i).arg(lastAdaptorName).arg(xvflags2str(ai[i].type)));
427 
428  if ((ai[i].type & req[j].xv_flags) != req[j].xv_flags)
429  {
430  LOG(VB_PLAYBACK, LOG_ERR, LOC +
431  "Missing XVideo flags, rejecting.");
432  continue;
433  }
434  else
435  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Has XVideo flags...");
436 
437  const XvPortID firstPort = ai[i].base_id;
438  const XvPortID lastPort = ai[i].base_id + ai[i].num_ports - 1;
439  XvPortID p = 0;
440 
441  if ((req[j].feature_flags & XvAttributes::kFeaturePicCtrl) &&
442  (!xv_is_attrib_supported(disp, firstPort, "XV_BRIGHTNESS")))
443  {
444  LOG(VB_PLAYBACK, LOG_ERR, LOC +
445  "Missing XV_BRIGHTNESS, rejecting.");
446  continue;
447  }
448  else if (req[j].feature_flags & XvAttributes::kFeaturePicCtrl)
449  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Has XV_BRIGHTNESS...");
450 
451  if ((req[j].feature_flags & XvAttributes::kFeatureChromakey) &&
452  (!xv_is_attrib_supported(disp, firstPort, "XV_COLORKEY")))
453  {
454  LOG(VB_PLAYBACK, LOG_ERR, LOC +
455  "Missing XV_COLORKEY, rejecting.");
456  continue;
457  }
458  else if (req[j].feature_flags & XvAttributes::kFeatureChromakey)
459  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Has XV_COLORKEY...");
460 
461  for (p = firstPort; (p <= lastPort) && (port == -1); ++p)
462  {
463  disp->Lock();
464  ret = XvGrabPort(disp->GetDisplay(), p, CurrentTime);
465  if (Success == ret)
466  {
467  LOG(VB_PLAYBACK, LOG_INFO, LOC +
468  QString("Grabbed xv port %1").arg(p));
469  port = p;
470  xvsetdefaults = add_open_xv_port(disp, p);
471  }
472  disp->Unlock();
473  }
474  }
475 
476  if (port != -1)
477  {
478  LOG(VB_PLAYBACK, LOG_INFO, LOC + req[j].description.arg(port));
479  LOG(VB_PLAYBACK, LOG_INFO, LOC +
480  QString("XV_SET_DEFAULTS is %1supported on this port")
481  .arg(xvsetdefaults ? "" : "not "));
482 
483  bool xv_vsync = xv_is_attrib_supported(disp, port,
484  "XV_SYNC_TO_VBLANK");
485  LOG(VB_PLAYBACK, LOG_INFO, LOC +
486  QString("XV_SYNC_TO_VBLANK %1supported")
487  .arg(xv_vsync ? "" : "not "));
488  if (xv_vsync)
489  {
490  LOG(VB_PLAYBACK, LOG_INFO, LOC +
491  QString("XVideo Sync to VBlank %1set")
492  .arg(xv_set_attrib(disp, port, "XV_SYNC_TO_VBLANK", 1) ?
493  "" : "NOT "));
494  }
495 
496  break;
497  }
498  }
499 
500  if (port == -1)
501  LOG(VB_PLAYBACK, LOG_INFO, LOC + "No suitable XVideo port found");
502 
503  // free list of Xv ports
504  if (ai)
505  XLOCK(disp, XvFreeAdaptorInfo(ai));
506 
507  if ((port != -1) && adaptor_name)
508  *adaptor_name = lastAdaptorName;
509 
510  return port;
511 }
512 
522 {
523  if (av_pause_frame.buf)
524  {
525  av_freep(&av_pause_frame.buf);
526  }
527 
528  int size = buffersize(FMT_YV12,
531  unsigned char* buf = (unsigned char*)av_malloc(size);
535  size);
536 
538 
540 }
541 
549 bool VideoOutputXv::InitVideoBuffers(bool use_xv, bool use_shm)
550 {
551  bool done = false;
552 
553  // Create ffmpeg VideoFrames
554  vbuffers.Init(31, true, 1, 12, 4, 2);
555 
556  // Fall back to XVideo if there is an xv_port
557  if (use_xv)
558  done = InitXVideo();
559 
560  // only HW accel allowed for PIP and PBP
561  if (!done && window.GetPIPState() > kPIPOff)
562  return done;
563 
564  // Fall back to shared memory, if we are allowed to use it
565  if (!done && use_shm)
566  done = InitXShm();
567 
568  // Fall back to plain old X calls
569  if (!done)
570  done = InitXlib();
571 
572  if (done)
574 
575  return done;
576 }
577 
578 static bool has_format(XvImageFormatValues *formats, int format_cnt, int id)
579 {
580  for (int i = 0; i < format_cnt; i++)
581  {
582  if (formats[i].id == id)
583  return true;
584  }
585 
586  return false;
587 }
588 
598 {
599  MythXLocker lock(disp);
600  disp->StartLog();
601  QString adaptor_name;
602  const QSize video_dim = window.GetVideoDim();
604  video_dim.width(), video_dim.height(),
605  xv_set_defaults, &adaptor_name);
606  if (xv_port == -1)
607  {
608  LOG(VB_GENERAL, LOG_ERR, LOC +
609  "Could not find suitable XVideo surface.");
610  return false;
611  }
612 
613  LOG(VB_GENERAL, LOG_INFO, LOC + QString("XVideo Adaptor Name: '%1'")
614  .arg(adaptor_name));
615 
616  xv_hue_base = VideoOutput::CalcHueBase(adaptor_name);
618  adaptor_name != "Intel(R) Video Overlay";
619 
620  bool foundimageformat = false;
622  int format_cnt = 0;
623  XvImageFormatValues *formats;
624  formats = XvListImageFormats(disp->GetDisplay(), xv_port, &format_cnt);
625 
626  for (int i = 0; i < format_cnt; i++)
627  {
628  char *chr = (char*) &(formats[i].id);
629  LOG(VB_PLAYBACK, LOG_INFO, LOC +
630  QString("XVideo Format #%1 is '%2%3%4%5'")
631  .arg(i).arg(chr[0]).arg(chr[1]).arg(chr[2]).arg(chr[3]));
632  }
633 
634  for (uint i = 0; i < sizeof(ids)/sizeof(int); i++)
635  {
636  if (has_format(formats, format_cnt, ids[i]))
637  {
638  xv_chroma = ids[i];
639  foundimageformat = true;
640  break;
641  }
642  }
643 
644  // IYUV is bit identical to I420, just pretend we saw I420
646 
647  if (formats)
648  XFree(formats);
649 
650  if (foundimageformat)
651  {
652  char *chr = (char*) &xv_chroma;
653  LOG(VB_PLAYBACK, LOG_INFO, LOC +
654  QString("Using XVideo Format '%1%2%3%4'")
655  .arg(chr[0]).arg(chr[1]).arg(chr[2]).arg(chr[3]));
656  }
657  else
658  {
659  LOG(VB_GENERAL, LOG_ERR, LOC +
660  "Couldn't find the proper XVideo image format.");
662  xv_port = -1;
663  }
664 
665  bool ok = xv_port >= 0;
666  if (ok)
667  ok = CreateBuffers(XVideo);
668 
669  if (!disp->StopLog())
670  {
671  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create XVideo Buffers.");
672  DeleteBuffers(XVideo, false);
674  xv_port = -1;
675  ok = false;
676  }
677  else
678  {
681  }
682 
683  return ok;
684 }
685 
695 {
696  MythXLocker lock(disp);
697  disp->StartLog();
698 
699  LOG(VB_GENERAL, LOG_ERR, LOC +
700  "Falling back to X shared memory video output."
701  "\n\t\t\t *** May be slow ***");
702 
703  bool ok = CreateBuffers(XShm);
704 
705  if (!disp->StopLog())
706  {
707  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate X shared memory.");
708  DeleteBuffers(XShm, false);
709  ok = false;
710  }
711  else
712  {
714  window.SetAllowPreviewEPG(false);
715  }
716 
717  return ok;
718 }
719 
729 {
730  MythXLocker lock(disp);
731  disp->StartLog();
732 
733  LOG(VB_GENERAL, LOG_ERR, LOC +
734  "Falling back to X11 video output over a network socket."
735  "\n\t\t\t *** May be very slow ***");
736 
737  bool ok = CreateBuffers(Xlib);
738 
739  if (!disp->StopLog())
740  {
741  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create X buffers.");
742  DeleteBuffers(Xlib, false);
743  ok = false;
744  }
745  else
746  {
748  window.SetAllowPreviewEPG(false);
749  }
750 
751  return ok;
752 }
753 
758 {
759  return (MythCodecID)(kCodec_MPEG1 + (stream_type-1));
760 }
761 
763 {
764  QString osdrenderer = db_vdisp_profile->GetOSDRenderer();
765 
766  if (osdrenderer == "chromakey")
767  {
768  if ((xv_colorkey == (int)XJ_letterbox_colour) ||
770  {
771  LOG(VB_PLAYBACK, LOG_ERR, LOC +
772  "Disabling ChromaKeyOSD as colorkeying will not work.");
773  }
774  else if (!((32 == disp->GetDepth()) || (24 == disp->GetDepth())))
775  {
776  LOG(VB_GENERAL, LOG_ERR, LOC +
777  QString("Number of bits per pixel is %1, \n\t\t\t"
778  "but we only support ARGB 32 bbp for ChromaKeyOSD.")
779  .arg(disp->GetDepth()));
780  }
781  else
782  {
783  chroma_osd = new ChromaKeyOSD(this);
784  }
785  return chroma_osd;
786  }
787 
788  return true;
789 }
790 
791 #define XV_INIT_FATAL_ERROR_TEST(test,msg) \
792 do { \
793  if (test) \
794  { \
795  LOG(VB_GENERAL, LOG_ERR, LOC + (msg) + " Exiting playback."); \
796  errorState = kError_Unknown; \
797  return false; \
798  } \
799 } while (false)
800 
801 static QString toCommaList(const QStringList &list)
802 {
803  QString ret = "";
804  for (QStringList::const_iterator it = list.begin(); it != list.end(); ++it)
805  ret += *it + ",";
806 
807  if (ret.length())
808  return ret.left(ret.length()-1);
809 
810  return "";
811 }
812 
814 {
815  // Figure out what video renderer to use
817  QStringList renderers = allowed_video_renderers(
819  QString renderer;
820 
821  QString tmp1 = db_vdisp_profile->GetVideoRenderer();
822  LOG(VB_PLAYBACK, LOG_INFO, LOC + "InitSetupBuffers() " +
823  QString("render: %1, allowed: %2")
824  .arg(tmp1).arg(toCommaList(renderers)));
825 
826  if (renderers.contains(tmp1))
827  renderer = tmp1;
828  else if (renderers.empty())
829  XV_INIT_FATAL_ERROR_TEST(false, "Failed to find a video renderer");
830  else
831  {
832  QString tmp2;
833  QStringList::const_iterator it = renderers.begin();
834  for (; it != renderers.end(); ++it)
835  tmp2 += *it + ",";
836 
837  renderer = renderers[0];
838 
839  LOG(VB_GENERAL, LOG_ERR, LOC +
840  QString("Desired video renderer '%1' not available.\n\t\t\t"
841  "codec '%2' makes '%3' available, using '%4' instead.")
843  .arg(toString(video_codec_id)).arg(tmp2).arg(renderer));
845  }
846 
847  // Create video buffers
848  bool use_xv = (renderer.startsWith("xv"));
849  bool use_shm = (renderer == "xshm");
850  bool ok = InitVideoBuffers(use_xv, use_shm);
851 
852  if (!ok && window.GetPIPState() == kPIPOff)
853  {
854  use_xv |= renderers.contains("xv-blit");
855  use_shm |= renderers.contains("xshm");
856  ok = InitVideoBuffers(use_xv, use_shm);
857  }
858  XV_INIT_FATAL_ERROR_TEST(!ok, "Failed to get any video output");
859 
860  if (xv_port && (VideoOutputSubType() >= XVideo))
862 
863  // Initialize the picture controls if we need to..
866 
867  return true;
868 }
869 
876 bool VideoOutputXv::Init(const QSize &video_dim_buf,
877  const QSize &video_dim_disp,
878  float aspect,
879  WId winid, const QRect &win_rect, MythCodecID codec_id)
880 {
881  window.SetNeedRepaint(true);
882 
883  XV_INIT_FATAL_ERROR_TEST(winid <= 0, "Invalid Window ID.");
884 
886  XV_INIT_FATAL_ERROR_TEST(!disp, "Failed to open display.");
887 
888  // Initialize X stuff
889  MythXLocker lock(disp);
890 
891  XJ_curwin = winid;
892  XJ_win = winid;
893  XV_INIT_FATAL_ERROR_TEST(!disp->CreateGC(XJ_win), "Failed to create GC.");
894 
895  // The letterbox color..
897  Colormap cmap = XDefaultColormap(disp->GetDisplay(), disp->GetScreen());
898  XColor colour, colour_exact;
900  QByteArray ascii_name = name.toLatin1();
901  const char *cname = ascii_name.constData();
902  if (XAllocNamedColor(disp->GetDisplay(), cmap, cname, &colour, &colour_exact))
903  XJ_letterbox_colour = colour.pixel;
904 
905  XJ_started = true;
906 
907  // Basic setup
908  VideoOutput::Init(video_dim_buf, video_dim_disp,
909  aspect, winid, win_rect, codec_id);
910 
911  // Set resolution/measurements (check XRandR, Xinerama, config settings)
912  InitDisplayMeasurements(video_dim_disp.width(), video_dim_disp.height(),
913  true);
914 
915  if (!InitSetupBuffers())
916  return false;
917 
918  InitColorKey(true);
919  CreateOSD();
920 
921  MoveResize();
922 
923  return true;
924 }
925 #undef XV_INIT_FATAL_ERROR_TEST
926 
933 void VideoOutputXv::InitColorKey(bool turnoffautopaint)
934 {
936  return;
937 
938  static const char *attr_autopaint = "XV_AUTOPAINT_COLORKEY";
939  int xv_val=0;
940 
941  // handle autopaint.. Normally we try to disable it so that bob-deint
942  // doesn't actually bob up the top and bottom borders up and down...
943  xv_draw_colorkey = true;
944  if (xv_is_attrib_supported(disp, xv_port, attr_autopaint, &xv_val))
945  {
946  if (turnoffautopaint && xv_val)
947  {
948  xv_set_attrib(disp, xv_port, attr_autopaint, 0);
949  if (!xv_get_attrib(disp, xv_port, attr_autopaint, xv_val) ||
950  xv_val)
951  {
952  LOG(VB_GENERAL, LOG_ERR, "Failed to disable autopaint");
953  xv_draw_colorkey = false;
954  }
955  }
956  else if (!turnoffautopaint && !xv_val)
957  {
958  xv_set_attrib(disp, xv_port, attr_autopaint, 1);
959  if (!xv_get_attrib(disp, xv_port, attr_autopaint, xv_val) ||
960  !xv_val)
961  {
962  LOG(VB_GENERAL, LOG_ERR, "Failed to enable autopaint");
963  }
964  }
965  else if (!turnoffautopaint && xv_val)
966  {
967  xv_draw_colorkey = false;
968  }
969  }
970 
971  // Check that we have a colorkey attribute and make sure it is not
972  // the same color as the MythTV letterboxing (currently Black).
973  // This avoids avoid bob-deint actually bobbing the borders of
974  // the video up and down..
975  int letterbox_color = XJ_letterbox_colour;
976  static const char *attr_chroma = "XV_COLORKEY";
977  if (!xv_is_attrib_supported(disp, xv_port, attr_chroma, &xv_colorkey))
978  {
979  // set to MythTV letterbox color as a sentinel
980  xv_colorkey = letterbox_color;
981  }
982  else if (xv_colorkey == letterbox_color)
983  {
984  // if it is a valid attribute and set to the letterbox color, change it
985  xv_set_attrib(disp, xv_port, attr_chroma, 1);
986 
987  if (xv_get_attrib(disp, xv_port, attr_chroma, xv_val) &&
988  xv_val != letterbox_color)
989  {
990  xv_colorkey = xv_val;
991  }
992  }
993 
994  if (xv_colorkey == letterbox_color)
995  {
996  LOG(VB_PLAYBACK, LOG_INFO, LOC +
997  "Chromakeying not possible with this XVideo port.");
998  }
999 }
1000 
1001 // documented in videooutbase.cpp
1003 {
1004  bool deint = VideoOutput::SetDeinterlacingEnabled(enable);
1005  xv_need_bobdeint_repaint = (m_deintfiltername == "bobdeint");
1006  return deint;
1007 }
1008 
1009 bool VideoOutputXv::SetupDeinterlace(bool interlaced,
1010  const QString& overridefilter)
1011 {
1012  bool deint = VideoOutput::SetupDeinterlace(interlaced, overridefilter);
1013  window.SetNeedRepaint(true);
1014  return deint;
1015 }
1016 
1024 bool VideoOutputXv::ApproveDeintFilter(const QString &filtername) const
1025 {
1026  // TODO implement bobdeint for non-Xv
1027  VOSType vos = VideoOutputSubType();
1028 
1029  if (filtername == "bobdeint" && (vos >= XVideo))
1030  return true;
1031 
1032  return VideoOutput::ApproveDeintFilter(filtername);
1033 }
1034 
1046 vector<unsigned char*> VideoOutputXv::CreateShmImages(uint num, bool use_xv)
1047 {
1048  const QSize video_dim = window.GetVideoDim();
1049  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1050  QString("CreateShmImages(%1): video_dim: %2x%3")
1051  .arg(num).arg(video_dim.width()).arg(video_dim.height()));
1052 
1053  MythXLocker lock(disp);
1054  Display *d = disp->GetDisplay();
1055  vector<unsigned char*> bufs;
1056  for (uint i = 0; i < num; i++)
1057  {
1058  XShmSegmentInfo *info = new XShmSegmentInfo;
1059  void *image = nullptr;
1060  int size = 0;
1061  int desiredsize = 0;
1062 
1063  if (use_xv)
1064  {
1065  XvImage *img =
1066  XvShmCreateImage(d, xv_port, xv_chroma, nullptr,
1067  video_dim.width(), video_dim.height(), info);
1068  size = img->data_size + 64;
1069  image = img;
1070  desiredsize = video_dim.width() * video_dim.height() * 3 / 2;
1071 
1072  if (image && size < desiredsize)
1073  {
1074  LOG(VB_GENERAL, LOG_ERR, LOC + "CreateXvShmImages(): "
1075  "XvShmCreateImage() failed to create image of the "
1076  "requested size.");
1077  XFree(image);
1078  image = nullptr;
1079  delete info;
1080  }
1081 
1082  if (image && (3 == img->num_planes))
1083  {
1084  XJ_shm_infos.push_back(info);
1085  YUVInfo tmp(img->width, img->height, img->data_size,
1086  img->pitches, img->offsets);
1087  if (xv_chroma == GUID_YV12_PLANAR)
1088  {
1089  swap(tmp.pitches[1], tmp.pitches[2]);
1090  swap(tmp.offsets[1], tmp.offsets[2]);
1091  }
1092 
1093  XJ_yuv_infos.push_back(tmp);
1094  }
1095  else if (image)
1096  {
1097  LOG(VB_GENERAL, LOG_ERR, LOC + "CreateXvShmImages(): "
1098  "XvShmCreateImage() failed to create image "
1099  "with the correct number of pixel planes.");
1100  XFree(image);
1101  image = nullptr;
1102  delete info;
1103  }
1104  }
1105  else
1106  {
1107  int width = window.GetDisplayVisibleRect().width() & ~0x1;
1108  int height = window.GetDisplayVisibleRect().height() & ~0x1;
1109  XImage *img =
1110  XShmCreateImage(d, DefaultVisual(d, disp->GetScreen()),
1111  disp->GetDepth(), ZPixmap, nullptr, info,
1112  width, height);
1113  size = img->bytes_per_line * img->height + 64;
1114  image = img;
1115  desiredsize = (width * height * 3 / 2);
1116  if (image && size < desiredsize)
1117  {
1118  LOG(VB_GENERAL, LOG_ERR, LOC + "CreateXvShmImages(): "
1119  "XShmCreateImage() failed to create image of the "
1120  "requested size.");
1121  XDestroyImage((XImage *)image);
1122  image = nullptr;
1123  delete info;
1124  }
1125 
1126  if (image)
1127  {
1128  YUVInfo tmp(img->width, img->height,
1129  img->bytes_per_line * img->height, nullptr, nullptr);
1130  XJ_yuv_infos.push_back(tmp);
1131  XJ_shm_infos.push_back(info);
1132  }
1133  }
1134 
1135  if (image)
1136  {
1137  XJ_shm_infos[i]->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
1138  if (XJ_shm_infos[i]->shmid >= 0)
1139  {
1140  XJ_shm_infos[i]->shmaddr = (char*)
1141  shmat(XJ_shm_infos[i]->shmid, nullptr, 0);
1142  if (use_xv)
1143  ((XvImage*)image)->data = XJ_shm_infos[i]->shmaddr;
1144  else
1145  ((XImage*)image)->data = XJ_shm_infos[i]->shmaddr;
1146  xv_buffers[(unsigned char*) XJ_shm_infos[i]->shmaddr] = image;
1147  XJ_shm_infos[i]->readOnly = False;
1148 
1149  XShmAttach(d, XJ_shm_infos[i]);
1150  disp->Sync(); // needed for FreeBSD?
1151 
1152  // Mark for delete immediately.
1153  // It won't actually be removed until after we detach it.
1154  shmctl(XJ_shm_infos[i]->shmid, IPC_RMID, nullptr);
1155 
1156  bufs.push_back((unsigned char*) XJ_shm_infos[i]->shmaddr);
1157  }
1158  else
1159  {
1160  LOG(VB_GENERAL, LOG_ERR, LOC +
1161  "CreateXvShmImages(): shmget() failed." + ENO);
1162  break;
1163  }
1164  }
1165  else
1166  {
1167  LOG(VB_GENERAL, LOG_ERR, LOC + "CreateXvShmImages(): "
1168  "XvShmCreateImage() failed to create image.");
1169  break;
1170  }
1171  }
1172  return bufs;
1173 }
1174 
1176 {
1177  bool ok = false;
1178 
1179  const QSize video_dim = window.GetVideoDim();
1180  const QRect display_visible_rect = window.GetDisplayVisibleRect();
1181 
1182  if (subtype == XVideo && xv_port >= 0)
1183  {
1184  vector<unsigned char*> bufs =
1185  CreateShmImages(vbuffers.Size(), true);
1186 
1187  ok = (bufs.size() >= vbuffers.Size()) &&
1189  video_dim.width(), video_dim.height(),
1190  bufs, XJ_yuv_infos);
1191 
1192  disp->Sync();
1193  }
1194  else if (subtype == XShm || subtype == Xlib)
1195  {
1196  if (subtype == XShm)
1197  {
1198  vector<unsigned char*> bufs = CreateShmImages(1, false);
1199  if (bufs.empty())
1200  return false;
1201  XJ_non_xv_image = (XImage*) xv_buffers.begin()->second;
1202  }
1203  else
1204  {
1205  MythXLocker lock(disp);
1206  Display *d = disp->GetDisplay();
1207  int bytes_per_line;
1208  int scrn = disp->GetScreen();
1209  Visual *visual = DefaultVisual(d, scrn);
1210  XJ_non_xv_image = XCreateImage(d, visual, disp->GetDepth(),
1211  ZPixmap, /*offset*/0, /*data*/nullptr,
1212  display_visible_rect.width() & ~0x1,
1213  display_visible_rect.height() & ~0x1,
1214  /*bitmap_pad*/8, 0);
1215 
1216  if (!XJ_non_xv_image)
1217  {
1218  LOG(VB_GENERAL, LOG_ERR, LOC + "XCreateImage failed: " +
1219  QString("XJ_disp(0x%1) visual(0x%2) \n")
1220  .arg((uint64_t)d,0,16).arg((uint64_t)visual,0,16) +
1221  QString(" ") +
1222  QString("depth(%1) ").arg(disp->GetDepth()) +
1223  QString("WxH(%1""x%2) ")
1224  .arg(display_visible_rect.width())
1225  .arg(display_visible_rect.height()));
1226  return false;
1227  }
1228  bytes_per_line = XJ_non_xv_image->bytes_per_line;
1229  XJ_non_xv_image->data = (char*) malloc(
1230  bytes_per_line * display_visible_rect.height());
1231  }
1232 
1233  switch (XJ_non_xv_image->bits_per_pixel)
1234  { // only allow these three output formats for non-xv videout
1235  case 16: non_xv_av_format = AV_PIX_FMT_RGB565; break;
1236  case 24: non_xv_av_format = AV_PIX_FMT_RGB24; break;
1237  case 32: non_xv_av_format = AV_PIX_FMT_RGB32; break;
1238  default: non_xv_av_format = AV_PIX_FMT_NB;
1239  }
1240  if (AV_PIX_FMT_NB == non_xv_av_format)
1241  {
1242  QString msg = QString(
1243  "Non XVideo modes only support displays with 16,\n\t\t\t"
1244  "24, or 32 bits per pixel. But you have a %1 bpp display.")
1245  .arg(disp->GetDepth()*8);
1246 
1247  LOG(VB_GENERAL, LOG_ERR, LOC + msg);
1248  }
1249  else
1251  video_dim.width(), video_dim.height());
1252  }
1253 
1254  if (ok)
1255  CreatePauseFrame(subtype);
1256 
1257  return ok;
1258 }
1259 
1260 void VideoOutputXv::DeleteBuffers(VOSType subtype, bool delete_pause_frame)
1261 {
1262  (void) subtype;
1263  DiscardFrames(true);
1264 
1265  if (chroma_osd)
1266  {
1267  delete chroma_osd;
1268  chroma_osd = nullptr;
1269  }
1270 
1271  Display *d = disp->GetDisplay();
1272 
1274 
1275  if (delete_pause_frame)
1276  {
1277  if (av_pause_frame.buf)
1278  {
1279  av_freep(&av_pause_frame.buf);
1280  }
1282  {
1283  av_freep(&av_pause_frame.qscale_table);
1284  }
1285  }
1286 
1287  for (uint i = 0; i < XJ_shm_infos.size(); i++)
1288  {
1289  MythXLocker lock(disp);
1290  XShmDetach(d, XJ_shm_infos[i]);
1291  XvImage *image = (XvImage*)
1292  xv_buffers[(unsigned char*) XJ_shm_infos[i]->shmaddr];
1293  if (image)
1294  {
1295  if ((XImage*)image == XJ_non_xv_image)
1296  XDestroyImage(XJ_non_xv_image);
1297  else
1298  XFree(image);
1299  }
1300  if (XJ_shm_infos[i]->shmaddr)
1301  shmdt(XJ_shm_infos[i]->shmaddr);
1302  if (XJ_shm_infos[i]->shmid > 0)
1303  shmctl(XJ_shm_infos[i]->shmid, IPC_RMID, nullptr);
1304  delete XJ_shm_infos[i];
1305  }
1306  XJ_shm_infos.clear();
1307  xv_buffers.clear();
1308  XJ_yuv_infos.clear();
1309  XJ_non_xv_image = nullptr;
1310 }
1311 
1312 void VideoOutputXv::EmbedInWidget(const QRect &rect)
1313 {
1314  QMutexLocker locker(&global_lock);
1315 
1316  if (!window.IsEmbedding())
1318  MoveResize();
1319 }
1320 
1322 {
1323  if (!window.IsEmbedding())
1324  return;
1325 
1326  QMutexLocker locker(&global_lock);
1327 
1329  MoveResize();
1330 }
1331 
1340 {
1341  if (!frame)
1342  return;
1343 
1344  vbuffers.DiscardFrame(frame);
1345 }
1346 
1348 {
1349  LOG(VB_PLAYBACK, LOG_INFO, LOC + "ClearAfterSeek()");
1350  DiscardFrames(false);
1351 }
1352 
1353 void VideoOutputXv::DiscardFrames(bool next_frame_keyframe)
1354 {
1355  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1356  QString("DiscardFrames(%1)").arg(next_frame_keyframe));
1357  if (VideoOutputSubType() <= XVideo)
1358  {
1359  vbuffers.DiscardFrames(next_frame_keyframe);
1360  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1361  QString("DiscardFrames() 3: %1 -- done()")
1362  .arg(vbuffers.GetStatus()));
1363  return;
1364  }
1365 }
1366 
1373 {
1374  if (!frame)
1375  frame = vbuffers.GetScratchFrame();
1376 
1377  global_lock.lock();
1378  framesPlayed = frame->frameNumber + 1;
1379  global_lock.unlock();
1380 
1381  if (vbuffers.GetScratchFrame() == frame)
1383 }
1384 
1391 {
1392  if (!buffer)
1393  buffer = vbuffers.GetScratchFrame();
1394 
1395  framesPlayed = buffer->frameNumber + 1;
1396  int width = buffer->width;
1397  int height = buffer->height;
1398 
1399  // bad way to throttle frame display for non-Xv mode.
1400  // calculate fps we can do and skip enough frames so we don't exceed.
1401  if (non_xv_frames_shown == 0)
1402  non_xv_stop_time = time(nullptr) + 4;
1403 
1404  const QRect display_visible_rect = window.GetDisplayVisibleRect();
1405 
1406  if ((!non_xv_fps) && (time(nullptr) > non_xv_stop_time))
1407  {
1408  non_xv_fps = (int)(non_xv_frames_shown / 4);
1409 
1410  if (non_xv_fps < 25)
1411  {
1412  non_xv_show_frame = 120 / (non_xv_frames_shown + 1);
1413  LOG(VB_GENERAL, LOG_ERR, LOC +
1414  QString("\n***\n"
1415  "* Your system is not capable of displaying the\n"
1416  "* full framerate at %1""x%2 resolution. Frames\n"
1417  "* will be skipped in order to keep the audio and\n"
1418  "* video in sync.\n").arg(display_visible_rect.width())
1419  .arg(display_visible_rect.height()));
1420  }
1421  }
1422 
1424 
1426  return;
1427 
1428  if (!XJ_non_xv_image)
1429  {
1430  LOG(VB_GENERAL, LOG_ERR, LOC + "XJ_non_xv_image == nullptr");
1431  return;
1432  }
1433 
1434  int out_width = display_visible_rect.width() & ~0x1;
1435  int out_height = display_visible_rect.height() & ~0x1;
1436  AVFrame image_in, image_out;
1437 
1438  if ((out_width == width) &&
1439  (out_height == height))
1440  {
1441  m_copyFrame.Copy(&image_out, buffer);
1442  }
1443  else
1444  {
1445  static QMutex lock;
1446  static struct SwsContext *scontext = nullptr;
1447  int size = buffersize(FMT_YV12, out_width, out_height);
1448  unsigned char *sbuf = (unsigned char*)av_malloc(size);
1449 
1450  av_image_fill_arrays(image_out.data, image_out.linesize,
1451  sbuf, AV_PIX_FMT_YUV420P,
1452  out_width, out_height, IMAGE_ALIGN);
1453  AVPictureFill(&image_in, buffer);
1454  QMutexLocker locker(&lock);
1455  scontext = sws_getCachedContext(scontext, width, height,
1456  AV_PIX_FMT_YUV420P, out_width,
1457  out_height, AV_PIX_FMT_YUV420P,
1458  SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
1459 
1460  sws_scale(scontext, image_in.data, image_in.linesize, 0, height,
1461  image_out.data, image_out.linesize);
1462  }
1463 
1464  av_image_fill_arrays(image_in.data, image_in.linesize,
1465  (uint8_t *)XJ_non_xv_image->data,
1466  non_xv_av_format, out_width, out_height, IMAGE_ALIGN);
1467 
1468  m_copyFrame.Copy(&image_in, non_xv_av_format, &image_out, AV_PIX_FMT_YUV420P,
1469  out_width, out_height);
1470 
1471  {
1472  QMutexLocker locker(&global_lock);
1473  disp->Lock();
1474  if (XShm == video_output_subtype)
1475  XShmPutImage(disp->GetDisplay(), XJ_curwin, disp->GetGC(), XJ_non_xv_image,
1476  0, 0, 0, 0, out_width, out_height, False);
1477  else
1478  XPutImage(disp->GetDisplay(), XJ_curwin, disp->GetGC(), XJ_non_xv_image,
1479  0, 0, 0, 0, out_width, out_height);
1480  disp->Unlock();
1481  }
1482 
1483  av_freep(&image_out.data[0]);
1484 }
1485 
1486 // this is documented in videooutbase.cpp
1488  OSD *osd)
1489 {
1490  (void)osd;
1491  if (IsErrored())
1492  {
1493  LOG(VB_GENERAL, LOG_ERR, LOC + "IsErrored() in PrepareFrame()");
1494  return;
1495  }
1496 
1497  if (VideoOutputSubType() == XVideo)
1498  PrepareFrameXv(buffer);
1499  else
1500  PrepareFrameMem(buffer, scan);
1501 }
1502 
1503 static void calc_bob(FrameScanType scan, int imgh, int disphoff,
1504  int imgy, int dispyoff,
1505  int frame_height, int top_field_first,
1506  int &field, int &src_y, int &dest_y,
1507  int& xv_src_y_incr, int &xv_dest_y_incr)
1508 {
1509  int dst_half_line_in_src = 0, dest_y_incr = 0, src_y_incr = 0;
1510  field = 3;
1511  src_y = imgy;
1512  dest_y = dispyoff;
1513  xv_src_y_incr = 0;
1514 
1515  if ((kScan_Interlaced != scan) && (kScan_Intr2ndField != scan))
1516  return;
1517 
1518  // a negative offset y gives us bobbing, so adjust...
1519  if (dispyoff < 0)
1520  {
1521  dest_y_incr = -dispyoff;
1522  src_y_incr = dest_y_incr * imgh / disphoff;
1523  xv_src_y_incr -= (int) (0.5 * dest_y_incr * imgh / disphoff);
1524  }
1525 
1526  if ((scan == kScan_Interlaced && top_field_first == 1) ||
1527  (scan == kScan_Intr2ndField && top_field_first == 0))
1528  {
1529  field = 1;
1530  xv_src_y_incr += - imgy / 2;
1531  }
1532  else if ((scan == kScan_Interlaced && top_field_first == 0) ||
1533  (scan == kScan_Intr2ndField && top_field_first == 1))
1534  {
1535  field = 2;
1536  xv_src_y_incr += (frame_height - imgy) / 2;
1537 
1538  dst_half_line_in_src =
1539  max((int) round((((double)disphoff)/imgh) - 0.00001), 0);
1540  }
1541  src_y += src_y_incr;
1542  dest_y += dest_y_incr;
1543 
1544 #define NVIDIA_6629
1545 #ifdef NVIDIA_6629
1546  xv_dest_y_incr = dst_half_line_in_src;
1547  // nVidia v 66.29, does proper compensation when imgh==frame_height
1548  // but we need to compensate when the difference is >= 5%
1549  if (frame_height>=(int)(imgh+(0.05*frame_height)) && 2==field)
1550  {
1551  //int nrml = (int) round((((double)disphoff)/frame_height) - 0.00001);
1552  int mod = -dst_half_line_in_src;
1553  dest_y += mod;
1554  xv_dest_y_incr -= mod;
1555  }
1556 #else
1557  dest_y += dst_half_line_in_src;
1558 #endif
1559 
1560  // DEBUG
1561 #if 0
1562  static int last_dest_y_field[3] = { -1000, -1000, -1000, };
1563  int last_dest_y = last_dest_y_field[field];
1564 
1565  if (last_dest_y != dest_y)
1566  {
1567  LOG(VB_GENERAL, LOG_DEBUG,
1568  QString("####### Field %1 #######").arg(field));
1569  LOG(VB_GENERAL, LOG_DEBUG, QString(" src_y: %1").arg(src_y));
1570  LOG(VB_GENERAL, LOG_DEBUG, QString(" dest_y: %1").arg(dest_y));
1571  LOG(VB_GENERAL, LOG_DEBUG,
1572  QString(" xv_src_y_incr: %1").arg(xv_src_y_incr));
1573  LOG(VB_GENERAL, LOG_DEBUG,
1574  QString("xv_dest_y_incr: %1").arg(xv_dest_y_incr));
1575  LOG(VB_GENERAL, LOG_DEBUG, QString(" disphoff: %1").arg(disphoff));
1576  LOG(VB_GENERAL, LOG_DEBUG, QString(" imgh: %1").arg(imgh));
1577  LOG(VB_GENERAL, LOG_DEBUG, QString(" mod: %1").arg(mod));
1578  }
1579  last_dest_y_field[field] = dest_y;
1580 #endif
1581 }
1582 
1584 {
1585  VideoFrame *frame = GetLastShownFrame();
1586 
1587  XvImage *image = (XvImage*) xv_buffers[frame->buf];
1588  if (!image)
1589  return;
1590 
1591  const QRect video_rect = window.GetVideoRect();
1592  const QRect display_video_rect = (vsz_enabled && chroma_osd) ?
1595  int field = 3, src_y = video_rect.top(), dest_y = display_video_rect.top();
1596  if (m_deinterlacing && (m_deintfiltername == "bobdeint"))
1597  {
1598  int xv_src_y_incr = 0, xv_dest_y_incr = 0;
1599  calc_bob(scan,
1600  video_rect.height(), display_video_rect.height(),
1601  video_rect.top(), display_video_rect.top(),
1602  frame->height, frame->top_field_first,
1603  field, src_y, dest_y, xv_src_y_incr, xv_dest_y_incr);
1604  src_y += xv_src_y_incr;
1605  dest_y += xv_dest_y_incr;
1606  }
1607 
1608  {
1609  QMutexLocker locker(&global_lock);
1610  int video_height = (3 != field) ?
1611  (video_rect.height()/2) : video_rect.height();
1612  disp->Lock();
1613  XvShmPutImage(disp->GetDisplay(), xv_port, XJ_curwin,
1614  disp->GetGC(), image,
1615  video_rect.left(), src_y,
1616  video_rect.width(), video_height,
1617  display_video_rect.left(), dest_y,
1618  display_video_rect.width(),
1619  display_video_rect.height(), False);
1620  disp->Unlock();
1621  }
1622 }
1623 
1624 // this is documented in videooutbase.cpp
1626 {
1627  if (IsErrored())
1628  {
1629  LOG(VB_GENERAL, LOG_ERR, LOC + "IsErrored() is true in Show()");
1630  return;
1631  }
1632 
1635  {
1636  DrawUnusedRects(/* don't do a sync*/false);
1637  }
1638 
1639  if (VideoOutputSubType() == XVideo)
1640  ShowXVideo(scan);
1641 
1642  disp->Sync();
1643 }
1644 
1646 {
1647  // boboff assumes the smallest interlaced resolution is 480 lines - 5%
1648  bool use_bob = (m_deinterlacing && m_deintfiltername == "bobdeint");
1649  const QRect display_visible_rect = window.GetDisplayVisibleRect();
1650  const QRect display_video_rect = window.GetDisplayVideoRect();
1651  int boboff_raw = (int)round(((double)display_video_rect.height()) /
1652  456 - 0.00001);
1653  int boboff = use_bob ? boboff_raw : 0;
1654 
1656 
1657  Display *d = disp->GetDisplay();
1659  {
1660  XLOCK(disp, XShmPutImage(d, XJ_curwin, disp->GetGC(),
1661  chroma_osd->GetImage(), 0, 0, 0, 0,
1662  display_visible_rect.width(),
1663  display_visible_rect.height(), False));
1664  if (sync)
1665  disp->Sync();
1666 
1667  window.SetNeedRepaint(false);
1668  xv_need_bobdeint_repaint = false;
1669  return;
1670  }
1671 
1673  {
1676  QRect(display_visible_rect.left(),
1677  display_visible_rect.top() + boboff,
1678  display_visible_rect.width(),
1679  display_visible_rect.height() - 2 * boboff));
1680  }
1682  {
1683  // if this is only for deinterlacing mode switching, draw
1684  // the border areas, presumably the main image is undamaged.
1687  QRect(display_visible_rect.left(),
1688  display_visible_rect.top(),
1689  display_visible_rect.width(),
1690  boboff_raw));
1692  QRect(display_visible_rect.left(),
1693  display_visible_rect.height() - 2 * boboff_raw,
1694  display_visible_rect.width(),
1695  display_visible_rect.height()));
1696  }
1697 
1698  window.SetNeedRepaint(false);
1699  xv_need_bobdeint_repaint = false;
1700 
1701  // Set colour for masked areas
1703 
1704  if (display_video_rect.left() > display_visible_rect.left())
1705  { // left
1707  QRect(display_visible_rect.left(),
1708  display_visible_rect.top(),
1709  display_video_rect.left() - display_visible_rect.left(),
1710  display_visible_rect.height()));
1711  }
1712  if (display_video_rect.left() + display_video_rect.width() <
1713  display_visible_rect.left() + display_visible_rect.width())
1714  { // right
1716  QRect(display_video_rect.left() + display_video_rect.width(),
1717  display_visible_rect.top(),
1718  (display_visible_rect.left() +
1719  display_visible_rect.width()) -
1720  (display_video_rect.left() +
1721  display_video_rect.width()),
1722  display_visible_rect.height()));
1723  }
1724  if (display_video_rect.top() + boboff > display_visible_rect.top())
1725  { // top of screen
1727  QRect(display_visible_rect.left(),
1728  display_visible_rect.top(),
1729  display_visible_rect.width(),
1730  display_video_rect.top() + boboff -
1731  display_visible_rect.top()));
1732  }
1733  if (display_video_rect.top() + display_video_rect.height() <
1734  display_visible_rect.top() + display_visible_rect.height())
1735  { // bottom of screen
1737  QRect(display_visible_rect.left(),
1738  display_video_rect.top() + display_video_rect.height(),
1739  display_visible_rect.width(),
1740  (display_visible_rect.top() +
1741  display_visible_rect.height()) -
1742  (display_video_rect.top() +
1743  display_video_rect.height())));
1744  }
1745 
1746  if (sync)
1747  disp->Sync();
1748 }
1749 
1750 // documented in videooutbase.cpp
1752 {
1753  QMutexLocker locker(&global_lock);
1755 }
1756 
1757 void VideoOutputXv::UpdatePauseFrame(int64_t &disp_timecode)
1758 {
1759  QMutexLocker locker(&global_lock);
1760 
1761  LOG(VB_PLAYBACK, LOG_INFO, LOC + "UpdatePauseFrame() " +
1762  vbuffers.GetStatus());
1763 
1764  if (VideoOutputSubType() <= XVideo)
1765  {
1766  // Try used frame first, then fall back to scratch frame.
1768 
1769  VideoFrame *used_frame = nullptr;
1770  if (vbuffers.Size(kVideoBuffer_used) > 0)
1771  used_frame = vbuffers.Head(kVideoBuffer_used);
1772 
1773  if (used_frame)
1774  CopyFrame(&av_pause_frame, used_frame);
1775 
1776  vbuffers.end_lock();
1777 
1778  if (!used_frame)
1779  {
1782  }
1783 
1784  disp_timecode = av_pause_frame.disp_timecode;
1785  }
1786 }
1787 
1789  FilterChain *filterList,
1790  const PIPMap &pipPlayers,
1792 {
1793  if (IsErrored())
1794  {
1795  LOG(VB_GENERAL, LOG_ERR, LOC + "IsErrored() in ProcessFrame()");
1796  return;
1797  }
1798 
1799  bool deint_proc = m_deinterlacing && (m_deintFilter != nullptr);
1800  bool pauseframe = false;
1801  if (!frame)
1802  {
1803  frame = vbuffers.GetScratchFrame();
1804  vector<const VideoFrame*> locks;
1805  locks.push_back(frame);
1806  locks.push_back(&av_pause_frame);
1807  CopyFrame(frame, &av_pause_frame);
1808  pauseframe = true;
1809  }
1810 
1811  CropToDisplay(frame);
1812 
1813  bool safepauseframe = pauseframe && !IsBobDeint();
1814  if (!pauseframe || safepauseframe)
1815  {
1816  if (filterList)
1817  filterList->ProcessFrame(frame);
1818 
1819  if (deint_proc && m_deinterlaceBeforeOSD)
1820  m_deintFilter->ProcessFrame(frame, scan);
1821  }
1822 
1823  ShowPIPs(frame, pipPlayers);
1824 
1825  if (osd && !window.IsEmbedding())
1826  {
1827  if (!chroma_osd)
1828  DisplayOSD(frame, osd);
1829  else
1830  {
1831  QMutexLocker locker(&global_lock);
1834  }
1835  }
1836 
1837  if ((!pauseframe || safepauseframe) &&
1838  deint_proc && !m_deinterlaceBeforeOSD)
1839  {
1840  m_deintFilter->ProcessFrame(frame, scan);
1841  }
1842 }
1843 
1844 // this is documented in videooutbase.cpp
1846  PictureAttribute attribute, int newValue)
1847 {
1848  newValue = videoColourSpace.SetPictureAttribute(attribute, newValue);
1849  if (newValue >= 0)
1850  newValue = SetXVPictureAttribute(attribute, newValue);
1851  return newValue;
1852 }
1853 
1855 {
1856  QString attrName = toXVString(attribute);
1857  QByteArray ascii_attr_name = attrName.toLatin1();
1858  const char *cname = ascii_attr_name.constData();
1859 
1860  if (attrName.isEmpty())
1861  {
1862  LOG(VB_GENERAL, LOG_ERR, "\n\n\n attrName.isEmpty() \n\n\n");
1863  return -1;
1864  }
1865 
1866  int port_min = xv_attribute_min[attribute];
1867  int port_max = xv_attribute_max[attribute];
1868  int port_def = xv_attribute_def[attribute];
1869  int range = port_max - port_min;
1870 
1871  int valAdj = (kPictureAttribute_Hue == attribute) ? xv_hue_base : 0;
1872 
1873  if (xv_set_defaults && range && (kPictureAttribute_Hue == attribute))
1874  {
1875  float tmp = (((float)(port_def - port_min) / (float)range) * 100.0f);
1876  valAdj = lroundf(tmp);
1877  }
1878 
1879  int tmpval2 = (newValue + valAdj) % 100;
1880  int tmpval3 = (int) roundf(range * 0.01f * tmpval2);
1881  int value = min(tmpval3 + port_min, port_max);
1882 
1883  xv_set_attrib(disp, xv_port, cname, value);
1884 
1885  return newValue;
1886 }
1887 
1889 {
1891 
1892  if (VideoOutputSubType() >= XVideo)
1893  {
1894  if (xv_set_defaults)
1895  {
1896  QByteArray ascii_name = "XV_SET_DEFAULTS";
1897  const char *name = ascii_name.constData();
1899  }
1900 
1901  int val, min_val, max_val;
1902  for (uint i = 0; i < kPictureAttribute_MAX; i++)
1903  {
1904  QString attrName = toXVString((PictureAttribute)i);
1905  QByteArray ascii_attr_name = attrName.toLatin1();
1906  const char *cname = ascii_attr_name.constData();
1907 
1908  if (attrName.isEmpty())
1909  continue;
1910 
1911  if (xv_is_attrib_supported(disp, xv_port, cname,
1912  &val, &min_val, &max_val))
1913  {
1914  supported = (PictureAttributeSupported)
1915  (supported | toMask((PictureAttribute)i));
1916  xv_attribute_min[(PictureAttribute)i] = min_val;
1917  xv_attribute_max[(PictureAttribute)i] = max_val;
1919  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("%1: %2:%3:%4")
1920  .arg(cname).arg(min_val).arg(val).arg(max_val));
1923  }
1924  }
1925 
1927  }
1928 }
1929 
1931  MythPlayer *pipplayer,
1932  bool do_pixel_adj) const
1933 {
1934  (void)do_pixel_adj;
1935 
1936  if (!pipplayer || !pipplayer->UsingNullVideo())
1937  return VideoOutput::GetPIPRect(location, pipplayer);
1938 
1939  QRect position;
1940  const QSize video_disp_dim = window.GetVideoDispDim();
1941  const QRect video_rect = window.GetVideoRect();
1942  const QRect display_video_rect = window.GetDisplayVideoRect();
1943  const QRect display_visible_rect = window.GetDisplayVisibleRect();
1944  float video_aspect = window.GetVideoAspect();
1945  if (video_aspect < 0.01f)
1946  video_aspect = 1.3333f;
1947 
1948  const float pip_size = (float)window.GetPIPSize();
1949  const float pipVideoAspect = pipplayer->GetVideoAspect();
1950 
1951  // adjust for aspect override modes...
1952  int letterXadj = 0;
1953  int letterYadj = 0;
1954  float letterAdj = 1.0f;
1956  {
1957  letterXadj = max(-display_video_rect.left(), 0);
1958  float xadj = (float)video_rect.width() / display_visible_rect.width();
1959  letterXadj = (int)(letterXadj * xadj);
1960  float yadj = (float)video_rect.height() / display_visible_rect.height();
1961  letterYadj = max(-display_video_rect.top(), 0);
1962  letterYadj = (int)(letterYadj * yadj);
1963  letterAdj = window.GetVideoAspect() /
1965  }
1966  // adjust for the relative aspect ratios of pip and main video
1967  float aspectAdj = pipVideoAspect / video_aspect;
1968 
1969  int tmph = (int) ((float)video_disp_dim.height() * pip_size * 0.01f);
1970  int tmpw = (int) ((float)video_disp_dim.width() * pip_size * 0.01f *
1971  aspectAdj * letterAdj);
1972  position.setWidth((tmpw >> 1) << 1);
1973  position.setHeight((tmph >> 1) << 1);
1974 
1975  int xoff = 30;
1976  int yoff = 40;
1977 
1978  switch (location)
1979  {
1980  default:
1981  case kPIPTopLeft:
1982  xoff += letterXadj;
1983  yoff += letterYadj;
1984  break;
1985  case kPIPBottomLeft:
1986  xoff += letterXadj;
1987  yoff = video_disp_dim.height() - position.height() -
1988  yoff - letterYadj;
1989  break;
1990  case kPIPTopRight:
1991  xoff = video_disp_dim.width() - position.width() -
1992  xoff - letterXadj;
1993  yoff = yoff + letterYadj;
1994  break;
1995  case kPIPBottomRight:
1996  xoff = video_disp_dim.width() - position.width() -
1997  xoff - letterXadj;
1998  yoff = video_disp_dim.height() - position.height() -
1999  yoff - letterYadj;
2000  break;
2001  }
2002 
2003  position.translate(xoff, yoff);
2004  return position;
2005 }
2006 
2008  MythCodecID myth_codec_id, const QSize &video_dim)
2009 {
2010  (void) video_dim;
2011 
2012  QStringList list;
2013 
2015 
2016  if (!disp)
2017  return list;
2018 
2019  list = allowed_video_renderers(myth_codec_id, disp);
2020 
2021  delete disp;
2022  return list;
2023 }
2024 
2026 {
2027  if (chroma_osd)
2028  return chroma_osd->GetPainter();
2029 
2030  return VideoOutput::GetOSDPainter();
2031 }
2032 
2033 static void SetFromEnv(bool &useXVideo, bool &useShm)
2034 {
2035  // can be used to force non-Xv mode as well as non-Xv/non-Shm mode
2036  if (getenv("NO_XV"))
2037  useXVideo = false;
2038  if (getenv("NO_SHM"))
2039  useXVideo = useShm = false;
2040 }
2041 
2042 static void SetFromHW(MythXDisplay *d, Window curwin,
2043  bool &useXVideo, bool &useShm)
2044 {
2045  (void)d;
2046  (void)curwin;
2047 
2048  if (!d)
2049  return;
2050 
2051  MythXLocker lock(d);
2052 
2053  // find out about XVideo support
2054  if (useXVideo)
2055  {
2056  uint p_ver, p_rel, p_req, p_event, p_err, ret;
2057  ret = XvQueryExtension(d->GetDisplay(), &p_ver, &p_rel,
2058  &p_req, &p_event, &p_err);
2059  if (Success != ret)
2060  {
2061  LOG(VB_GENERAL, LOG_ERR, LOC +
2062  "XVideo output requested, but is not supported by display.");
2063  useXVideo = false;
2064  }
2065  }
2066 
2067  if (useShm)
2068  {
2069  const char *dispname = DisplayString(d->GetDisplay());
2070  if ((dispname) && (*dispname == ':'))
2071  useShm = (bool) XShmQueryExtension(d->GetDisplay());
2072  }
2073 }
2074 
2075 static QStringList allowed_video_renderers(
2076  MythCodecID myth_codec_id, MythXDisplay *display, Window curwin)
2077 {
2078  if (!curwin)
2079  curwin = display->GetRoot();
2080 
2081  bool xv = true;
2082  bool shm = true;
2083 
2084  myth2av_codecid(myth_codec_id);
2085 
2086  SetFromEnv(xv, shm);
2087  SetFromHW(display, curwin, xv, shm);
2088 
2089  QStringList list;
2090  if (codec_is_std(myth_codec_id))
2091  {
2092  if (xv)
2093  list += "xv-blit";
2094  if (shm)
2095  list += "xshm";
2096  list += "xlib";
2097  }
2098 
2099  return list;
2100 }
static DisplayRes * GetDisplayRes(bool lock=false)
Factory method that returns a DisplayRes singleton.
Definition: DisplayRes.cpp:18
virtual void ResizeForVideo(uint width=0, uint height=0)
Sets display parameters based on video resolution.
AVPixelFormat non_xv_av_format
Definition: videoout_xv.h:149
static void SetFromEnv(bool &useXV, bool &useShm)
static const uint kFeatureChromakey
bool CreateGC(Window win)
MythXDisplay * OpenMythXDisplay(void)
static int swap(VideoFrame *frame, int datasize, int offset, int shift)
Definition: filter_vflip.c:24
void save_port_attributes(int port)
Definition: util-xv.cpp:46
Display * GetDisplay(void)
Definition: mythxdisplay.h:21
QString m_deintfiltername
Definition: videooutbase.h:351
float GetVideoAspect(void) const
Definition: mythplayer.h:175
void SetVideoRenderer(const QString &video_renderer)
QMap< PictureAttribute, int > xv_attribute_max
Definition: videoout_xv.h:163
bool ProcessOSD(OSD *osd)
QMutex global_lock
Definition: videoout_xv.h:131
void DrawUnusedRects(bool sync=true) override
Draws non-video portions of the screen.
void SetDisplayAspect(float displayAspect)
static QStringList allowed_video_renderers(MythCodecID codec_id, MythXDisplay *display, Window curwin=0)
def scan(profile, smoonURL, gate)
Definition: scan.py:43
void ProcessFrame(VideoFrame *frame, OSD *osd, FilterChain *filterList, const PIPMap &pipPlayers, FrameScanType scan) override
vector< XShmSegmentInfo * > XJ_shm_infos
Definition: videoout_xv.h:141
void SetLastShownFrameToScratch(void)
QMap< MythPlayer *, PIPLocation > PIPMap
Definition: videooutbase.h:37
void Unlock(void)
Definition: mythxdisplay.h:24
ChromaKeyOSD * chroma_osd
Definition: videoout_xv.h:167
bool IsRepaintNeeded(void) const
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
int SetXVPictureAttribute(PictureAttribute attribute, int newValue)
virtual bool DisplayOSD(VideoFrame *frame, OSD *osd)
If the OSD has changed, this will convert the OSD buffer to the OSDSurface's color format.
int Copy(VideoFrame *dst, const VideoFrame *src)
Definition: mythavutil.cpp:196
QString GetStatus(int n=-1) const
LetterBoxColour db_letterbox_colour
Definition: videooutbase.h:325
PictureAttributeSupported
QString toString(MarkTypes type)
#define XLOCK(dpy, arg)
Definition: mythxdisplay.h:76
bool InitXShm(void)
Creates and initializes video buffers.
virtual bool IsBobDeint(void) const
bool m_deinterlacing
Definition: videooutbase.h:350
void InitColorKey(bool turnoffautopaint)
Initializes color keying support used by XVideo output methods.
MythCodecID
Definition: mythcodecid.h:10
VideoColourSpace videoColourSpace
Definition: videooutbase.h:322
bool InitXVideo(void)
Creates and initializes video buffers.
bool UsingNullVideo(void) const
Definition: mythplayer.h:232
bool CreateOSD(void)
struct AVFrame AVFrame
bool ApproveDeintFilter(const QString &filtername) const override
Approves bobdeint filter for XVideo and otherwise defers to VideoOutput::ApproveDeintFilter(const QSt...
QRect GetVideoRect(void) const
QString toXString(LetterBoxColour letterboxcolour)
XvAttributes()=default
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 ShowXVideo(FrameScanType scan)
#define LOC
Definition: videoout_xv.cpp:50
bool
Definition: pxsup2dast.c:30
static bool has_format(XvImageFormatValues *formats, int format_cnt, int id)
void CropToDisplay(VideoFrame *frame)
FrameScanType
Definition: videoouttypes.h:80
void del_open_xv_port(int port)
Definition: util-xv.cpp:114
int GrabSuitableXvPort(MythXDisplay *disp, Window root, MythCodecID type, uint width, uint height, bool &xvsetdefaults, QString *adaptor_name=nullptr)
Internal function used to grab a XVideo port with the desired properties.
This file is intended to hold X11 specific utility functions.
Definition: mythxdisplay.h:16
void Lock(void)
Definition: mythxdisplay.h:23
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.
virtual void StopEmbedding(void)
Tells video output to stop embedding video in an existing window.
MythXDisplay * disp
Definition: videoout_xv.h:136
friend class ChromaKeyOSD
Definition: videoout_xv.h:30
static const uint kFeaturePicCtrl
VideoFrame av_pause_frame
Definition: videoout_xv.h:140
void ProcessFrame(VideoFrame *Frame, FrameScanType scan=kScan_Ignore)
bool StopLog(void)
unsigned long GetBlack(void) const
Definition: mythxdisplay.h:28
const char * formats[8]
Definition: vbilut.cpp:190
QString xvflags2str(int flags)
Definition: util-xv.cpp:138
VideoDisplayProfile * db_vdisp_profile
Definition: videooutbase.h:330
bool SetDeinterlacingEnabled(bool) override
Attempts to enable/disable deinterlacing using existing deinterlace method when enabling.
uint Size(BufferType type) const
static guint32 * tmp
Definition: goom_core.c:35
vector< unsigned char * > CreateShmImages(uint num, bool use_xv)
Creates Shared Memory Images.
void restore_port_attributes(int port, bool clear)
Definition: util-xv.cpp:73
void Sync(bool flush=false)
unsigned char * qscale_table
Definition: mythframe.h:54
static const uint kFeatureNone
virtual void EmbedInWidget(const QRect &rect)
Tells video output to embed video in an existing window.
bool xv_use_picture_controls
Definition: videoout_xv.h:161
bool xv_is_attrib_supported(MythXDisplay *disp, int port, const char *name, int *current_value, int *min_value, int *max_value)
Definition: util-xv.cpp:154
VOSType video_output_subtype
Definition: videoout_xv.h:130
static void UngrabXvPort(MythXDisplay *disp, int port)
Internal function used to release an XVideo port.
#define round(x)
Definition: videoout_xv.cpp:65
int GetScreen(void) const
Definition: mythxdisplay.h:22
#define GUID_YV12_PLANAR
Definition: fourcc.h:71
unsigned char b
Definition: ParseText.cpp:340
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:109
long long framesPlayed
Definition: videooutbase.h:361
static MythCodecID GetBestSupportedCodec(uint stream_type)
bool CreateBuffers(VideoFrameType type, int width, int height, vector< unsigned char * > bufs, vector< YUVInfo > yuvinfo)
#define IMAGE_ALIGN
Definition: mythconfig.h:19
unsigned long XJ_letterbox_colour
Definition: videoout_xv.h:137
Window XJ_curwin
Definition: videoout_xv.h:135
virtual void ShowPIPs(VideoFrame *frame, const PIPMap &pipPlayers)
enum VideoOutputSubType VOSType
void MoveResizeWindow(QRect new_rect) override
This class serves as the base class for all video output methods.
Definition: videooutbase.h:46
static QStringList GetAllowedRenderers(MythCodecID myth_codec_id, const QSize &video_dim)
bool Init(const QSize &video_dim_buf, const QSize &video_dim_disp, float aspect, WId winid, const QRect &win_rect, MythCodecID codec_id) override
Initializes class for video output.
bool SetupDeinterlace(bool interlaced, const QString &overridefilter="") override
Attempts to enable or disable deinterlacing.
static void CopyFrame(VideoFrame *to, const VideoFrame *from)
Copies frame data from one VideoFrame to another.
void PrepareFrame(VideoFrame *, FrameScanType, OSD *osd) override
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
void PrepareFrameMem(VideoFrame *, FrameScanType)
VideoBuffers vbuffers
VideoBuffers instance used to track video output buffers.
Definition: videooutbase.h:357
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:830
void CreatePauseFrame(VOSType subtype)
Creates an extra frame for pause.
int GetDepth(void) const
Definition: mythxdisplay.h:25
int height
Definition: mythframe.h:42
void UpdatePauseFrame(int64_t &default_tc) override
Updates frame displayed when video is paused.
MythCodecID video_codec_id
Definition: videooutbase.h:329
void MoveResizeWin(Window win, const QRect &rect)
static const uint16_t * d
VideoErrorState errorState
Definition: videooutbase.h:360
QRect GetTmpDisplayVisibleRect(void) const
void SetNeedRepaint(bool needRepaint)
void PrepareFrameXv(VideoFrame *)
bool CreateBuffers(VOSType subtype)
void InitDisplayMeasurements(uint width, uint height, bool resize)
Init display measurements based on database settings and actual screen parameters.
void StartLog(void)
bool IsEmbedding(void) const
Returns if videooutput is embedding.
bool xv_get_attrib(MythXDisplay *disp, int port, const char *name, int &val)
Definition: util-xv.cpp:220
long long frameNumber
Definition: mythframe.h:48
void end_lock()
Definition: videobuffers.h:100
QString toXVString(PictureAttribute pictureattribute)
int non_xv_show_frame
Definition: videoout_xv.h:147
PictureAttribute
Definition: videoouttypes.h:89
QRect vsz_desired_display_rect
Definition: videooutbase.h:343
MythPainter * GetOSDPainter(void) override
QSize GetVideoDispDim(void) const
void VideoAspectRatioChanged(float aspect) override
Calls SetVideoAspectRatio(float aspect), then calls MoveResize() to apply changes.
XImage * XJ_non_xv_image
Definition: videoout_xv.h:145
time_t non_xv_stop_time
Definition: videoout_xv.h:150
XvAttributes(const QString &a, uint b, uint c)
QRect GetDisplayVideoRect(void) const
int top_field_first
1 if top field is first.
Definition: mythframe.h:58
void SetInput(const QSize &size, float framerate=0, const QString &codecName=QString())
const char * name
Definition: ParseText.cpp:339
void SetForeground(unsigned long color)
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:99
void ClearAfterSeek(void) override
Tells video output to toss decoded buffers due to a seek.
bool IsErrored() const
Returns true if a fatal error has been encountered.
Definition: videooutbase.h:179
void * av_malloc(unsigned int size)
bool vsz_enabled
Definition: videooutbase.h:342
QMap< PictureAttribute, int > xv_attribute_def
Definition: videoout_xv.h:164
#define XV_INIT_FATAL_ERROR_TEST(test, msg)
static void calc_bob(FrameScanType scan, int imgh, int disphoff, int imgy, int dispyoff, int frame_height, int top_field_first, int &field, int &src_y, int &dest_y, int &xv_src_y_incr, int &xv_dest_y_incr)
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...
PIPState GetPIPState(void) const
int myth2av_codecid(MythCodecID codec_id, bool &vdpau)
DisplayRes * display_res
Definition: videooutbase.h:364
PIPLocation
Definition: videoouttypes.h:19
VideoFrame * GetScratchFrame(void)
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.
void StopEmbedding(void) override
Tells video output to stop embedding video in an existing window.
QSize GetActualVideoDim(void) const
static int CalcHueBase(const QString &adaptor_name)
PictureAttributeSupported toMask(PictureAttribute pictureattribute)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
buffer_map_t xv_buffers
Definition: videoout_xv.h:159
static void SetFromHW(MythXDisplay *d, Window curwin, bool &useXV, bool &useShm)
int64_t disp_timecode
Definition: mythframe.h:50
QSize monitor_dim
Definition: videooutbase.h:368
void DiscardFrame(VideoFrame *frame)
Frame is ready to be reused by decoder.
void DiscardFrame(VideoFrame *) override
Frame is ready to be reused by decoder added to the done or available list.
bool GetBoolSetting(const QString &key, bool defaultval=false)
virtual bool ApproveDeintFilter(const QString &filtername) const
Approves bobdeint filter for XVideo and otherwise defers to VideoOutput::ApproveDeintFilter(const QSt...
int SetPictureAttribute(PictureAttribute attribute, int newValue) override
Sets a specified picture attribute.
static void GetRenderOptions(render_opts &opts, QStringList &cpudeints)
Definition: videoout_xv.cpp:80
QSize monitor_sz
Definition: videooutbase.h:367
void EmbedInWidget(const QRect &rect) override
Tells video output to embed video in an existing window.
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
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.
bool xv_need_bobdeint_repaint
Definition: videoout_xv.h:160
virtual void Zoom(ZoomDirection direction)
Sets up zooming into to different parts of the video, the zoom is actually applied in MoveResize().
void SetSupportedAttributes(PictureAttributeSupported supported)
void Show(FrameScanType) override
QMap< PictureAttribute, int > xv_attribute_min
Definition: videoout_xv.h:162
virtual void MoveResize(void)
performs all the calculations for video framing and any resizing.
float GetOverridenVideoAspect(void) const
vector< YUVInfo > XJ_yuv_infos
Definition: videoout_xv.h:142
void SetDisplayDim(QSize displayDim)
long long non_xv_frames_shown
Definition: videoout_xv.h:146
void MoveResize(void) override
performs all the calculations for video framing and any resizing.
bool xv_set_attrib(MythXDisplay *disp, int port, const char *name, int val)
Definition: util-xv.cpp:204
Definition: osd.h:132
#define GUID_I420_PLANAR
Definition: fourcc.h:69
float GetVideoAspect(void) const
bool InitVideoBuffers(bool use_xv, bool use_shm)
Creates and initializes video buffers.
QRect GetDisplayVisibleRect(void) const
FilterChain * m_deintFilter
Definition: videooutbase.h:353
QString GetVideoRenderer(void) const
void WindowResized(const QSize &new_size) override
void SetAllowPreviewEPG(bool allowPreviewEPG)
MythAVCopy m_copyFrame
Definition: videooutbase.h:382
static QString toCommaList(const QStringList &list)
QSize GetVideoDim(void) const
VOSType VideoOutputSubType() const
Definition: videoout_xv.h:97
bool add_open_xv_port(MythXDisplay *disp, int port)
Definition: util-xv.cpp:96
int GetPIPSize(void) const
MythPainter * GetPainter(void)
Definition: osdchromakey.h:24
bool InitSetupBuffers(void)
static uint buffersize(VideoFrameType type, int width, int height, int _aligned=64)
Definition: mythframe.h:291
QString description
VideoOutWindow window
Definition: videooutbase.h:320
bool InitXlib(void)
Creates and initializes video buffers.
virtual MythPainter * GetOSDPainter(void)
Definition: videooutbase.h:268
int GetPictureAttribute(PictureAttribute attribute)
bool m_deinterlaceBeforeOSD
Definition: videooutbase.h:354
void Zoom(ZoomDirection direction) override
Sets up zooming into to different parts of the video, the zoom is actually applied in MoveResize().
const char * vr_str[]
Definition: videoout_xv.cpp:75
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.
frame_queue_t::iterator begin_lock(BufferType)
void DeleteBuffers(VOSType subtype, bool delete_pause_frame)
void FillRectangle(Window win, const QRect &rect)
void DiscardFrames(bool next_frame_keyframe)
Mark all used frames as ready to be reused, this is for seek.
GC GetGC(void) const
Definition: mythxdisplay.h:27
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
void InitPictureAttributes(void) override
bool xv_draw_colorkey
Definition: videoout_xv.h:156
virtual bool SetDeinterlacingEnabled(bool)
Attempts to enable/disable deinterlacing using existing deinterlace method when enabling.
void DeleteBuffers(void)
bool xv_set_defaults
Definition: videoout_xv.h:158
void SetDisplayVisibleRect(QRect rect)
int XShmQueryExtension(Display *)
int SetPictureAttribute(PictureAttribute attribute, int value)
#define codec_is_std(id)
Definition: mythcodecid.h:112
XImage * GetImage()
Definition: osdchromakey.h:23
int XShmGetEventBase(Display *)
Window GetRoot(void) const
Definition: mythxdisplay.h:26
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.
#define GUID_IYUV_PLANAR
bit equivalent to I420
Definition: fourcc.h:70
QRect GetPIPRect(PIPLocation location, MythPlayer *pipplayer=nullptr, bool do_pixel_adj=true) const override
returns QRect of PIP based on PIPLocation