MythTV  0.28pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
videoout_openglvaapi.cpp
Go to the documentation of this file.
1 #include "videoout_openglvaapi.h"
2 #include "vaapicontext.h"
3 #include "mythmainwindow.h"
4 #include "mythpainter.h"
5 
6 #define LOC QString("VidOutGLVAAPI: ")
7 #define ERR QString("VidOutGLVAAPI Error: ")
8 
10 {
11  opts.renderers->append("openglvaapi");
12 
13  (*opts.deints)["openglvaapi"].append("vaapionefield");
14  (*opts.deints)["openglvaapi"].append("vaapibobdeint");
15  (*opts.deints)["openglvaapi"].append("none");
16  (*opts.osds)["openglvaapi"].append("opengl2");
17 
18  if (opts.decoders->contains("vaapi"))
19  (*opts.safe_renderers)["vaapi"].append("openglvaapi");
20 
21  if (opts.decoders->contains("ffmpeg"))
22  (*opts.safe_renderers)["ffmpeg"].append("openglvaapi");
23 
24  (*opts.safe_renderers)["dummy"].append("openglvaapi");
25  (*opts.safe_renderers)["nuppel"].append("openglvaapi");
26 
27  opts.priorities->insert("openglvaapi", 110);
28 }
29 
31  : VideoOutputOpenGL(), m_ctx(NULL), m_pauseBuffer(NULL)
32 {
33 }
34 
36 {
37  TearDown();
38 }
39 
41 {
43 }
44 
45 bool VideoOutputOpenGLVAAPI::InputChanged(const QSize &video_dim_buf,
46  const QSize &video_dim_disp,
47  float aspect,
48  MythCodecID av_codec_id, void *codec_private,
49  bool &aspect_only)
50 {
51  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputChanged(%1,%2,%3) %4->%5")
52  .arg(video_dim_disp.width()).arg(video_dim_disp.height())
53  .arg(aspect)
54  .arg(toString(video_codec_id)).arg(toString(av_codec_id)));
55 
56  if (!codec_is_vaapi(av_codec_id))
57  return VideoOutputOpenGL::InputChanged(video_dim_buf, video_dim_disp,
58  aspect, av_codec_id,
59  codec_private, aspect_only);
60 
61  QMutexLocker locker(&gl_context_lock);
62 
63  bool wasembedding = window.IsEmbedding();
64  QRect oldrect;
65  if (wasembedding)
66  {
67  oldrect = window.GetEmbeddingRect();
68  StopEmbedding();
69  }
70 
71  bool cid_changed = (video_codec_id != av_codec_id);
72  bool res_changed = video_dim_disp != window.GetActualVideoDim();
73  bool asp_changed = aspect != window.GetVideoAspect();
74 
75  if (!res_changed && !cid_changed)
76  {
77  if (asp_changed)
78  {
79  aspect_only = true;
81  MoveResize();
82  if (wasembedding)
83  EmbedInWidget(oldrect);
84  }
85  return true;
86  }
87 
88  if (gCoreContext->IsUIThread())
89  TearDown();
90  else
92 
93  QRect disp = window.GetDisplayVisibleRect();
94  if (Init(video_dim_buf, video_dim_disp,
95  aspect, gl_parent_win, disp, av_codec_id))
96  {
97  if (wasembedding)
98  EmbedInWidget(oldrect);
99  if (gCoreContext->IsUIThread())
100  BestDeint();
101  return true;
102  }
103 
104  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to re-initialise video output.");
106 
107  return false;
108 }
109 
110 bool VideoOutputOpenGLVAAPI::Init(const QSize &video_dim_buf,
111  const QSize &video_dim_disp,
112  float aspect,
113  WId winid, const QRect &win_rect,
114  MythCodecID codec_id)
115 {
116  bool ok = VideoOutputOpenGL::Init(video_dim_buf, video_dim_disp,
117  aspect, winid,
118  win_rect, codec_id);
119  if (ok && codec_is_vaapi(video_codec_id))
121  return ok;
122 }
123 
125 {
126  // FIXME During a video stream change this is called from the decoder
127  // thread - which breaks all other efforts to remove non-UI thread
128  // access to the OpenGL context. There is no obvious fix however - if we
129  // don't delete and re-create the VAAPI decoder context immediately then
130  // the decoder fails and playback exits.
131 
132  // lvr 27-oct-13
133  // in 0.27 if m_ctx->CreateDisplay is called outside of the UI thread then
134  // it fails, which then causes subsequent unbalanced calls to doneCurrent
135  // which results in Qt aborting. So just fail if non-UI.
136  if (!gCoreContext->IsUIThread())
137  {
138  LOG(VB_GENERAL, LOG_ERR, LOC +
139  "CreateVAAPIContext called from non-UI thread");
140  return false;
141  }
142 
143  OpenGLLocker ctx_lock(gl_context);
144 
145  if (m_ctx)
147 
149  if (m_ctx && m_ctx->CreateDisplay(size, false, gl_context) &&
150  m_ctx->CreateBuffers())
151  {
152  int num_buffers = m_ctx->GetNumBuffers();
153  const QSize video_dim = window.GetActualVideoDim();
154 
155  bool ok = true;
156  for (int i = 0; i < num_buffers; i++)
157  {
158  ok &= vbuffers.CreateBuffer(video_dim.width(),
159  video_dim.height(), i,
161  FMT_VAAPI);
162  }
164  return ok;
165  }
166 
167  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VAAPI context.");
169  return false;
170 }
171 
173 {
174  QMutexLocker locker(&gl_context_lock);
175  delete m_ctx;
176  m_ctx = NULL;
177 }
178 
180 {
181  QMutexLocker locker(&gl_context_lock);
182  if (codec_is_vaapi(video_codec_id))
183  {
184  vbuffers.Init(24, true, 2, 1, 4, 1);
185  return true;
186  }
188 }
189 
190 void* VideoOutputOpenGLVAAPI::GetDecoderContext(unsigned char* buf, uint8_t*& id)
191 {
192  if (m_ctx)
193  {
194  id = GetSurfaceIDPointer(buf);
195  return &m_ctx->m_ctx;
196  }
197  return NULL;
198 }
199 
201 {
202  if (m_ctx)
203  return m_ctx->GetSurfaceIDPointer(buf);
204  return NULL;
205 }
206 
208 {
209  if (db_vdisp_profile)
210  db_vdisp_profile->SetVideoRenderer("openglvaapi");
211 }
212 
213 bool VideoOutputOpenGLVAAPI::ApproveDeintFilter(const QString &filtername) const
214 {
215  return filtername.contains("vaapi");
216 }
217 
219 {
220  m_deinterlacing = enable;
221  SetupDeinterlace(enable);
222  return m_deinterlacing;
223 }
224 
225 bool VideoOutputOpenGLVAAPI::SetupDeinterlace(bool i, const QString& ovrf)
226 {
227  //m_deintfiltername = !db_vdisp_profile ? "" :
228  // db_vdisp_profile->GetFilteredDeint(ovrf);
229  m_deinterlacing = i;
230  return m_deinterlacing;
231 }
232 
234 {
235  if (codec_is_vaapi(video_codec_id))
236  {
237  if (m_ctx)
239  return;
240  }
242 }
243 
245  int newValue)
246 {
247  int val = newValue;
248  if (codec_is_vaapi(video_codec_id) && m_ctx)
249  val = m_ctx->SetPictureAttribute(attribute, newValue);
250  return VideoOutput::SetPictureAttribute(attribute, val);
251 }
252 
253 void VideoOutputOpenGLVAAPI::UpdatePauseFrame(int64_t &disp_timecode)
254 {
255  if (codec_is_std(video_codec_id))
256  {
258  return;
259  }
260 
263  {
265  CopyFrame(&av_pause_frame, frame);
266  m_pauseBuffer = frame->buf;
267  disp_timecode = frame->disp_timecode;
268  }
269  else
270  LOG(VB_PLAYBACK, LOG_WARNING, LOC +
271  "Could not update pause frame - no used frames.");
272 
273  vbuffers.end_lock();
274 }
275 
277  FilterChain *filterList,
278  const PIPMap &pipPlayers,
280 {
281  QMutexLocker locker(&gl_context_lock);
282  VideoOutputOpenGL::ProcessFrame(frame, osd, filterList, pipPlayers, scan);
283 
284  if (codec_is_vaapi(video_codec_id) && m_ctx && gl_videochain)
285  {
287  m_ctx->CopySurfaceToTexture(frame ? frame->buf : m_pauseBuffer,
292  }
293 }
294 
296  MythCodecID myth_codec_id, const QSize &video_dim)
297 {
298  (void) video_dim;
299  QStringList list;
300  if ((codec_is_std(myth_codec_id) || (codec_is_vaapi(myth_codec_id))) &&
301  !getenv("NO_VAAPI"))
302  {
303  list += "openglvaapi";
304  }
305  return list;
306 }
307 
309  uint width, uint height, const QString &decoder,
310  uint stream_type, bool no_acceleration,
311  PixelFormat &pix_fmt)
312 {
313  QSize size(width, height);
314  bool use_cpu = no_acceleration;
315  PixelFormat fmt = PIX_FMT_YUV420P;
316  MythCodecID test_cid = (MythCodecID)(kCodec_MPEG1_VAAPI + (stream_type - 1));
317  if (codec_is_vaapi(test_cid) && decoder == "vaapi" && !getenv("NO_VAAPI"))
318  use_cpu |= !VAAPIContext::IsFormatAccelerated(size, test_cid, fmt);
319  else
320  use_cpu = true;
321 
322  if (use_cpu)
323  return (MythCodecID)(kCodec_MPEG1 + (stream_type - 1));
324 
325  pix_fmt = fmt;
326  return test_cid;
327 }
328 
330 {
331  QMutexLocker locker(&gl_context_lock);
332 
333  if (gl_context)
334  {
335  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Re-using context"));
336  return true;
337  }
338 
340  if (!win)
341  {
342  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to get MythMainWindow");
343  return false;
344  }
345 
346  gl_context = dynamic_cast<MythRenderOpenGL*>(win->GetRenderDevice());
347 
349  {
350  gl_context->IncrRef();
351  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Using main UI render context");
352  return true;
353  }
354 
355  QWidget *device = QWidget::find(gl_parent_win);
356  if (!device)
357  {
358  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to find parent window");
359  return false;
360  }
361 
362  gl_context = MythRenderOpenGL::Create(OPENGL_PAINTER, device);
363  if (gl_context && gl_context->create())
364  {
365  gl_context->Init();
366  LOG(VB_GENERAL, LOG_INFO, LOC +
367  "Created MythRenderOpenGL 1.x device.");
368  return true;
369  }
370 
371  LOG(VB_GENERAL, LOG_ERR, LOC +
372  "Failed to create MythRenderOpenGL 1.x device.");
373  if (gl_context)
374  gl_context->DecrRef();
375  gl_context = NULL;
376 
377  return false;
378 }
bool CopySurfaceToTexture(const void *buf, uint texture, uint texture_type, FrameScanType scan)
void StopEmbedding(void)
Tells video output to stop embedding video in an existing window.
virtual int SetPictureAttribute(PictureAttribute, int newValue)
Sets a specified picture attribute.
int GetNumBuffers(void) const
Definition: vaapicontext.h:44
void SetVideoRenderer(const QString &video_renderer)
virtual void InitPictureAttributes(void)
QMap< MythPlayer *, PIPLocation > PIPMap
Definition: videooutbase.h:37
priority_map_t * priorities
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.
QString toString(MarkTypes type)
bool m_deinterlacing
Definition: videooutbase.h:334
MythCodecID
Definition: mythcodecid.h:10
VideoColourSpace videoColourSpace
Definition: videooutbase.h:306
void DestroyCPUResources(void)
safe_list_t * renderers
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
uint8_t * GetSurfaceIDPointer(void *buf)
static MythMainWindow * getMainWindow(const bool useDB=true)
Return the existing main window, or create one.
QRect GetDisplayVisibleRect(void) const
safe_map_t * deints
virtual void * GetDecoderContext(unsigned char *buf, uint8_t *&id)
bool CreateVAAPIContext(QSize size)
QSize GetActualVideoDim(void) const
FrameScanType
Definition: videoouttypes.h:76
unsigned int uint
Definition: compat.h:136
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
virtual void InitPictureAttributes(void)
bool InputChanged(const QSize &video_dim_buf, const QSize &video_dim_disp, float aspect, MythCodecID av_codec_id, void *codec_private, bool &aspect_only)
Tells video output to discard decoded frames and wait for new ones.
VideoDisplayProfile * db_vdisp_profile
Definition: videooutbase.h:314
virtual void doneCurrent()
uint GetInputTexture(void) const
voidpf void * buf
Definition: ioapi.h:136
vaapi_context m_ctx
Definition: vaapicontext.h:64
bool ApproveDeintFilter(const QString &filtername) const
Approves bobdeint filter for XVideo and otherwise defers to VideoOutput::ApproveDeintFilter(const QSt...
safe_list_t * decoders
RenderType Type(void) const
QRect GetEmbeddingRect(void) const
safe_map_t * osds
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.
bool SetupDeinterlace(bool i, const QString &ovrf="")
Attempts to enable or disable deinterlacing.
virtual int SetPictureAttribute(PictureAttribute attribute, int newValue)
Sets a specified picture attribute.
static void CopyFrame(VideoFrame *to, const VideoFrame *from)
Copies frame data from one VideoFrame to another.
virtual int IncrRef(void)
Increments reference count.
virtual bool CreateBuffers(void)
static void GetRenderOptions(render_opts &opts)
VideoBuffers vbuffers
VideoBuffers instance used to track video output buffers.
Definition: videooutbase.h:341
MythCodecID video_codec_id
Definition: videooutbase.h:313
static MythRenderOpenGL * Create(const QString &painter, QPaintDevice *device=NULL)
VideoErrorState errorState
Definition: videooutbase.h:344
virtual void BestDeint(void)
Change to the best deinterlacing method.
void MoveResize(void)
performs all the calculations for video framing and any resizing.
bool CreateBuffers(void)
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
uint8_t * GetSurfaceIDPointer(void *buf)
bool CreateBuffer(int width, int height, uint num, void *data, VideoFrameType fmt)
void end_lock()
Definition: videobuffers.h:99
virtual bool SetupContext(void)
OpenGLVideo * gl_videochain
PictureAttribute
Definition: videoouttypes.h:85
bool CreateDisplay(QSize size, bool noreuse=false, MythRenderOpenGL *render=NULL)
float GetVideoAspect(void) const
MythRenderOpenGL * gl_context
MythRender * GetRenderDevice()
void InitPictureAttributes(VideoColourSpace &colourspace)
void EmbedInWidget(const QRect &rect)
Tells video output to embed video in an existing window.
line height
Definition: MythXMLTest.css:26
GLint GLenum GLsizei width
void ProcessFrame(VideoFrame *frame, OSD *osd, FilterChain *filterList, const PIPMap &pipPlayers, FrameScanType scan)
virtual void ProcessFrame(VideoFrame *frame, OSD *osd, FilterChain *filterList, const PIPMap &pipPlayers, FrameScanType scan)
int64_t disp_timecode
Definition: mythframe.h:45
uint Size(BufferType type) const
typedef void(APIENTRY *MYTH_GLTEXIMAGE1DPROC)(GLenum target
safe_map_t * safe_renderers
void SetInputUpdated(void)
bool SetDeinterlacingEnabled(bool enable)
Attempts to enable/disable deinterlacing using existing deinterlace method when enabling.
VideoFrame * Head(BufferType)
virtual void VideoAspectRatioChanged(float aspect)
Calls SetVideoAspectRatio(float aspect), then calls MoveResize() to apply changes.
virtual void makeCurrent()
virtual bool InputChanged(const QSize &video_dim_buf, const QSize &video_dim_disp, float aspect, MythCodecID av_codec_id, void *codec_private, bool &aspect_only)
Tells video output to discard decoded frames and wait for new ones.
Definition: osd.h:131
virtual void UpdatePauseFrame(int64_t &disp_timecode)
Updates frame displayed when video is paused.
static const QString LOC
static QStringList GetAllowedRenderers(MythCodecID myth_codec_id, const QSize &video_dim)
virtual void UpdatePauseFrame(int64_t &disp_timecode)
Updates frame displayed when video is paused.
VideoOutWindow window
Definition: videooutbase.h:304
static MythCodecID GetBestSupportedCodec(uint width, uint height, const QString &decoder, uint stream_type, bool no_acceleration, PixelFormat &pix_fmt)
uint GetTextureType(void) const
int SetPictureAttribute(PictureAttribute attribute, int newValue)
void Init(uint numdecode, bool extra_for_pause, uint need_free, uint needprebuffer_normal, uint needprebuffer_small, uint keepprebuffer)
Creates buffers and sets various buffer management parameters.
void * GetVideoSurface(int i)
frame_queue_t::iterator begin_lock(BufferType)
unsigned char * buf
Definition: mythframe.h:34
bool IsEmbedding(void) const
Returns if videooutput is embedding.
static bool IsFormatAccelerated(QSize size, MythCodecID codec, PixelFormat &pix_fmt)
VideoFrame av_pause_frame
MYTH_GLsizeiptr size