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  : video_output_subtype(XVUnknown),
139  global_lock(QMutex::Recursive),
140 
141  XJ_win(0), XJ_curwin(0), disp(nullptr), XJ_letterbox_colour(0),
142  XJ_started(false),
143 
144  XJ_non_xv_image(nullptr), non_xv_frames_shown(0), non_xv_show_frame(1),
145  non_xv_fps(0), non_xv_av_format(AV_PIX_FMT_NB), non_xv_stop_time(0),
146 
147  xv_port(-1), xv_hue_base(0),
148  xv_colorkey(0), xv_draw_colorkey(false),
149  xv_chroma(0), xv_set_defaults(false),
150  xv_need_bobdeint_repaint(false),
151  xv_use_picture_controls(true),
152 
153  chroma_osd(nullptr)
154 {
155  LOG(VB_PLAYBACK, LOG_INFO, LOC + "ctor");
156  memset(&av_pause_frame, 0, sizeof(av_pause_frame));
157 
158  if (gCoreContext->GetBoolSetting("UseVideoModes", false))
160 }
161 
163 {
164  LOG(VB_PLAYBACK, LOG_INFO, LOC + "dtor");
165 
166  const QRect tmp_display_visible_rect =
168 
169  if (window.GetPIPState() == kPIPStandAlone &&
170  !tmp_display_visible_rect.isEmpty())
171  {
172  window.SetDisplayVisibleRect(tmp_display_visible_rect);
173  }
174 
175  if (XJ_started)
176  {
177  const QRect display_visible_rect = window.GetDisplayVisibleRect();
179  disp->FillRectangle(XJ_curwin, display_visible_rect);
180  m_deinterlacing = false;
181  }
182 
183  // Delete the video buffers
185 
186  // ungrab port...
187  if (xv_port >= 0 && XJ_started)
188  {
189  XLOCK(disp, XvStopVideo(disp->GetDisplay(), xv_port, XJ_curwin));
191  xv_port = -1;
192  }
193 
194  if (XJ_started)
195  {
196  XJ_started = false;
197  delete disp;
198  disp = nullptr;
199  }
200 }
201 
202 // this is documented in videooutbase.cpp
204 {
205  QMutexLocker locker(&global_lock);
206  VideoOutput::Zoom(direction);
207  MoveResize();
208 }
209 
210 // this is documented in videooutbase.cpp
212 {
213  QMutexLocker locker(&global_lock);
215  if (chroma_osd)
216  window.SetNeedRepaint(true);
217 }
218 
219 void VideoOutputXv::WindowResized(const QSize &new_size)
220 {
221  // This is causing problems in association with xrandr/display resolution
222  // switching. Disabling for 0.24 as this is the only videooutput class
223  // that implements this method
224  // see http://cvs.mythtv.org/trac/ticket/7408
225  QMutexLocker locker(&global_lock);
226 
227  window.SetDisplayVisibleRect(QRect(QPoint(0, 0), new_size));
228 
229  const QSize display_dim = QSize(
230  (monitor_dim.width() * new_size.width()) / monitor_sz.width(),
231  (monitor_dim.height() * new_size.height())/ monitor_sz.height());
232  window.SetDisplayDim(display_dim);
233 
235  ((float)display_dim.width()) / display_dim.height());
236 
237  MoveResize();
238 }
239 
240 // documented in videooutbase.cpp
241 bool VideoOutputXv::InputChanged(const QSize &video_dim_buf,
242  const QSize &video_dim_disp,
243  float aspect,
244  MythCodecID av_codec_id,
245  void *codec_private,
246  bool &aspect_only)
247 {
248  LOG(VB_PLAYBACK, LOG_INFO, LOC +
249  QString("InputChanged(%1,%2,%3) '%4'->'%5'")
250  .arg(video_dim_disp.width()).arg(video_dim_disp.height())
251  .arg(aspect)
252  .arg(toString(video_codec_id)).arg(toString(av_codec_id)));
253 
254  QMutexLocker locker(&global_lock);
255 
256  bool cid_changed = (video_codec_id != av_codec_id);
257  bool res_changed = video_dim_disp != window.GetActualVideoDim();
258  bool asp_changed = aspect != window.GetVideoAspect();
259 
260  if (!res_changed && !cid_changed)
261  {
262  aspect_only = true;
263  if (asp_changed)
264  {
265  VideoAspectRatioChanged(aspect);
266  MoveResize();
267  }
268  return true;
269  }
270 
271  VideoOutput::InputChanged(video_dim_buf, video_dim_disp,
272  aspect, av_codec_id, codec_private,
273  aspect_only);
274 
275  bool delete_pause_frame = cid_changed;
276  DeleteBuffers(VideoOutputSubType(), delete_pause_frame);
277 
278  const QSize video_disp_dim = window.GetVideoDispDim();
279  ResizeForVideo((uint) video_disp_dim.width(),
280  (uint) video_disp_dim.height());
281 
282  bool ok = true;
283  if (cid_changed)
284  {
285  // ungrab port...
286  if (xv_port >= 0)
287  {
289  xv_port = -1;
290  }
291 
292  ok = InitSetupBuffers();
293  }
294  else
295  {
297  }
298 
299  InitColorKey(true);
300  CreateOSD();
301 
302  MoveResize();
303 
304  if (!ok)
305  {
306  LOG(VB_GENERAL, LOG_ERR, LOC +
307  "InputChanged(): Failed to recreate buffers");
309  }
310 
311  return ok;
312 }
313 
315 {
316  if (disp)
317  disp->MoveResizeWin(XJ_win, new_rect);
318 }
319 
321 {
322  public:
323  XvAttributes() = default;
324  XvAttributes(const QString &a, uint b, uint c) :
325  description(a), xv_flags(b), feature_flags(c) {}
326 
327  public:
328  QString description;
331 
332  static const uint kFeatureNone = 0x00;
333  static const uint kFeatureChromakey = 0x01;
334  static const uint kFeaturePicCtrl = 0x02;
335 };
336 
341 {
342  if (!disp)
343  return;
344 
345  LOG(VB_PLAYBACK, LOG_INFO, LOC +
346  QString("Closing XVideo port %1").arg(port));
347  disp->Lock();
349  XvUngrabPort(disp->GetDisplay(), port, CurrentTime);
350  del_open_xv_port(port);
351  disp->Unlock();
352 }
353 
360  MythCodecID /*mcodecid*/,
361  uint width, uint height,
362  bool &xvsetdefaults,
363  QString *adaptor_name)
364 {
365  if (adaptor_name)
366  *adaptor_name = QString();
367 
368  // create list of requirements to check in order..
369  vector<XvAttributes> req;
370  req.push_back(XvAttributes(
371  "XVideo surface found on port %1",
372  XvInputMask | XvImageMask,
374 
375  // try to get an adapter with picture attributes
376  uint end = req.size();
377  for (uint i = 0; i < end; i++)
378  {
379  req.push_back(req[i]);
380  req[i].feature_flags |= XvAttributes::kFeaturePicCtrl;
381  }
382 
383  // figure out if we want chromakeying..
384  db_vdisp_profile->SetInput(QSize(width, height));
385  if (db_vdisp_profile->GetOSDRenderer() == "chromakey")
386  {
387  end = req.size();
388  for (uint i = 0; i < end; i++)
389  {
390  req.push_back(req[i]);
391  req[i].feature_flags |= XvAttributes::kFeatureChromakey;
392  }
393  }
394 
395  // get the list of Xv ports
396  XvAdaptorInfo *ai = nullptr;
397  uint p_num_adaptors = 0;
398  int ret = Success;
399  XLOCK(_disp, ret = XvQueryAdaptors(_disp->GetDisplay(), root,
400  &p_num_adaptors, &ai));
401  if (Success != ret)
402  {
403  LOG(VB_GENERAL, LOG_ERR, LOC +
404  "XVideo supported, but no free Xv ports found."
405  "\n\t\t\tYou may need to reload video driver.");
406  return -1;
407  }
408 
409  QString lastAdaptorName;
410  int port = -1;
411 
412  // find an Xv port
413  for (size_t j = 0; j < req.size(); ++j)
414  {
415  LOG(VB_PLAYBACK, LOG_INFO, LOC +
416  QString("@ j=%1 Looking for flag[s]: %2 %3")
417  .arg(j).arg(xvflags2str(req[j].xv_flags))
418  .arg(req[j].feature_flags,0,16));
419 
420  for (int i = 0; i < (int)p_num_adaptors && (port == -1); ++i)
421  {
422  lastAdaptorName = ai[i].name;
423  LOG(VB_PLAYBACK, LOG_INFO, LOC +
424  QString("Adaptor#%1: %2 has flag[s]: %3")
425  .arg(i).arg(lastAdaptorName).arg(xvflags2str(ai[i].type)));
426 
427  if ((ai[i].type & req[j].xv_flags) != req[j].xv_flags)
428  {
429  LOG(VB_PLAYBACK, LOG_ERR, LOC +
430  "Missing XVideo flags, rejecting.");
431  continue;
432  }
433  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Has XVideo flags...");
434 
435  const XvPortID firstPort = ai[i].base_id;
436  const XvPortID lastPort = ai[i].base_id + ai[i].num_ports - 1;
437  XvPortID p = 0;
438 
439  if ((req[j].feature_flags & XvAttributes::kFeaturePicCtrl) &&
440  (!xv_is_attrib_supported(_disp, firstPort, "XV_BRIGHTNESS")))
441  {
442  LOG(VB_PLAYBACK, LOG_ERR, LOC +
443  "Missing XV_BRIGHTNESS, rejecting.");
444  continue;
445  }
446  if (req[j].feature_flags & XvAttributes::kFeaturePicCtrl)
447  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Has XV_BRIGHTNESS...");
448 
449  if ((req[j].feature_flags & XvAttributes::kFeatureChromakey) &&
450  (!xv_is_attrib_supported(_disp, firstPort, "XV_COLORKEY")))
451  {
452  LOG(VB_PLAYBACK, LOG_ERR, LOC +
453  "Missing XV_COLORKEY, rejecting.");
454  continue;
455  }
456  if (req[j].feature_flags & XvAttributes::kFeatureChromakey)
457  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Has XV_COLORKEY...");
458 
459  for (p = firstPort; (p <= lastPort) && (port == -1); ++p)
460  {
461  _disp->Lock();
462  ret = XvGrabPort(_disp->GetDisplay(), p, CurrentTime);
463  if (Success == ret)
464  {
465  LOG(VB_PLAYBACK, LOG_INFO, LOC +
466  QString("Grabbed xv port %1").arg(p));
467  port = p;
468  xvsetdefaults = add_open_xv_port(_disp, p);
469  }
470  _disp->Unlock();
471  }
472  }
473 
474  if (port != -1)
475  {
476  LOG(VB_PLAYBACK, LOG_INFO, LOC + req[j].description.arg(port));
477  LOG(VB_PLAYBACK, LOG_INFO, LOC +
478  QString("XV_SET_DEFAULTS is %1supported on this port")
479  .arg(xvsetdefaults ? "" : "not "));
480 
481  bool xv_vsync = xv_is_attrib_supported(_disp, port,
482  "XV_SYNC_TO_VBLANK");
483  LOG(VB_PLAYBACK, LOG_INFO, LOC +
484  QString("XV_SYNC_TO_VBLANK %1supported")
485  .arg(xv_vsync ? "" : "not "));
486  if (xv_vsync)
487  {
488  LOG(VB_PLAYBACK, LOG_INFO, LOC +
489  QString("XVideo Sync to VBlank %1set")
490  .arg(xv_set_attrib(_disp, port, "XV_SYNC_TO_VBLANK", 1) ?
491  "" : "NOT "));
492  }
493 
494  break;
495  }
496  }
497 
498  if (port == -1)
499  LOG(VB_PLAYBACK, LOG_INFO, LOC + "No suitable XVideo port found");
500 
501  // free list of Xv ports
502  if (ai)
503  XLOCK(_disp, XvFreeAdaptorInfo(ai));
504 
505  if ((port != -1) && adaptor_name)
506  *adaptor_name = lastAdaptorName;
507 
508  return port;
509 }
510 
520 {
521  if (av_pause_frame.buf)
522  {
523  av_freep(&av_pause_frame.buf);
524  }
525 
526  int size = buffersize(FMT_YV12,
529  unsigned char* buf = (unsigned char*)av_malloc(size);
533  size);
534 
536 
538 }
539 
547 bool VideoOutputXv::InitVideoBuffers(bool use_xv, bool use_shm)
548 {
549  bool done = false;
550 
551  // Create ffmpeg VideoFrames
552  vbuffers.Init(31, true, 1, 12, 4, 2);
553 
554  // Fall back to XVideo if there is an xv_port
555  if (use_xv)
556  done = InitXVideo();
557 
558  // only HW accel allowed for PIP and PBP
559  if (!done && window.GetPIPState() > kPIPOff)
560  return done;
561 
562  // Fall back to shared memory, if we are allowed to use it
563  if (!done && use_shm)
564  done = InitXShm();
565 
566  // Fall back to plain old X calls
567  if (!done)
568  done = InitXlib();
569 
570  if (done)
572 
573  return done;
574 }
575 
576 static bool has_format(XvImageFormatValues *formats, int format_cnt, int id)
577 {
578  for (int i = 0; i < format_cnt; i++)
579  {
580  if (formats[i].id == id)
581  return true;
582  }
583 
584  return false;
585 }
586 
596 {
597  MythXLocker lock(disp);
598  disp->StartLog();
599  QString adaptor_name;
600  const QSize video_dim = window.GetVideoDim();
602  video_dim.width(), video_dim.height(),
603  xv_set_defaults, &adaptor_name);
604  if (xv_port == -1)
605  {
606  LOG(VB_GENERAL, LOG_ERR, LOC +
607  "Could not find suitable XVideo surface.");
608  return false;
609  }
610 
611  LOG(VB_GENERAL, LOG_INFO, LOC + QString("XVideo Adaptor Name: '%1'")
612  .arg(adaptor_name));
613 
614  xv_hue_base = VideoOutput::CalcHueBase(adaptor_name);
616  adaptor_name != "Intel(R) Video Overlay";
617 
618  bool foundimageformat = false;
620  int format_cnt = 0;
621  XvImageFormatValues *formats;
622  formats = XvListImageFormats(disp->GetDisplay(), xv_port, &format_cnt);
623 
624  for (int i = 0; i < format_cnt; i++)
625  {
626  char *chr = (char*) &(formats[i].id);
627  LOG(VB_PLAYBACK, LOG_INFO, LOC +
628  QString("XVideo Format #%1 is '%2%3%4%5'")
629  .arg(i).arg(chr[0]).arg(chr[1]).arg(chr[2]).arg(chr[3]));
630  }
631 
632  for (size_t i = 0; i < sizeof(ids)/sizeof(int); i++)
633  {
634  if (has_format(formats, format_cnt, ids[i]))
635  {
636  xv_chroma = ids[i];
637  foundimageformat = true;
638  break;
639  }
640  }
641 
642  // IYUV is bit identical to I420, just pretend we saw I420
644 
645  if (formats)
646  XFree(formats);
647 
648  if (foundimageformat)
649  {
650  char *chr = (char*) &xv_chroma;
651  LOG(VB_PLAYBACK, LOG_INFO, LOC +
652  QString("Using XVideo Format '%1%2%3%4'")
653  .arg(chr[0]).arg(chr[1]).arg(chr[2]).arg(chr[3]));
654  }
655  else
656  {
657  LOG(VB_GENERAL, LOG_ERR, LOC +
658  "Couldn't find the proper XVideo image format.");
660  xv_port = -1;
661  }
662 
663  bool ok = xv_port >= 0;
664  if (ok)
665  ok = CreateBuffers(XVideo);
666 
667  if (!disp->StopLog())
668  {
669  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create XVideo Buffers.");
670  DeleteBuffers(XVideo, false);
672  xv_port = -1;
673  ok = false;
674  }
675  else
676  {
679  }
680 
681  return ok;
682 }
683 
693 {
694  MythXLocker lock(disp);
695  disp->StartLog();
696 
697  LOG(VB_GENERAL, LOG_ERR, LOC +
698  "Falling back to X shared memory video output."
699  "\n\t\t\t *** May be slow ***");
700 
701  bool ok = CreateBuffers(XShm);
702 
703  if (!disp->StopLog())
704  {
705  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate X shared memory.");
706  DeleteBuffers(XShm, false);
707  ok = false;
708  }
709  else
710  {
712  window.SetAllowPreviewEPG(false);
713  }
714 
715  return ok;
716 }
717 
727 {
728  MythXLocker lock(disp);
729  disp->StartLog();
730 
731  LOG(VB_GENERAL, LOG_ERR, LOC +
732  "Falling back to X11 video output over a network socket."
733  "\n\t\t\t *** May be very slow ***");
734 
735  bool ok = CreateBuffers(Xlib);
736 
737  if (!disp->StopLog())
738  {
739  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create X buffers.");
740  DeleteBuffers(Xlib, false);
741  ok = false;
742  }
743  else
744  {
746  window.SetAllowPreviewEPG(false);
747  }
748 
749  return ok;
750 }
751 
756 {
757  return (MythCodecID)(kCodec_MPEG1 + (stream_type-1));
758 }
759 
761 {
762  QString osdrenderer = db_vdisp_profile->GetOSDRenderer();
763 
764  if (osdrenderer == "chromakey")
765  {
766  if ((xv_colorkey == (int)XJ_letterbox_colour) ||
768  {
769  LOG(VB_PLAYBACK, LOG_ERR, LOC +
770  "Disabling ChromaKeyOSD as colorkeying will not work.");
771  }
772  else if (!((32 == disp->GetDepth()) || (24 == disp->GetDepth())))
773  {
774  LOG(VB_GENERAL, LOG_ERR, LOC +
775  QString("Number of bits per pixel is %1, \n\t\t\t"
776  "but we only support ARGB 32 bbp for ChromaKeyOSD.")
777  .arg(disp->GetDepth()));
778  }
779  else
780  {
781  chroma_osd = new ChromaKeyOSD(this);
782  }
783  return chroma_osd;
784  }
785 
786  return true;
787 }
788 
789 #define XV_INIT_FATAL_ERROR_TEST(test,msg) \
790 do { \
791  if (test) \
792  { \
793  LOG(VB_GENERAL, LOG_ERR, LOC + (msg) + " Exiting playback."); \
794  errorState = kError_Unknown; \
795  return false; \
796  } \
797 } while (false)
798 
799 static QString toCommaList(const QStringList &list)
800 {
801  QString ret = "";
802  for (QStringList::const_iterator it = list.begin(); it != list.end(); ++it)
803  ret += *it + ",";
804 
805  if (ret.length())
806  return ret.left(ret.length()-1);
807 
808  return "";
809 }
810 
812 {
813  // Figure out what video renderer to use
815  QStringList renderers = allowed_video_renderers(
817  QString renderer;
818 
819  QString tmp1 = db_vdisp_profile->GetVideoRenderer();
820  LOG(VB_PLAYBACK, LOG_INFO, LOC + "InitSetupBuffers() " +
821  QString("render: %1, allowed: %2")
822  .arg(tmp1).arg(toCommaList(renderers)));
823 
824  if (renderers.contains(tmp1))
825  renderer = tmp1;
826  else if (renderers.empty())
827  XV_INIT_FATAL_ERROR_TEST(false, "Failed to find a video renderer");
828  else
829  {
830  QString tmp2;
831  QStringList::const_iterator it = renderers.begin();
832  for (; it != renderers.end(); ++it)
833  tmp2 += *it + ",";
834 
835  renderer = renderers[0];
836 
837  LOG(VB_GENERAL, LOG_ERR, LOC +
838  QString("Desired video renderer '%1' not available.\n\t\t\t"
839  "codec '%2' makes '%3' available, using '%4' instead.")
841  .arg(toString(video_codec_id)).arg(tmp2).arg(renderer));
843  }
844 
845  // Create video buffers
846  bool use_xv = (renderer.startsWith("xv"));
847  bool use_shm = (renderer == "xshm");
848  bool ok = InitVideoBuffers(use_xv, use_shm);
849 
850  if (!ok && window.GetPIPState() == kPIPOff)
851  {
852  use_xv |= renderers.contains("xv-blit");
853  use_shm |= renderers.contains("xshm");
854  ok = InitVideoBuffers(use_xv, use_shm);
855  }
856  XV_INIT_FATAL_ERROR_TEST(!ok, "Failed to get any video output");
857 
858  if (xv_port && (VideoOutputSubType() >= XVideo))
860 
861  // Initialize the picture controls if we need to..
864 
865  return true;
866 }
867 
874 bool VideoOutputXv::Init(const QSize &video_dim_buf,
875  const QSize &video_dim_disp,
876  float aspect,
877  WId winid, const QRect &win_rect, MythCodecID codec_id)
878 {
879  window.SetNeedRepaint(true);
880 
881  XV_INIT_FATAL_ERROR_TEST(winid <= 0, "Invalid Window ID.");
882 
884  XV_INIT_FATAL_ERROR_TEST(!disp, "Failed to open display.");
885 
886  // Initialize X stuff
887  MythXLocker lock(disp);
888 
889  XJ_curwin = winid;
890  XJ_win = winid;
891  XV_INIT_FATAL_ERROR_TEST(!disp->CreateGC(XJ_win), "Failed to create GC.");
892 
893  // The letterbox color..
895  Colormap cmap = XDefaultColormap(disp->GetDisplay(), disp->GetScreen());
896  XColor colour, colour_exact;
898  QByteArray ascii_name = name.toLatin1();
899  const char *cname = ascii_name.constData();
900  if (XAllocNamedColor(disp->GetDisplay(), cmap, cname, &colour, &colour_exact))
901  XJ_letterbox_colour = colour.pixel;
902 
903  XJ_started = true;
904 
905  // Basic setup
906  VideoOutput::Init(video_dim_buf, video_dim_disp,
907  aspect, winid, win_rect, codec_id);
908 
909  // Set resolution/measurements (check XRandR, Xinerama, config settings)
910  InitDisplayMeasurements(video_dim_disp.width(), video_dim_disp.height(),
911  true);
912 
913  if (!InitSetupBuffers())
914  return false;
915 
916  InitColorKey(true);
917  CreateOSD();
918 
919  MoveResize();
920 
921  return true;
922 }
923 #undef XV_INIT_FATAL_ERROR_TEST
924 
931 void VideoOutputXv::InitColorKey(bool turnoffautopaint)
932 {
934  return;
935 
936  static const char *attr_autopaint = "XV_AUTOPAINT_COLORKEY";
937  int xv_val=0;
938 
939  // handle autopaint.. Normally we try to disable it so that bob-deint
940  // doesn't actually bob up the top and bottom borders up and down...
941  xv_draw_colorkey = true;
942  if (xv_is_attrib_supported(disp, xv_port, attr_autopaint, &xv_val))
943  {
944  if (turnoffautopaint && xv_val)
945  {
946  xv_set_attrib(disp, xv_port, attr_autopaint, 0);
947  if (!xv_get_attrib(disp, xv_port, attr_autopaint, xv_val) ||
948  xv_val)
949  {
950  LOG(VB_GENERAL, LOG_ERR, "Failed to disable autopaint");
951  xv_draw_colorkey = false;
952  }
953  }
954  else if (!turnoffautopaint && !xv_val)
955  {
956  xv_set_attrib(disp, xv_port, attr_autopaint, 1);
957  if (!xv_get_attrib(disp, xv_port, attr_autopaint, xv_val) ||
958  !xv_val)
959  {
960  LOG(VB_GENERAL, LOG_ERR, "Failed to enable autopaint");
961  }
962  }
963  else if (!turnoffautopaint && xv_val)
964  {
965  xv_draw_colorkey = false;
966  }
967  }
968 
969  // Check that we have a colorkey attribute and make sure it is not
970  // the same color as the MythTV letterboxing (currently Black).
971  // This avoids avoid bob-deint actually bobbing the borders of
972  // the video up and down..
973  int letterbox_color = XJ_letterbox_colour;
974  static const char *attr_chroma = "XV_COLORKEY";
975  if (!xv_is_attrib_supported(disp, xv_port, attr_chroma, &xv_colorkey))
976  {
977  // set to MythTV letterbox color as a sentinel
978  xv_colorkey = letterbox_color;
979  }
980  else if (xv_colorkey == letterbox_color)
981  {
982  // if it is a valid attribute and set to the letterbox color, change it
983  xv_set_attrib(disp, xv_port, attr_chroma, 1);
984 
985  if (xv_get_attrib(disp, xv_port, attr_chroma, xv_val) &&
986  xv_val != letterbox_color)
987  {
988  xv_colorkey = xv_val;
989  }
990  }
991 
992  if (xv_colorkey == letterbox_color)
993  {
994  LOG(VB_PLAYBACK, LOG_INFO, LOC +
995  "Chromakeying not possible with this XVideo port.");
996  }
997 }
998 
999 // documented in videooutbase.cpp
1001 {
1002  bool deint = VideoOutput::SetDeinterlacingEnabled(enable);
1003  xv_need_bobdeint_repaint = (m_deintfiltername == "bobdeint");
1004  return deint;
1005 }
1006 
1007 bool VideoOutputXv::SetupDeinterlace(bool interlaced,
1008  const QString& overridefilter)
1009 {
1010  bool deint = VideoOutput::SetupDeinterlace(interlaced, overridefilter);
1011  window.SetNeedRepaint(true);
1012  return deint;
1013 }
1014 
1022 bool VideoOutputXv::ApproveDeintFilter(const QString &filtername) const
1023 {
1024  // TODO implement bobdeint for non-Xv
1025  VOSType vos = VideoOutputSubType();
1026 
1027  if (filtername == "bobdeint" && (vos >= XVideo))
1028  return true;
1029 
1030  return VideoOutput::ApproveDeintFilter(filtername);
1031 }
1032 
1044 vector<unsigned char*> VideoOutputXv::CreateShmImages(uint num, bool use_xv)
1045 {
1046  const QSize video_dim = window.GetVideoDim();
1047  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1048  QString("CreateShmImages(%1): video_dim: %2x%3")
1049  .arg(num).arg(video_dim.width()).arg(video_dim.height()));
1050 
1051  MythXLocker lock(disp);
1052  Display *d = disp->GetDisplay();
1053  vector<unsigned char*> bufs;
1054  for (uint i = 0; i < num; i++)
1055  {
1056  XShmSegmentInfo *info = new XShmSegmentInfo;
1057  void *image = nullptr;
1058  int size = 0;
1059  int desiredsize = 0;
1060 
1061  if (use_xv)
1062  {
1063  XvImage *img =
1064  XvShmCreateImage(d, xv_port, xv_chroma, nullptr,
1065  video_dim.width(), video_dim.height(), info);
1066  size = img->data_size + 64;
1067  image = img;
1068  desiredsize = video_dim.width() * video_dim.height() * 3 / 2;
1069 
1070  if (image && size < desiredsize)
1071  {
1072  LOG(VB_GENERAL, LOG_ERR, LOC + "CreateXvShmImages(): "
1073  "XvShmCreateImage() failed to create image of the "
1074  "requested size.");
1075  XFree(image);
1076  image = nullptr;
1077  delete info;
1078  }
1079 
1080  if (image && (3 == img->num_planes))
1081  {
1082  XJ_shm_infos.push_back(info);
1083  YUVInfo tmp(img->width, img->height, img->data_size,
1084  img->pitches, img->offsets);
1085  if (xv_chroma == GUID_YV12_PLANAR)
1086  {
1087  swap(tmp.m_pitches[1], tmp.m_pitches[2]);
1088  swap(tmp.m_offsets[1], tmp.m_offsets[2]);
1089  }
1090 
1091  XJ_yuv_infos.push_back(tmp);
1092  }
1093  else if (image)
1094  {
1095  LOG(VB_GENERAL, LOG_ERR, LOC + "CreateXvShmImages(): "
1096  "XvShmCreateImage() failed to create image "
1097  "with the correct number of pixel planes.");
1098  XFree(image);
1099  image = nullptr;
1100  delete info;
1101  }
1102  }
1103  else
1104  {
1105  int width = window.GetDisplayVisibleRect().width() & ~0x1;
1106  int height = window.GetDisplayVisibleRect().height() & ~0x1;
1107  XImage *img =
1108  XShmCreateImage(d, DefaultVisual(d, disp->GetScreen()),
1109  disp->GetDepth(), ZPixmap, nullptr, info,
1110  width, height);
1111  size = img->bytes_per_line * img->height + 64;
1112  image = img;
1113  desiredsize = (width * height * 3 / 2);
1114  if (image && size < desiredsize)
1115  {
1116  LOG(VB_GENERAL, LOG_ERR, LOC + "CreateXvShmImages(): "
1117  "XShmCreateImage() failed to create image of the "
1118  "requested size.");
1119  XDestroyImage((XImage *)image);
1120  image = nullptr;
1121  delete info;
1122  }
1123 
1124  if (image)
1125  {
1126  YUVInfo tmp(img->width, img->height,
1127  img->bytes_per_line * img->height, nullptr, nullptr);
1128  XJ_yuv_infos.push_back(tmp);
1129  XJ_shm_infos.push_back(info);
1130  }
1131  }
1132 
1133  if (image)
1134  {
1135  XJ_shm_infos[i]->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
1136  if (XJ_shm_infos[i]->shmid >= 0)
1137  {
1138  XJ_shm_infos[i]->shmaddr = (char*)
1139  shmat(XJ_shm_infos[i]->shmid, nullptr, 0);
1140  if (use_xv)
1141  ((XvImage*)image)->data = XJ_shm_infos[i]->shmaddr;
1142  else
1143  ((XImage*)image)->data = XJ_shm_infos[i]->shmaddr;
1144  xv_buffers[(unsigned char*) XJ_shm_infos[i]->shmaddr] = image;
1145  XJ_shm_infos[i]->readOnly = False;
1146 
1147  XShmAttach(d, XJ_shm_infos[i]);
1148  disp->Sync(); // needed for FreeBSD?
1149 
1150  // Mark for delete immediately.
1151  // It won't actually be removed until after we detach it.
1152  shmctl(XJ_shm_infos[i]->shmid, IPC_RMID, nullptr);
1153 
1154  bufs.push_back((unsigned char*) XJ_shm_infos[i]->shmaddr);
1155  }
1156  else
1157  {
1158  LOG(VB_GENERAL, LOG_ERR, LOC +
1159  "CreateXvShmImages(): shmget() failed." + ENO);
1160  break;
1161  }
1162  }
1163  else
1164  {
1165  LOG(VB_GENERAL, LOG_ERR, LOC + "CreateXvShmImages(): "
1166  "XvShmCreateImage() failed to create image.");
1167  break;
1168  }
1169  }
1170  return bufs;
1171 }
1172 
1174 {
1175  bool ok = false;
1176 
1177  const QSize video_dim = window.GetVideoDim();
1178  const QRect display_visible_rect = window.GetDisplayVisibleRect();
1179 
1180  if (subtype == XVideo && xv_port >= 0)
1181  {
1182  vector<unsigned char*> bufs =
1183  CreateShmImages(vbuffers.Size(), true);
1184 
1185  ok = (bufs.size() >= vbuffers.Size()) &&
1187  video_dim.width(), video_dim.height(),
1188  bufs, XJ_yuv_infos);
1189 
1190  disp->Sync();
1191  }
1192  else if (subtype == XShm || subtype == Xlib)
1193  {
1194  if (subtype == XShm)
1195  {
1196  vector<unsigned char*> bufs = CreateShmImages(1, false);
1197  if (bufs.empty())
1198  return false;
1199  XJ_non_xv_image = (XImage*) xv_buffers.begin()->second;
1200  }
1201  else
1202  {
1203  MythXLocker lock(disp);
1204  Display *d = disp->GetDisplay();
1205  int bytes_per_line;
1206  int scrn = disp->GetScreen();
1207  Visual *visual = DefaultVisual(d, scrn);
1208  XJ_non_xv_image = XCreateImage(d, visual, disp->GetDepth(),
1209  ZPixmap, /*offset*/0, /*data*/nullptr,
1210  display_visible_rect.width() & ~0x1,
1211  display_visible_rect.height() & ~0x1,
1212  /*bitmap_pad*/8, 0);
1213 
1214  if (!XJ_non_xv_image)
1215  {
1216  LOG(VB_GENERAL, LOG_ERR, LOC + "XCreateImage failed: " +
1217  QString("XJ_disp(0x%1) visual(0x%2) \n")
1218  .arg((uint64_t)d,0,16).arg((uint64_t)visual,0,16) +
1219  QString(" ") +
1220  QString("depth(%1) ").arg(disp->GetDepth()) +
1221  QString("WxH(%1""x%2) ")
1222  .arg(display_visible_rect.width())
1223  .arg(display_visible_rect.height()));
1224  return false;
1225  }
1226  bytes_per_line = XJ_non_xv_image->bytes_per_line;
1227  XJ_non_xv_image->data = (char*) malloc(
1228  bytes_per_line * display_visible_rect.height());
1229  }
1230 
1231  switch (XJ_non_xv_image->bits_per_pixel)
1232  { // only allow these three output formats for non-xv videout
1233  case 16: non_xv_av_format = AV_PIX_FMT_RGB565; break;
1234  case 24: non_xv_av_format = AV_PIX_FMT_RGB24; break;
1235  case 32: non_xv_av_format = AV_PIX_FMT_RGB32; break;
1236  default: non_xv_av_format = AV_PIX_FMT_NB;
1237  }
1238  if (AV_PIX_FMT_NB == non_xv_av_format)
1239  {
1240  QString msg = QString(
1241  "Non XVideo modes only support displays with 16,\n\t\t\t"
1242  "24, or 32 bits per pixel. But you have a %1 bpp display.")
1243  .arg(disp->GetDepth()*8);
1244 
1245  LOG(VB_GENERAL, LOG_ERR, LOC + msg);
1246  }
1247  else
1249  video_dim.width(), video_dim.height());
1250  }
1251 
1252  if (ok)
1253  CreatePauseFrame(subtype);
1254 
1255  return ok;
1256 }
1257 
1258 void VideoOutputXv::DeleteBuffers(VOSType subtype, bool delete_pause_frame)
1259 {
1260  (void) subtype;
1261  DiscardFrames(true);
1262 
1263  if (chroma_osd)
1264  {
1265  delete chroma_osd;
1266  chroma_osd = nullptr;
1267  }
1268 
1269  Display *d = disp->GetDisplay();
1270 
1272 
1273  if (delete_pause_frame)
1274  {
1275  if (av_pause_frame.buf)
1276  {
1277  av_freep(&av_pause_frame.buf);
1278  }
1280  {
1281  av_freep(&av_pause_frame.qscale_table);
1282  }
1283  }
1284 
1285  for (size_t i = 0; i < XJ_shm_infos.size(); i++)
1286  {
1287  MythXLocker lock(disp);
1288  XShmDetach(d, XJ_shm_infos[i]);
1289  XvImage *image = (XvImage*)
1290  xv_buffers[(unsigned char*) XJ_shm_infos[i]->shmaddr];
1291  if (image)
1292  {
1293  if ((XImage*)image == XJ_non_xv_image)
1294  XDestroyImage(XJ_non_xv_image);
1295  else
1296  XFree(image);
1297  }
1298  if (XJ_shm_infos[i]->shmaddr)
1299  shmdt(XJ_shm_infos[i]->shmaddr);
1300  if (XJ_shm_infos[i]->shmid > 0)
1301  shmctl(XJ_shm_infos[i]->shmid, IPC_RMID, nullptr);
1302  delete XJ_shm_infos[i];
1303  }
1304  XJ_shm_infos.clear();
1305  xv_buffers.clear();
1306  XJ_yuv_infos.clear();
1307  XJ_non_xv_image = nullptr;
1308 }
1309 
1310 void VideoOutputXv::EmbedInWidget(const QRect &rect)
1311 {
1312  QMutexLocker locker(&global_lock);
1313 
1314  if (!window.IsEmbedding())
1316  MoveResize();
1317 }
1318 
1320 {
1321  if (!window.IsEmbedding())
1322  return;
1323 
1324  QMutexLocker locker(&global_lock);
1325 
1327  MoveResize();
1328 }
1329 
1338 {
1339  if (!frame)
1340  return;
1341 
1342  vbuffers.DiscardFrame(frame);
1343 }
1344 
1346 {
1347  LOG(VB_PLAYBACK, LOG_INFO, LOC + "ClearAfterSeek()");
1348  DiscardFrames(false);
1349 }
1350 
1351 void VideoOutputXv::DiscardFrames(bool next_frame_keyframe)
1352 {
1353  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1354  QString("DiscardFrames(%1)").arg(next_frame_keyframe));
1355  if (VideoOutputSubType() <= XVideo)
1356  {
1357  vbuffers.DiscardFrames(next_frame_keyframe);
1358  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1359  QString("DiscardFrames() 3: %1 -- done()")
1360  .arg(vbuffers.GetStatus()));
1361  return;
1362  }
1363 }
1364 
1371 {
1372  if (!frame)
1373  frame = vbuffers.GetScratchFrame();
1374 
1375  global_lock.lock();
1376  framesPlayed = frame->frameNumber + 1;
1377  global_lock.unlock();
1378 
1379  if (vbuffers.GetScratchFrame() == frame)
1381 }
1382 
1389 {
1390  if (!buffer)
1391  buffer = vbuffers.GetScratchFrame();
1392 
1393  framesPlayed = buffer->frameNumber + 1;
1394  int width = buffer->width;
1395  int height = buffer->height;
1396 
1397  // bad way to throttle frame display for non-Xv mode.
1398  // calculate fps we can do and skip enough frames so we don't exceed.
1399  if (non_xv_frames_shown == 0)
1400  non_xv_stop_time = time(nullptr) + 4;
1401 
1402  const QRect display_visible_rect = window.GetDisplayVisibleRect();
1403 
1404  if ((!non_xv_fps) && (time(nullptr) > non_xv_stop_time))
1405  {
1406  non_xv_fps = (int)(non_xv_frames_shown / 4);
1407 
1408  if (non_xv_fps < 25)
1409  {
1410  non_xv_show_frame = 120 / (non_xv_frames_shown + 1);
1411  LOG(VB_GENERAL, LOG_ERR, LOC +
1412  QString("\n***\n"
1413  "* Your system is not capable of displaying the\n"
1414  "* full framerate at %1""x%2 resolution. Frames\n"
1415  "* will be skipped in order to keep the audio and\n"
1416  "* video in sync.\n").arg(display_visible_rect.width())
1417  .arg(display_visible_rect.height()));
1418  }
1419  }
1420 
1422 
1424  return;
1425 
1426  if (!XJ_non_xv_image)
1427  {
1428  LOG(VB_GENERAL, LOG_ERR, LOC + "XJ_non_xv_image == nullptr");
1429  return;
1430  }
1431 
1432  int out_width = display_visible_rect.width() & ~0x1;
1433  int out_height = display_visible_rect.height() & ~0x1;
1434  AVFrame image_in, image_out;
1435 
1436  if ((out_width == width) &&
1437  (out_height == height))
1438  {
1439  m_copyFrame.Copy(&image_out, buffer);
1440  }
1441  else
1442  {
1443  static QMutex lock;
1444  static struct SwsContext *scontext = nullptr;
1445  int size = buffersize(FMT_YV12, out_width, out_height);
1446  unsigned char *sbuf = (unsigned char*)av_malloc(size);
1447 
1448  av_image_fill_arrays(image_out.data, image_out.linesize,
1449  sbuf, AV_PIX_FMT_YUV420P,
1450  out_width, out_height, IMAGE_ALIGN);
1451  AVPictureFill(&image_in, buffer);
1452  QMutexLocker locker(&lock);
1453  scontext = sws_getCachedContext(scontext, width, height,
1454  AV_PIX_FMT_YUV420P, out_width,
1455  out_height, AV_PIX_FMT_YUV420P,
1456  SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
1457 
1458  sws_scale(scontext, image_in.data, image_in.linesize, 0, height,
1459  image_out.data, image_out.linesize);
1460  }
1461 
1462  av_image_fill_arrays(image_in.data, image_in.linesize,
1463  (uint8_t *)XJ_non_xv_image->data,
1464  non_xv_av_format, out_width, out_height, IMAGE_ALIGN);
1465 
1466  m_copyFrame.Copy(&image_in, non_xv_av_format, &image_out, AV_PIX_FMT_YUV420P,
1467  out_width, out_height);
1468 
1469  {
1470  QMutexLocker locker(&global_lock);
1471  disp->Lock();
1472  if (XShm == video_output_subtype)
1473  XShmPutImage(disp->GetDisplay(), XJ_curwin, disp->GetGC(), XJ_non_xv_image,
1474  0, 0, 0, 0, out_width, out_height, False);
1475  else
1476  XPutImage(disp->GetDisplay(), XJ_curwin, disp->GetGC(), XJ_non_xv_image,
1477  0, 0, 0, 0, out_width, out_height);
1478  disp->Unlock();
1479  }
1480 
1481  av_freep(&image_out.data[0]);
1482 }
1483 
1484 // this is documented in videooutbase.cpp
1486  OSD *osd)
1487 {
1488  (void)osd;
1489  if (IsErrored())
1490  {
1491  LOG(VB_GENERAL, LOG_ERR, LOC + "IsErrored() in PrepareFrame()");
1492  return;
1493  }
1494 
1495  if (VideoOutputSubType() == XVideo)
1496  PrepareFrameXv(buffer);
1497  else
1498  PrepareFrameMem(buffer, scan);
1499 }
1500 
1501 static void calc_bob(FrameScanType scan, int imgh, int disphoff,
1502  int imgy, int dispyoff,
1503  int frame_height, int top_field_first,
1504  int &field, int &src_y, int &dest_y,
1505  int& xv_src_y_incr, int &xv_dest_y_incr)
1506 {
1507  int dst_half_line_in_src = 0, dest_y_incr = 0, src_y_incr = 0;
1508  field = 3;
1509  src_y = imgy;
1510  dest_y = dispyoff;
1511  xv_src_y_incr = 0;
1512 
1513  if ((kScan_Interlaced != scan) && (kScan_Intr2ndField != scan))
1514  return;
1515 
1516  // a negative offset y gives us bobbing, so adjust...
1517  if (dispyoff < 0)
1518  {
1519  dest_y_incr = -dispyoff;
1520  src_y_incr = dest_y_incr * imgh / disphoff;
1521  xv_src_y_incr -= (int) (0.5 * dest_y_incr * imgh / disphoff);
1522  }
1523 
1524  if ((scan == kScan_Interlaced && top_field_first == 1) ||
1525  (scan == kScan_Intr2ndField && top_field_first == 0))
1526  {
1527  field = 1;
1528  xv_src_y_incr += - imgy / 2;
1529  }
1530  else if ((scan == kScan_Interlaced && top_field_first == 0) ||
1531  (scan == kScan_Intr2ndField && top_field_first == 1))
1532  {
1533  field = 2;
1534  xv_src_y_incr += (frame_height - imgy) / 2;
1535 
1536  dst_half_line_in_src =
1537  max((int) round((((double)disphoff)/imgh) - 0.00001), 0);
1538  }
1539  src_y += src_y_incr;
1540  dest_y += dest_y_incr;
1541 
1542 #define NVIDIA_6629
1543 #ifdef NVIDIA_6629
1544  xv_dest_y_incr = dst_half_line_in_src;
1545  // nVidia v 66.29, does proper compensation when imgh==frame_height
1546  // but we need to compensate when the difference is >= 5%
1547  if (frame_height>=(int)(imgh+(0.05*frame_height)) && 2==field)
1548  {
1549  //int nrml = (int) round((((double)disphoff)/frame_height) - 0.00001);
1550  int mod = -dst_half_line_in_src;
1551  dest_y += mod;
1552  xv_dest_y_incr -= mod;
1553  }
1554 #else
1555  dest_y += dst_half_line_in_src;
1556 #endif
1557 
1558  // DEBUG
1559 #if 0
1560  static int last_dest_y_field[3] = { -1000, -1000, -1000, };
1561  int last_dest_y = last_dest_y_field[field];
1562 
1563  if (last_dest_y != dest_y)
1564  {
1565  LOG(VB_GENERAL, LOG_DEBUG,
1566  QString("####### Field %1 #######").arg(field));
1567  LOG(VB_GENERAL, LOG_DEBUG, QString(" src_y: %1").arg(src_y));
1568  LOG(VB_GENERAL, LOG_DEBUG, QString(" dest_y: %1").arg(dest_y));
1569  LOG(VB_GENERAL, LOG_DEBUG,
1570  QString(" xv_src_y_incr: %1").arg(xv_src_y_incr));
1571  LOG(VB_GENERAL, LOG_DEBUG,
1572  QString("xv_dest_y_incr: %1").arg(xv_dest_y_incr));
1573  LOG(VB_GENERAL, LOG_DEBUG, QString(" disphoff: %1").arg(disphoff));
1574  LOG(VB_GENERAL, LOG_DEBUG, QString(" imgh: %1").arg(imgh));
1575  LOG(VB_GENERAL, LOG_DEBUG, QString(" mod: %1").arg(mod));
1576  }
1577  last_dest_y_field[field] = dest_y;
1578 #endif
1579 }
1580 
1582 {
1583  VideoFrame *frame = GetLastShownFrame();
1584 
1585  XvImage *image = (XvImage*) xv_buffers[frame->buf];
1586  if (!image)
1587  return;
1588 
1589  const QRect video_rect = window.GetVideoRect();
1590  const QRect display_video_rect = (vsz_enabled && chroma_osd) ?
1593  int field = 3, src_y = video_rect.top(), dest_y = display_video_rect.top();
1594  if (m_deinterlacing && (m_deintfiltername == "bobdeint"))
1595  {
1596  int xv_src_y_incr = 0, xv_dest_y_incr = 0;
1597  calc_bob(scan,
1598  video_rect.height(), display_video_rect.height(),
1599  video_rect.top(), display_video_rect.top(),
1600  frame->height, frame->top_field_first,
1601  field, src_y, dest_y, xv_src_y_incr, xv_dest_y_incr);
1602  src_y += xv_src_y_incr;
1603  dest_y += xv_dest_y_incr;
1604  }
1605 
1606  {
1607  QMutexLocker locker(&global_lock);
1608  int video_height = (3 != field) ?
1609  (video_rect.height()/2) : video_rect.height();
1610  disp->Lock();
1611  XvShmPutImage(disp->GetDisplay(), xv_port, XJ_curwin,
1612  disp->GetGC(), image,
1613  video_rect.left(), src_y,
1614  video_rect.width(), video_height,
1615  display_video_rect.left(), dest_y,
1616  display_video_rect.width(),
1617  display_video_rect.height(), False);
1618  disp->Unlock();
1619  }
1620 }
1621 
1622 // this is documented in videooutbase.cpp
1624 {
1625  if (IsErrored())
1626  {
1627  LOG(VB_GENERAL, LOG_ERR, LOC + "IsErrored() is true in Show()");
1628  return;
1629  }
1630 
1633  {
1634  DrawUnusedRects(/* don't do a sync*/false);
1635  }
1636 
1637  if (VideoOutputSubType() == XVideo)
1638  ShowXVideo(scan);
1639 
1640  disp->Sync();
1641 }
1642 
1644 {
1645  // boboff assumes the smallest interlaced resolution is 480 lines - 5%
1646  bool use_bob = (m_deinterlacing && m_deintfiltername == "bobdeint");
1647  const QRect display_visible_rect = window.GetDisplayVisibleRect();
1648  const QRect display_video_rect = window.GetDisplayVideoRect();
1649  int boboff_raw = (int)round(((double)display_video_rect.height()) /
1650  456 - 0.00001);
1651  int boboff = use_bob ? boboff_raw : 0;
1652 
1654 
1655  Display *d = disp->GetDisplay();
1657  {
1658  XLOCK(disp, XShmPutImage(d, XJ_curwin, disp->GetGC(),
1659  chroma_osd->GetImage(), 0, 0, 0, 0,
1660  display_visible_rect.width(),
1661  display_visible_rect.height(), False));
1662  if (sync)
1663  disp->Sync();
1664 
1665  window.SetNeedRepaint(false);
1666  xv_need_bobdeint_repaint = false;
1667  return;
1668  }
1669 
1671  {
1674  QRect(display_visible_rect.left(),
1675  display_visible_rect.top() + boboff,
1676  display_visible_rect.width(),
1677  display_visible_rect.height() - 2 * boboff));
1678  }
1680  {
1681  // if this is only for deinterlacing mode switching, draw
1682  // the border areas, presumably the main image is undamaged.
1685  QRect(display_visible_rect.left(),
1686  display_visible_rect.top(),
1687  display_visible_rect.width(),
1688  boboff_raw));
1690  QRect(display_visible_rect.left(),
1691  display_visible_rect.height() - 2 * boboff_raw,
1692  display_visible_rect.width(),
1693  display_visible_rect.height()));
1694  }
1695 
1696  window.SetNeedRepaint(false);
1697  xv_need_bobdeint_repaint = false;
1698 
1699  // Set colour for masked areas
1701 
1702  if (display_video_rect.left() > display_visible_rect.left())
1703  { // left
1705  QRect(display_visible_rect.left(),
1706  display_visible_rect.top(),
1707  display_video_rect.left() - display_visible_rect.left(),
1708  display_visible_rect.height()));
1709  }
1710  if (display_video_rect.left() + display_video_rect.width() <
1711  display_visible_rect.left() + display_visible_rect.width())
1712  { // right
1714  QRect(display_video_rect.left() + display_video_rect.width(),
1715  display_visible_rect.top(),
1716  (display_visible_rect.left() +
1717  display_visible_rect.width()) -
1718  (display_video_rect.left() +
1719  display_video_rect.width()),
1720  display_visible_rect.height()));
1721  }
1722  if (display_video_rect.top() + boboff > display_visible_rect.top())
1723  { // top of screen
1725  QRect(display_visible_rect.left(),
1726  display_visible_rect.top(),
1727  display_visible_rect.width(),
1728  display_video_rect.top() + boboff -
1729  display_visible_rect.top()));
1730  }
1731  if (display_video_rect.top() + display_video_rect.height() <
1732  display_visible_rect.top() + display_visible_rect.height())
1733  { // bottom of screen
1735  QRect(display_visible_rect.left(),
1736  display_video_rect.top() + display_video_rect.height(),
1737  display_visible_rect.width(),
1738  (display_visible_rect.top() +
1739  display_visible_rect.height()) -
1740  (display_video_rect.top() +
1741  display_video_rect.height())));
1742  }
1743 
1744  if (sync)
1745  disp->Sync();
1746 }
1747 
1748 // documented in videooutbase.cpp
1750 {
1751  QMutexLocker locker(&global_lock);
1753 }
1754 
1755 void VideoOutputXv::UpdatePauseFrame(int64_t &disp_timecode)
1756 {
1757  QMutexLocker locker(&global_lock);
1758 
1759  LOG(VB_PLAYBACK, LOG_INFO, LOC + "UpdatePauseFrame() " +
1760  vbuffers.GetStatus());
1761 
1762  if (VideoOutputSubType() <= XVideo)
1763  {
1764  // Try used frame first, then fall back to scratch frame.
1766 
1767  VideoFrame *used_frame = nullptr;
1768  if (vbuffers.Size(kVideoBuffer_used) > 0)
1769  used_frame = vbuffers.Head(kVideoBuffer_used);
1770 
1771  if (used_frame)
1772  CopyFrame(&av_pause_frame, used_frame);
1773 
1774  vbuffers.end_lock();
1775 
1776  if (!used_frame)
1777  {
1780  }
1781 
1782  disp_timecode = av_pause_frame.disp_timecode;
1783  }
1784 }
1785 
1787  FilterChain *filterList,
1788  const PIPMap &pipPlayers,
1790 {
1791  if (IsErrored())
1792  {
1793  LOG(VB_GENERAL, LOG_ERR, LOC + "IsErrored() in ProcessFrame()");
1794  return;
1795  }
1796 
1797  bool deint_proc = m_deinterlacing && (m_deintFilter != nullptr);
1798  bool pauseframe = false;
1799  if (!frame)
1800  {
1801  frame = vbuffers.GetScratchFrame();
1802  vector<const VideoFrame*> locks;
1803  locks.push_back(frame);
1804  locks.push_back(&av_pause_frame);
1805  CopyFrame(frame, &av_pause_frame);
1806  pauseframe = true;
1807  }
1808 
1809  CropToDisplay(frame);
1810 
1811  bool safepauseframe = pauseframe && !IsBobDeint();
1812  if (!pauseframe || safepauseframe)
1813  {
1814  if (filterList)
1815  filterList->ProcessFrame(frame);
1816 
1817  if (deint_proc && m_deinterlaceBeforeOSD)
1818  m_deintFilter->ProcessFrame(frame, scan);
1819  }
1820 
1821  ShowPIPs(frame, pipPlayers);
1822 
1823  if (osd && !window.IsEmbedding())
1824  {
1825  if (!chroma_osd)
1826  DisplayOSD(frame, osd);
1827  else
1828  {
1829  QMutexLocker locker(&global_lock);
1832  }
1833  }
1834 
1835  if ((!pauseframe || safepauseframe) &&
1836  deint_proc && !m_deinterlaceBeforeOSD)
1837  {
1838  m_deintFilter->ProcessFrame(frame, scan);
1839  }
1840 }
1841 
1842 // this is documented in videooutbase.cpp
1844  PictureAttribute attribute, int newValue)
1845 {
1846  newValue = videoColourSpace.SetPictureAttribute(attribute, newValue);
1847  if (newValue >= 0)
1848  newValue = SetXVPictureAttribute(attribute, newValue);
1849  return newValue;
1850 }
1851 
1853 {
1854  QString attrName = toXVString(attribute);
1855  QByteArray ascii_attr_name = attrName.toLatin1();
1856  const char *cname = ascii_attr_name.constData();
1857 
1858  if (attrName.isEmpty())
1859  {
1860  LOG(VB_GENERAL, LOG_ERR, "\n\n\n attrName.isEmpty() \n\n\n");
1861  return -1;
1862  }
1863 
1864  int port_min = xv_attribute_min[attribute];
1865  int port_max = xv_attribute_max[attribute];
1866  int port_def = xv_attribute_def[attribute];
1867  int range = port_max - port_min;
1868 
1869  int valAdj = (kPictureAttribute_Hue == attribute) ? xv_hue_base : 0;
1870 
1871  if (xv_set_defaults && range && (kPictureAttribute_Hue == attribute))
1872  {
1873  float tmp = (((float)(port_def - port_min) / (float)range) * 100.0F);
1874  valAdj = lroundf(tmp);
1875  }
1876 
1877  int tmpval2 = (newValue + valAdj) % 100;
1878  int tmpval3 = (int) roundf(range * 0.01F * tmpval2);
1879  int value = min(tmpval3 + port_min, port_max);
1880 
1881  xv_set_attrib(disp, xv_port, cname, value);
1882 
1883  return newValue;
1884 }
1885 
1887 {
1889 
1890  if (VideoOutputSubType() >= XVideo)
1891  {
1892  if (xv_set_defaults)
1893  {
1894  QByteArray ascii_name = "XV_SET_DEFAULTS";
1895  const char *name = ascii_name.constData();
1897  }
1898 
1899  int val, min_val, max_val;
1900  for (uint i = 0; i < kPictureAttribute_MAX; i++)
1901  {
1902  QString attrName = toXVString((PictureAttribute)i);
1903  QByteArray ascii_attr_name = attrName.toLatin1();
1904  const char *cname = ascii_attr_name.constData();
1905 
1906  if (attrName.isEmpty())
1907  continue;
1908 
1909  if (xv_is_attrib_supported(disp, xv_port, cname,
1910  &val, &min_val, &max_val))
1911  {
1912  supported = (PictureAttributeSupported)
1913  (supported | toMask((PictureAttribute)i));
1914  xv_attribute_min[(PictureAttribute)i] = min_val;
1915  xv_attribute_max[(PictureAttribute)i] = max_val;
1917  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("%1: %2:%3:%4")
1918  .arg(cname).arg(min_val).arg(val).arg(max_val));
1921  }
1922  }
1923 
1925  }
1926 }
1927 
1929  MythPlayer *pipplayer,
1930  bool do_pixel_adj) const
1931 {
1932  (void)do_pixel_adj;
1933 
1934  if (!pipplayer || !pipplayer->UsingNullVideo())
1935  return VideoOutput::GetPIPRect(location, pipplayer);
1936 
1937  QRect position;
1938  const QSize video_disp_dim = window.GetVideoDispDim();
1939  const QRect video_rect = window.GetVideoRect();
1940  const QRect display_video_rect = window.GetDisplayVideoRect();
1941  const QRect display_visible_rect = window.GetDisplayVisibleRect();
1942  float video_aspect = window.GetVideoAspect();
1943  if (video_aspect < 0.01F)
1944  video_aspect = 1.3333F;
1945 
1946  const float pip_size = (float)window.GetPIPSize();
1947  const float pipVideoAspect = pipplayer->GetVideoAspect();
1948 
1949  // adjust for aspect override modes...
1950  int letterXadj = 0;
1951  int letterYadj = 0;
1952  float letterAdj = 1.0F;
1954  {
1955  letterXadj = max(-display_video_rect.left(), 0);
1956  float xadj = (float)video_rect.width() / display_visible_rect.width();
1957  letterXadj = (int)(letterXadj * xadj);
1958  float yadj = (float)video_rect.height() / display_visible_rect.height();
1959  letterYadj = max(-display_video_rect.top(), 0);
1960  letterYadj = (int)(letterYadj * yadj);
1961  letterAdj = window.GetVideoAspect() /
1963  }
1964  // adjust for the relative aspect ratios of pip and main video
1965  float aspectAdj = pipVideoAspect / video_aspect;
1966 
1967  int tmph = (int) ((float)video_disp_dim.height() * pip_size * 0.01F);
1968  int tmpw = (int) ((float)video_disp_dim.width() * pip_size * 0.01F *
1969  aspectAdj * letterAdj);
1970  position.setWidth((tmpw >> 1) << 1);
1971  position.setHeight((tmph >> 1) << 1);
1972 
1973  int xoff = 30;
1974  int yoff = 40;
1975 
1976  switch (location)
1977  {
1978  default:
1979  case kPIPTopLeft:
1980  xoff += letterXadj;
1981  yoff += letterYadj;
1982  break;
1983  case kPIPBottomLeft:
1984  xoff += letterXadj;
1985  yoff = video_disp_dim.height() - position.height() -
1986  yoff - letterYadj;
1987  break;
1988  case kPIPTopRight:
1989  xoff = video_disp_dim.width() - position.width() -
1990  xoff - letterXadj;
1991  yoff = yoff + letterYadj;
1992  break;
1993  case kPIPBottomRight:
1994  xoff = video_disp_dim.width() - position.width() -
1995  xoff - letterXadj;
1996  yoff = video_disp_dim.height() - position.height() -
1997  yoff - letterYadj;
1998  break;
1999  }
2000 
2001  position.translate(xoff, yoff);
2002  return position;
2003 }
2004 
2006  MythCodecID myth_codec_id, const QSize &video_dim)
2007 {
2008  (void) video_dim;
2009 
2010  QStringList list;
2011 
2013 
2014  if (!disp)
2015  return list;
2016 
2017  list = allowed_video_renderers(myth_codec_id, disp);
2018 
2019  delete disp;
2020  return list;
2021 }
2022 
2024 {
2025  if (chroma_osd)
2026  return chroma_osd->GetPainter();
2027 
2028  return VideoOutput::GetOSDPainter();
2029 }
2030 
2031 static void SetFromEnv(bool &useXVideo, bool &useShm)
2032 {
2033  // can be used to force non-Xv mode as well as non-Xv/non-Shm mode
2034  if (getenv("NO_XV"))
2035  useXVideo = false;
2036  if (getenv("NO_SHM"))
2037  useXVideo = useShm = false;
2038 }
2039 
2040 static void SetFromHW(MythXDisplay *d, Window curwin,
2041  bool &useXVideo, bool &useShm)
2042 {
2043  (void)d;
2044  (void)curwin;
2045 
2046  if (!d)
2047  return;
2048 
2049  MythXLocker lock(d);
2050 
2051  // find out about XVideo support
2052  if (useXVideo)
2053  {
2054  uint p_ver, p_rel, p_req, p_event, p_err, ret;
2055  ret = XvQueryExtension(d->GetDisplay(), &p_ver, &p_rel,
2056  &p_req, &p_event, &p_err);
2057  if (Success != ret)
2058  {
2059  LOG(VB_GENERAL, LOG_ERR, LOC +
2060  "XVideo output requested, but is not supported by display.");
2061  useXVideo = false;
2062  }
2063  }
2064 
2065  if (useShm)
2066  {
2067  const char *dispname = DisplayString(d->GetDisplay());
2068  if ((dispname) && (*dispname == ':'))
2069  useShm = (bool) XShmQueryExtension(d->GetDisplay());
2070  }
2071 }
2072 
2073 static QStringList allowed_video_renderers(
2074  MythCodecID myth_codec_id, MythXDisplay *display, Window curwin)
2075 {
2076  if (!curwin)
2077  curwin = display->GetRoot();
2078 
2079  bool xv = true;
2080  bool shm = true;
2081 
2082  myth2av_codecid(myth_codec_id);
2083 
2084  SetFromEnv(xv, shm);
2085  SetFromHW(display, curwin, xv, shm);
2086 
2087  QStringList list;
2088  if (codec_is_std(myth_codec_id))
2089  {
2090  if (xv)
2091  list += "xv-blit";
2092  if (shm)
2093  list += "xshm";
2094  list += "xlib";
2095  }
2096 
2097  return list;
2098 }
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:200
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:75
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:329
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)
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
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
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:217
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
AVCodecID myth2av_codecid(MythCodecID codec_id, bool &vdpau)
void SetInput(const QSize &size, float framerate=0, const QString &codecName=QString())
const char * name
Definition: ParseText.cpp:328
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
void UpdatePauseFrame(int64_t &disp_timecode) override
Updates frame displayed when video is paused.
#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
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
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
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:297
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:127
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