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 
5 #define LOC QString("VidOutGLVAAPI: ")
6 #define ERR QString("VidOutGLVAAPI Error: ")
7 
9 {
10  opts.renderers->append("openglvaapi");
11 
12  (*opts.deints)["openglvaapi"].append("vaapionefield");
13  (*opts.deints)["openglvaapi"].append("vaapibobdeint");
14  (*opts.deints)["openglvaapi"].append("none");
15  (*opts.osds)["openglvaapi"].append("opengl2");
16 
17  if (opts.decoders->contains("vaapi"))
18  (*opts.safe_renderers)["vaapi"].append("openglvaapi");
19 
20  if (opts.decoders->contains("ffmpeg"))
21  (*opts.safe_renderers)["ffmpeg"].append("openglvaapi");
22 
23  (*opts.safe_renderers)["dummy"].append("openglvaapi");
24  (*opts.safe_renderers)["nuppel"].append("openglvaapi");
25 
26  opts.priorities->insert("openglvaapi", 110);
27 }
28 
30  : VideoOutputOpenGL(), m_ctx(NULL), m_pauseBuffer(NULL)
31 {
32 }
33 
35 {
36  TearDown();
37 }
38 
40 {
42 }
43 
44 bool VideoOutputOpenGLVAAPI::InputChanged(const QSize &video_dim_buf,
45  const QSize &video_dim_disp,
46  float aspect,
47  MythCodecID av_codec_id, void *codec_private,
48  bool &aspect_only)
49 {
50  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputChanged(%1,%2,%3) %4->%5")
51  .arg(video_dim_disp.width()).arg(video_dim_disp.height())
52  .arg(aspect)
53  .arg(toString(video_codec_id)).arg(toString(av_codec_id)));
54 
55  if (!codec_is_vaapi(av_codec_id))
56  return VideoOutputOpenGL::InputChanged(video_dim_buf, video_dim_disp,
57  aspect, av_codec_id,
58  codec_private, aspect_only);
59 
60  QMutexLocker locker(&gl_context_lock);
61 
62  bool wasembedding = window.IsEmbedding();
63  QRect oldrect;
64  if (wasembedding)
65  {
66  oldrect = window.GetEmbeddingRect();
67  StopEmbedding();
68  }
69 
70  bool cid_changed = (video_codec_id != av_codec_id);
71  bool res_changed = video_dim_disp != window.GetActualVideoDim();
72  bool asp_changed = aspect != window.GetVideoAspect();
73 
74  if (!res_changed && !cid_changed)
75  {
76  if (asp_changed)
77  {
78  aspect_only = true;
80  MoveResize();
81  if (wasembedding)
82  EmbedInWidget(oldrect);
83  }
84  return true;
85  }
86 
87  if (gCoreContext->IsUIThread())
88  TearDown();
89  else
91 
92  QRect disp = window.GetDisplayVisibleRect();
93  if (Init(video_dim_buf, video_dim_disp,
94  aspect, gl_parent_win, disp, av_codec_id))
95  {
96  if (wasembedding)
97  EmbedInWidget(oldrect);
98  if (gCoreContext->IsUIThread())
99  BestDeint();
100  return true;
101  }
102 
103  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to re-initialise video output.");
105 
106  return false;
107 }
108 
109 bool VideoOutputOpenGLVAAPI::Init(const QSize &video_dim_buf,
110  const QSize &video_dim_disp,
111  float aspect,
112  WId winid, const QRect &win_rect,
113  MythCodecID codec_id)
114 {
115  bool ok = VideoOutputOpenGL::Init(video_dim_buf, video_dim_disp,
116  aspect, winid,
117  win_rect, codec_id);
118  if (ok && codec_is_vaapi(video_codec_id))
120  return ok;
121 }
122 
124 {
125  // FIXME During a video stream change this is called from the decoder
126  // thread - which breaks all other efforts to remove non-UI thread
127  // access to the OpenGL context. There is no obvious fix however - if we
128  // don't delete and re-create the VAAPI decoder context immediately then
129  // the decoder fails and playback exits.
130 
131  // lvr 27-oct-13
132  // in 0.27 if m_ctx->CreateDisplay is called outside of the UI thread then
133  // it fails, which then causes subsequent unbalanced calls to doneCurrent
134  // which results in Qt aborting. So just fail if non-UI.
135  if (!gCoreContext->IsUIThread())
136  {
137  LOG(VB_GENERAL, LOG_ERR, LOC +
138  "CreateVAAPIContext called from non-UI thread");
139  return false;
140  }
141 
142  OpenGLLocker ctx_lock(gl_context);
143 
144  if (m_ctx)
146 
148  if (m_ctx && m_ctx->CreateDisplay(size, false, gl_context) &&
149  m_ctx->CreateBuffers())
150  {
151  int num_buffers = m_ctx->GetNumBuffers();
152  const QSize video_dim = window.GetActualVideoDim();
153 
154  bool ok = true;
155  for (int i = 0; i < num_buffers; i++)
156  {
157  ok &= vbuffers.CreateBuffer(video_dim.width(),
158  video_dim.height(), i,
160  FMT_VAAPI);
161  }
163  return ok;
164  }
165 
166  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VAAPI context.");
168  return false;
169 }
170 
172 {
173  QMutexLocker locker(&gl_context_lock);
174  delete m_ctx;
175  m_ctx = NULL;
176 }
177 
179 {
180  QMutexLocker locker(&gl_context_lock);
181  if (codec_is_vaapi(video_codec_id))
182  {
183  vbuffers.Init(24, true, 2, 1, 4, 1);
184  return true;
185  }
187 }
188 
189 void* VideoOutputOpenGLVAAPI::GetDecoderContext(unsigned char* buf, uint8_t*& id)
190 {
191  if (m_ctx)
192  {
193  id = GetSurfaceIDPointer(buf);
194  return &m_ctx->m_ctx;
195  }
196  return NULL;
197 }
198 
200 {
201  if (m_ctx)
202  return m_ctx->GetSurfaceIDPointer(buf);
203  return NULL;
204 }
205 
207 {
208  if (db_vdisp_profile)
209  db_vdisp_profile->SetVideoRenderer("openglvaapi");
210 }
211 
212 bool VideoOutputOpenGLVAAPI::ApproveDeintFilter(const QString &filtername) const
213 {
214  return filtername.contains("vaapi");
215 }
216 
218 {
219  m_deinterlacing = enable;
220  SetupDeinterlace(enable);
221  return m_deinterlacing;
222 }
223 
224 bool VideoOutputOpenGLVAAPI::SetupDeinterlace(bool i, const QString& ovrf)
225 {
226  //m_deintfiltername = !db_vdisp_profile ? "" :
227  // db_vdisp_profile->GetFilteredDeint(ovrf);
228  m_deinterlacing = i;
229  return m_deinterlacing;
230 }
231 
233 {
234  if (codec_is_vaapi(video_codec_id))
235  {
236  if (m_ctx)
238  return;
239  }
241 }
242 
244  int newValue)
245 {
246  int val = newValue;
247  if (codec_is_vaapi(video_codec_id) && m_ctx)
248  val = m_ctx->SetPictureAttribute(attribute, newValue);
249  return VideoOutput::SetPictureAttribute(attribute, val);
250 }
251 
252 void VideoOutputOpenGLVAAPI::UpdatePauseFrame(int64_t &disp_timecode)
253 {
254  if (codec_is_std(video_codec_id))
255  {
257  return;
258  }
259 
262  {
264  CopyFrame(&av_pause_frame, frame);
265  m_pauseBuffer = frame->buf;
266  disp_timecode = frame->disp_timecode;
267  }
268  else
269  LOG(VB_PLAYBACK, LOG_WARNING, LOC +
270  "Could not update pause frame - no used frames.");
271 
272  vbuffers.end_lock();
273 }
274 
276  FilterChain *filterList,
277  const PIPMap &pipPlayers,
279 {
280  QMutexLocker locker(&gl_context_lock);
281  VideoOutputOpenGL::ProcessFrame(frame, osd, filterList, pipPlayers, scan);
282 
283  if (codec_is_vaapi(video_codec_id) && m_ctx && gl_videochain)
284  {
286  m_ctx->CopySurfaceToTexture(frame ? frame->buf : m_pauseBuffer,
291  }
292 }
293 
295  MythCodecID myth_codec_id, const QSize &video_dim)
296 {
297  (void) video_dim;
298  QStringList list;
299  if ((codec_is_std(myth_codec_id) || (codec_is_vaapi(myth_codec_id))) &&
300  !getenv("NO_VAAPI"))
301  {
302  list += "openglvaapi";
303  }
304  return list;
305 }
306 
308  uint width, uint height, const QString &decoder,
309  uint stream_type, bool no_acceleration,
310  PixelFormat &pix_fmt)
311 {
312  QSize size(width, height);
313  bool use_cpu = no_acceleration;
314  PixelFormat fmt = PIX_FMT_YUV420P;
315  MythCodecID test_cid = (MythCodecID)(kCodec_MPEG1_VAAPI + (stream_type - 1));
316  if (codec_is_vaapi(test_cid) && decoder == "vaapi" && !getenv("NO_VAAPI"))
317  use_cpu |= !VAAPIContext::IsFormatAccelerated(size, test_cid, fmt);
318  else
319  use_cpu = true;
320 
321  if (use_cpu)
322  return (MythCodecID)(kCodec_MPEG1 + (stream_type - 1));
323 
324  pix_fmt = fmt;
325  return test_cid;
326 }
327 
329 {
330  QMutexLocker locker(&gl_context_lock);
331 
332  if (gl_context)
333  {
334  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Re-using context"));
335  return true;
336  }
337 
339  if (!win)
340  {
341  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to get MythMainWindow");
342  return false;
343  }
344 
345  gl_context = dynamic_cast<MythRenderOpenGL*>(win->GetRenderDevice());
346 
348  {
349  gl_context->IncrRef();
350  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Using main UI render context");
351  return true;
352  }
353 
354  QWidget *device = QWidget::find(gl_parent_win);
355  if (!device)
356  {
357  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to find parent window");
358  return false;
359  }
360 
361  gl_context = MythRenderOpenGL::Create(OPENGL_PAINTER, device);
362  if (gl_context && gl_context->create())
363  {
364  gl_context->Init();
365  LOG(VB_GENERAL, LOG_INFO, LOC +
366  "Created MythRenderOpenGL 1.x device.");
367  return true;
368  }
369 
370  LOG(VB_GENERAL, LOG_ERR, LOC +
371  "Failed to create MythRenderOpenGL 1.x device.");
372  if (gl_context)
373  gl_context->DecrRef();
374  gl_context = NULL;
375 
376  return false;
377 }
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:139
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