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 
4 #define LOC QString("VidOutGLVAAPI: ")
5 #define ERR QString("VidOutGLVAAPI Error: ")
6 
8 {
9  opts.renderers->append("openglvaapi");
10 
11  (*opts.deints)["openglvaapi"].append("vaapionefield");
12  (*opts.deints)["openglvaapi"].append("vaapibobdeint");
13  (*opts.deints)["openglvaapi"].append("none");
14  (*opts.osds)["openglvaapi"].append("opengl2");
15 
16  if (opts.decoders->contains("vaapi"))
17  (*opts.safe_renderers)["vaapi"].append("openglvaapi");
18 
19  if (opts.decoders->contains("ffmpeg"))
20  (*opts.safe_renderers)["ffmpeg"].append("openglvaapi");
21 
22  (*opts.safe_renderers)["dummy"].append("openglvaapi");
23  (*opts.safe_renderers)["nuppel"].append("openglvaapi");
24 
25  opts.priorities->insert("openglvaapi", 110);
26 }
27 
29  : VideoOutputOpenGL(), m_ctx(NULL), m_pauseBuffer(NULL)
30 {
31 }
32 
34 {
35  TearDown();
36 }
37 
39 {
41 }
42 
43 bool VideoOutputOpenGLVAAPI::InputChanged(const QSize &video_dim_buf,
44  const QSize &video_dim_disp,
45  float aspect,
46  MythCodecID av_codec_id, void *codec_private,
47  bool &aspect_only)
48 {
49  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputChanged(%1,%2,%3) %4->%5")
50  .arg(video_dim_disp.width()).arg(video_dim_disp.height())
51  .arg(aspect)
52  .arg(toString(video_codec_id)).arg(toString(av_codec_id)));
53 
54  if (!codec_is_vaapi(av_codec_id))
55  return VideoOutputOpenGL::InputChanged(video_dim_buf, video_dim_disp,
56  aspect, av_codec_id,
57  codec_private, aspect_only);
58 
59  QMutexLocker locker(&gl_context_lock);
60 
61  bool wasembedding = window.IsEmbedding();
62  QRect oldrect;
63  if (wasembedding)
64  {
65  oldrect = window.GetEmbeddingRect();
66  StopEmbedding();
67  }
68 
69  bool cid_changed = (video_codec_id != av_codec_id);
70  bool res_changed = video_dim_disp != window.GetActualVideoDim();
71  bool asp_changed = aspect != window.GetVideoAspect();
72 
73  if (!res_changed && !cid_changed)
74  {
75  if (asp_changed)
76  {
77  aspect_only = true;
79  MoveResize();
80  if (wasembedding)
81  EmbedInWidget(oldrect);
82  }
83  return true;
84  }
85 
86  if (gCoreContext->IsUIThread())
87  TearDown();
88  else
90 
91  QRect disp = window.GetDisplayVisibleRect();
92  if (Init(video_dim_buf, video_dim_disp,
93  aspect, gl_parent_win, disp, av_codec_id))
94  {
95  if (wasembedding)
96  EmbedInWidget(oldrect);
97  if (gCoreContext->IsUIThread())
98  BestDeint();
99  return true;
100  }
101 
102  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to re-initialise video output.");
104 
105  return false;
106 }
107 
108 bool VideoOutputOpenGLVAAPI::Init(const QSize &video_dim_buf,
109  const QSize &video_dim_disp,
110  float aspect,
111  WId winid, const QRect &win_rect,
112  MythCodecID codec_id)
113 {
114  bool ok = VideoOutputOpenGL::Init(video_dim_buf, video_dim_disp,
115  aspect, winid,
116  win_rect, codec_id);
117  if (ok && codec_is_vaapi(video_codec_id))
119  return ok;
120 }
121 
123 {
124  // FIXME During a video stream change this is called from the decoder
125  // thread - which breaks all other efforts to remove non-UI thread
126  // access to the OpenGL context. There is no obvious fix however - if we
127  // don't delete and re-create the VAAPI decoder context immediately then
128  // the decoder fails and playback exits.
129  OpenGLLocker ctx_lock(gl_context);
130 
131  if (m_ctx)
133 
135  if (m_ctx && m_ctx->CreateDisplay(size) && m_ctx->CreateBuffers())
136  {
137  int num_buffers = m_ctx->GetNumBuffers();
138  const QSize video_dim = window.GetActualVideoDim();
139 
140  bool ok = true;
141  for (int i = 0; i < num_buffers; i++)
142  {
143  ok &= vbuffers.CreateBuffer(video_dim.width(),
144  video_dim.height(), i,
146  FMT_VAAPI);
147  }
149  return ok;
150  }
151 
152  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VAAPI context.");
154  return false;
155 }
156 
158 {
159  QMutexLocker locker(&gl_context_lock);
160  delete m_ctx;
161  m_ctx = NULL;
162 }
163 
165 {
166  QMutexLocker locker(&gl_context_lock);
167  if (codec_is_vaapi(video_codec_id))
168  {
169  vbuffers.Init(24, true, 2, 1, 4, 1);
170  return true;
171  }
173 }
174 
175 void* VideoOutputOpenGLVAAPI::GetDecoderContext(unsigned char* buf, uint8_t*& id)
176 {
177  if (m_ctx)
178  {
179  id = GetSurfaceIDPointer(buf);
180  return &m_ctx->m_ctx;
181  }
182  return NULL;
183 }
184 
186 {
187  if (m_ctx)
188  return m_ctx->GetSurfaceIDPointer(buf);
189  return NULL;
190 }
191 
193 {
194  if (db_vdisp_profile)
195  db_vdisp_profile->SetVideoRenderer("openglvaapi");
196 }
197 
198 bool VideoOutputOpenGLVAAPI::ApproveDeintFilter(const QString &filtername) const
199 {
200  return filtername.contains("vaapi");
201 }
202 
204 {
205  m_deinterlacing = enable;
206  SetupDeinterlace(enable);
207  return m_deinterlacing;
208 }
209 
210 bool VideoOutputOpenGLVAAPI::SetupDeinterlace(bool i, const QString& ovrf)
211 {
212  //m_deintfiltername = !db_vdisp_profile ? "" :
213  // db_vdisp_profile->GetFilteredDeint(ovrf);
214  m_deinterlacing = i;
215  return m_deinterlacing;
216 }
217 
219 {
220  if (codec_is_vaapi(video_codec_id))
221  {
222  if (m_ctx)
224  return;
225  }
227 }
228 
230  int newValue)
231 {
232  int val = newValue;
233  if (codec_is_vaapi(video_codec_id) && m_ctx)
234  val = m_ctx->SetPictureAttribute(attribute, newValue);
235  return VideoOutput::SetPictureAttribute(attribute, val);
236 }
237 
238 void VideoOutputOpenGLVAAPI::UpdatePauseFrame(int64_t &disp_timecode)
239 {
240  if (codec_is_std(video_codec_id))
241  {
243  return;
244  }
245 
248  {
250  CopyFrame(&av_pause_frame, frame);
251  m_pauseBuffer = frame->buf;
252  disp_timecode = frame->disp_timecode;
253  }
254  else
255  LOG(VB_PLAYBACK, LOG_WARNING, LOC +
256  "Could not update pause frame - no used frames.");
257 
258  vbuffers.end_lock();
259 }
260 
262  FilterChain *filterList,
263  const PIPMap &pipPlayers,
265 {
266  QMutexLocker locker(&gl_context_lock);
267  VideoOutputOpenGL::ProcessFrame(frame, osd, filterList, pipPlayers, scan);
268 
269  if (codec_is_vaapi(video_codec_id) && m_ctx && gl_videochain)
270  {
272  m_ctx->CopySurfaceToTexture(frame ? frame->buf : m_pauseBuffer,
277  }
278 }
279 
281  MythCodecID myth_codec_id, const QSize &video_dim)
282 {
283  (void) video_dim;
284  QStringList list;
285  if ((codec_is_std(myth_codec_id) || (codec_is_vaapi(myth_codec_id))) &&
286  !getenv("NO_VAAPI"))
287  {
288  list += "openglvaapi";
289  }
290  return list;
291 }
292 
294  uint width, uint height, const QString &decoder,
295  uint stream_type, bool no_acceleration,
296  PixelFormat &pix_fmt)
297 {
298  QSize size(width, height);
299  bool use_cpu = no_acceleration;
300  PixelFormat fmt = PIX_FMT_YUV420P;
301  MythCodecID test_cid = (MythCodecID)(kCodec_MPEG1_VAAPI + (stream_type - 1));
302  if (codec_is_vaapi(test_cid) && decoder == "vaapi" && !getenv("NO_VAAPI"))
303  use_cpu |= !VAAPIContext::IsFormatAccelerated(size, test_cid, fmt);
304  else
305  use_cpu = true;
306 
307  if (use_cpu)
308  return (MythCodecID)(kCodec_MPEG1 + (stream_type - 1));
309 
310  pix_fmt = fmt;
311  return test_cid;
312 }