MythTV  0.28pre
videoout_openglvaapi.cpp
Go to the documentation of this file.
1 #include "videoout_openglvaapi.h"
2 #include "mythrender_opengl.h"
3 #include "openglvideo.h"
4 #include "vaapicontext.h"
5 #include "mythpainter.h"
6 
7 #define LOC QString("VidOutGLVAAPI: ")
8 #define ERR QString("VidOutGLVAAPI Error: ")
9 
11 {
12  opts.renderers->append("openglvaapi");
13 
14  (*opts.deints)["openglvaapi"].append("vaapionefield");
15  (*opts.deints)["openglvaapi"].append("vaapibobdeint");
16  (*opts.deints)["openglvaapi"].append("none");
17  (*opts.osds)["openglvaapi"].append("opengl2");
18 
19  if (opts.decoders->contains("vaapi"))
20  (*opts.safe_renderers)["vaapi"].append("openglvaapi");
21 
22  if (opts.decoders->contains("ffmpeg"))
23  (*opts.safe_renderers)["ffmpeg"].append("openglvaapi");
24 
25  (*opts.safe_renderers)["dummy"].append("openglvaapi");
26  (*opts.safe_renderers)["nuppel"].append("openglvaapi");
27 
28  opts.priorities->insert("openglvaapi", 110);
29 }
30 
32  : VideoOutputOpenGL(), m_ctx(NULL), m_pauseBuffer(NULL)
33 {
34 }
35 
37 {
38  TearDown();
39 }
40 
42 {
44 }
45 
46 bool VideoOutputOpenGLVAAPI::InputChanged(const QSize &video_dim_buf,
47  const QSize &video_dim_disp,
48  float aspect,
49  MythCodecID av_codec_id, void *codec_private,
50  bool &aspect_only)
51 {
52  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputChanged(%1,%2,%3) %4->%5")
53  .arg(video_dim_disp.width()).arg(video_dim_disp.height())
54  .arg(aspect)
55  .arg(toString(video_codec_id)).arg(toString(av_codec_id)));
56 
57  if (!codec_is_vaapi(av_codec_id))
58  return VideoOutputOpenGL::InputChanged(video_dim_buf, video_dim_disp,
59  aspect, av_codec_id,
60  codec_private, aspect_only);
61 
62  QMutexLocker locker(&gl_context_lock);
63 
64  bool wasembedding = window.IsEmbedding();
65  QRect oldrect;
66  if (wasembedding)
67  {
68  oldrect = window.GetEmbeddingRect();
69  StopEmbedding();
70  }
71 
72  bool cid_changed = (video_codec_id != av_codec_id);
73  bool res_changed = video_dim_disp != window.GetActualVideoDim();
74  bool asp_changed = aspect != window.GetVideoAspect();
75 
76  if (!res_changed && !cid_changed)
77  {
78  if (asp_changed)
79  {
80  aspect_only = true;
82  MoveResize();
83  if (wasembedding)
84  EmbedInWidget(oldrect);
85  }
86  return true;
87  }
88 
89  if (gCoreContext->IsUIThread())
90  TearDown();
91  else
93 
94  QRect disp = window.GetDisplayVisibleRect();
95  if (Init(video_dim_buf, video_dim_disp,
96  aspect, gl_parent_win, disp, av_codec_id))
97  {
98  if (wasembedding)
99  EmbedInWidget(oldrect);
100  if (gCoreContext->IsUIThread())
101  BestDeint();
102  return true;
103  }
104 
105  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to re-initialise video output.");
107 
108  return false;
109 }
110 
111 bool VideoOutputOpenGLVAAPI::Init(const QSize &video_dim_buf,
112  const QSize &video_dim_disp,
113  float aspect,
114  WId winid, const QRect &win_rect,
115  MythCodecID codec_id)
116 {
117  bool ok = VideoOutputOpenGL::Init(video_dim_buf, video_dim_disp,
118  aspect, winid,
119  win_rect, codec_id);
120  if (ok && codec_is_vaapi(video_codec_id))
122  return ok;
123 }
124 
126 {
127  // FIXME During a video stream change this is called from the decoder
128  // thread - which breaks all other efforts to remove non-UI thread
129  // access to the OpenGL context. There is no obvious fix however - if we
130  // don't delete and re-create the VAAPI decoder context immediately then
131  // the decoder fails and playback exits.
132 
133  // lvr 27-oct-13
134  // in 0.27 if m_ctx->CreateDisplay is called outside of the UI thread then
135  // it fails, which then causes subsequent unbalanced calls to doneCurrent
136  // which results in Qt aborting. So just fail if non-UI.
137  if (!gCoreContext->IsUIThread())
138  {
139  LOG(VB_GENERAL, LOG_ERR, LOC +
140  "CreateVAAPIContext called from non-UI thread");
141  return false;
142  }
143 
144  OpenGLLocker ctx_lock(gl_context);
145 
146  if (m_ctx)
148 
150  if (m_ctx && m_ctx->CreateDisplay(size) && 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 }
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.
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:80
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)
__u64 val
Definition: videodev2.h:1041
uint8_t * GetSurfaceIDPointer(void *buf)
bool CreateBuffer(int width, int height, uint num, void *data, VideoFrameType fmt)
void end_lock()
Definition: videobuffers.h:100
OpenGLVideo * gl_videochain
PictureAttribute
Definition: videoouttypes.h:89
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.
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)
GLint GLenum GLsizei width
int64_t disp_timecode
Definition: mythframe.h:45
uint Size(BufferType type) const
typedef void(APIENTRY *MYTH_GLTEXIMAGE1DPROC)(GLenum target
static const char * toString(OMX_AUDIO_DDPBITSTREAMID id)
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
__u32 height
Definition: videodev2.h:1039
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