MythTV  0.28pre
videoout_openglvaapi.cpp
Go to the documentation of this file.
1 #include "videoout_openglvaapi.h"
2 #include "vaapicontext.h"
3 #include "mythpainter.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) && m_ctx->CreateBuffers())
149  {
150  int num_buffers = m_ctx->GetNumBuffers();
151  const QSize video_dim = window.GetActualVideoDim();
152 
153  bool ok = true;
154  for (int i = 0; i < num_buffers; i++)
155  {
156  ok &= vbuffers.CreateBuffer(video_dim.width(),
157  video_dim.height(), i,
159  FMT_VAAPI);
160  }
162  return ok;
163  }
164 
165  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VAAPI context.");
167  return false;
168 }
169 
171 {
172  QMutexLocker locker(&gl_context_lock);
173  delete m_ctx;
174  m_ctx = NULL;
175 }
176 
178 {
179  QMutexLocker locker(&gl_context_lock);
180  if (codec_is_vaapi(video_codec_id))
181  {
182  vbuffers.Init(24, true, 2, 1, 4, 1);
183  return true;
184  }
186 }
187 
188 void* VideoOutputOpenGLVAAPI::GetDecoderContext(unsigned char* buf, uint8_t*& id)
189 {
190  if (m_ctx)
191  {
192  id = GetSurfaceIDPointer(buf);
193  return &m_ctx->m_ctx;
194  }
195  return NULL;
196 }
197 
199 {
200  if (m_ctx)
201  return m_ctx->GetSurfaceIDPointer(buf);
202  return NULL;
203 }
204 
206 {
207  if (db_vdisp_profile)
208  db_vdisp_profile->SetVideoRenderer("openglvaapi");
209 }
210 
211 bool VideoOutputOpenGLVAAPI::ApproveDeintFilter(const QString &filtername) const
212 {
213  return filtername.contains("vaapi");
214 }
215 
217 {
218  m_deinterlacing = enable;
219  SetupDeinterlace(enable);
220  return m_deinterlacing;
221 }
222 
223 bool VideoOutputOpenGLVAAPI::SetupDeinterlace(bool i, const QString& ovrf)
224 {
225  //m_deintfiltername = !db_vdisp_profile ? "" :
226  // db_vdisp_profile->GetFilteredDeint(ovrf);
227  m_deinterlacing = i;
228  return m_deinterlacing;
229 }
230 
232 {
233  if (codec_is_vaapi(video_codec_id))
234  {
235  if (m_ctx)
237  return;
238  }
240 }
241 
243  int newValue)
244 {
245  int val = newValue;
246  if (codec_is_vaapi(video_codec_id) && m_ctx)
247  val = m_ctx->SetPictureAttribute(attribute, newValue);
248  return VideoOutput::SetPictureAttribute(attribute, val);
249 }
250 
251 void VideoOutputOpenGLVAAPI::UpdatePauseFrame(int64_t &disp_timecode)
252 {
253  if (codec_is_std(video_codec_id))
254  {
256  return;
257  }
258 
261  {
263  CopyFrame(&av_pause_frame, frame);
264  m_pauseBuffer = frame->buf;
265  disp_timecode = frame->disp_timecode;
266  }
267  else
268  LOG(VB_PLAYBACK, LOG_WARNING, LOC +
269  "Could not update pause frame - no used frames.");
270 
271  vbuffers.end_lock();
272 }
273 
275  FilterChain *filterList,
276  const PIPMap &pipPlayers,
278 {
279  QMutexLocker locker(&gl_context_lock);
280  VideoOutputOpenGL::ProcessFrame(frame, osd, filterList, pipPlayers, scan);
281 
282  if (codec_is_vaapi(video_codec_id) && m_ctx && gl_videochain)
283  {
285  m_ctx->CopySurfaceToTexture(frame ? frame->buf : m_pauseBuffer,
290  }
291 }
292 
294  MythCodecID myth_codec_id, const QSize &video_dim)
295 {
296  (void) video_dim;
297  QStringList list;
298  if ((codec_is_std(myth_codec_id) || (codec_is_vaapi(myth_codec_id))) &&
299  !getenv("NO_VAAPI"))
300  {
301  list += "openglvaapi";
302  }
303  return list;
304 }
305 
307  uint width, uint height, const QString &decoder,
308  uint stream_type, bool no_acceleration,
309  PixelFormat &pix_fmt)
310 {
311  QSize size(width, height);
312  bool use_cpu = no_acceleration;
313  PixelFormat fmt = PIX_FMT_YUV420P;
314  MythCodecID test_cid = (MythCodecID)(kCodec_MPEG1_VAAPI + (stream_type - 1));
315  if (codec_is_vaapi(test_cid) && decoder == "vaapi" && !getenv("NO_VAAPI"))
316  use_cpu |= !VAAPIContext::IsFormatAccelerated(size, test_cid, fmt);
317  else
318  use_cpu = true;
319 
320  if (use_cpu)
321  return (MythCodecID)(kCodec_MPEG1 + (stream_type - 1));
322 
323  pix_fmt = fmt;
324  return test_cid;
325 }
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:42
void SetVideoRenderer(const QString &video_renderer)
virtual void InitPictureAttributes(void)
def scan(profile, smoonURL, gate)
Definition: scan.py:43
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
uint8_t * GetSurfaceIDPointer(void *buf)
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
bool CreateDisplay(QSize size, bool noreuse=false)
vaapi_context m_ctx
Definition: vaapicontext.h:62
bool ApproveDeintFilter(const QString &filtername) const
Approves bobdeint filter for XVideo and otherwise defers to VideoOutput::ApproveDeintFilter(const QSt...
safe_list_t * decoders
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 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
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)
uint8_t * GetSurfaceIDPointer(void *buf)
bool CreateBuffer(int width, int height, uint num, void *data, VideoFrameType fmt)
void end_lock()
Definition: videobuffers.h:99
OpenGLVideo * gl_videochain
PictureAttribute
Definition: videoouttypes.h:85
float GetVideoAspect(void) const
MythRenderOpenGL * gl_context
void InitPictureAttributes(VideoColourSpace &colourspace)
void EmbedInWidget(const QRect &rect)
Tells video output to embed video in an existing window.
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