00001 #include "videoout_openglvaapi.h"
00002 #include "vaapicontext.h"
00003
00004 #define LOC QString("VidOutGLVAAPI: ")
00005 #define ERR QString("VidOutGLVAAPI Error: ")
00006
00007 void VideoOutputOpenGLVAAPI::GetRenderOptions(render_opts &opts)
00008 {
00009 opts.renderers->append("openglvaapi");
00010
00011 (*opts.deints)["openglvaapi"].append("vaapionefield");
00012 (*opts.deints)["openglvaapi"].append("vaapibobdeint");
00013 (*opts.deints)["openglvaapi"].append("none");
00014 (*opts.osds)["openglvaapi"].append("opengl2");
00015
00016 if (opts.decoders->contains("vaapi"))
00017 (*opts.safe_renderers)["vaapi"].append("openglvaapi");
00018
00019 if (opts.decoders->contains("ffmpeg"))
00020 (*opts.safe_renderers)["ffmpeg"].append("openglvaapi");
00021
00022 (*opts.safe_renderers)["dummy"].append("openglvaapi");
00023 (*opts.safe_renderers)["nuppel"].append("openglvaapi");
00024
00025 opts.priorities->insert("openglvaapi", 110);
00026 }
00027
00028 VideoOutputOpenGLVAAPI::VideoOutputOpenGLVAAPI()
00029 : VideoOutputOpenGL(), m_ctx(NULL), m_pauseBuffer(NULL)
00030 {
00031 }
00032
00033 VideoOutputOpenGLVAAPI::~VideoOutputOpenGLVAAPI()
00034 {
00035 TearDown();
00036 }
00037
00038 void VideoOutputOpenGLVAAPI::TearDown(void)
00039 {
00040 DeleteVAAPIContext();
00041 }
00042
00043 bool VideoOutputOpenGLVAAPI::InputChanged(const QSize &input_size, float aspect,
00044 MythCodecID av_codec_id, void *codec_private,
00045 bool &aspect_only)
00046 {
00047 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("InputChanged(%1,%2,%3) %4->%5")
00048 .arg(input_size.width()).arg(input_size.height()).arg(aspect)
00049 .arg(toString(video_codec_id)).arg(toString(av_codec_id)));
00050
00051 if (!codec_is_vaapi(av_codec_id))
00052 return VideoOutputOpenGL::InputChanged(input_size, aspect, av_codec_id,
00053 codec_private, aspect_only);
00054
00055 QMutexLocker locker(&gl_context_lock);
00056
00057 bool wasembedding = window.IsEmbedding();
00058 QRect oldrect;
00059 if (wasembedding)
00060 {
00061 oldrect = window.GetEmbeddingRect();
00062 StopEmbedding();
00063 }
00064
00065 bool cid_changed = (video_codec_id != av_codec_id);
00066 bool res_changed = input_size != window.GetActualVideoDim();
00067 bool asp_changed = aspect != window.GetVideoAspect();
00068
00069 if (!res_changed && !cid_changed)
00070 {
00071 if (asp_changed)
00072 {
00073 aspect_only = true;
00074 VideoAspectRatioChanged(aspect);
00075 MoveResize();
00076 if (wasembedding)
00077 EmbedInWidget(oldrect);
00078 }
00079 return true;
00080 }
00081
00082 if (gCoreContext->IsUIThread())
00083 TearDown();
00084 else
00085 DestroyCPUResources();
00086
00087 QRect disp = window.GetDisplayVisibleRect();
00088 if (Init(input_size.width(), input_size.height(),
00089 aspect, gl_parent_win, disp, av_codec_id))
00090 {
00091 if (wasembedding)
00092 EmbedInWidget(oldrect);
00093 if (gCoreContext->IsUIThread())
00094 BestDeint();
00095 return true;
00096 }
00097
00098 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to re-initialise video output.");
00099 errorState = kError_Unknown;
00100
00101 return false;
00102 }
00103
00104 bool VideoOutputOpenGLVAAPI::Init(int width, int height, float aspect,
00105 WId winid, const QRect &win_rect,
00106 MythCodecID codec_id)
00107 {
00108 bool ok = VideoOutputOpenGL::Init(width, height, aspect, winid,
00109 win_rect, codec_id);
00110 if (ok && codec_is_vaapi(video_codec_id))
00111 return CreateVAAPIContext(window.GetActualVideoDim());
00112 return ok;
00113 }
00114
00115 bool VideoOutputOpenGLVAAPI::CreateVAAPIContext(QSize size)
00116 {
00117
00118
00119
00120
00121
00122 OpenGLLocker ctx_lock(gl_context);
00123
00124 if (m_ctx)
00125 DeleteVAAPIContext();
00126
00127 m_ctx = new VAAPIContext(kVADisplayGLX, video_codec_id);
00128 if (m_ctx && m_ctx->CreateDisplay(size) && m_ctx->CreateBuffers())
00129 {
00130 int num_buffers = m_ctx->GetNumBuffers();
00131 const QSize video_dim = window.GetActualVideoDim();
00132
00133 bool ok = true;
00134 for (int i = 0; i < num_buffers; i++)
00135 {
00136 ok &= vbuffers.CreateBuffer(video_dim.width(),
00137 video_dim.height(), i,
00138 m_ctx->GetVideoSurface(i),
00139 FMT_VAAPI);
00140 }
00141 InitPictureAttributes();
00142 return ok;
00143 }
00144
00145 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VAAPI context.");
00146 errorState = kError_Unknown;
00147 return false;
00148 }
00149
00150 void VideoOutputOpenGLVAAPI::DeleteVAAPIContext(void)
00151 {
00152 QMutexLocker locker(&gl_context_lock);
00153 delete m_ctx;
00154 m_ctx = NULL;
00155 }
00156
00157 bool VideoOutputOpenGLVAAPI::CreateBuffers(void)
00158 {
00159 QMutexLocker locker(&gl_context_lock);
00160 if (codec_is_vaapi(video_codec_id))
00161 {
00162 vbuffers.Init(24, true, 2, 1, 4, 1);
00163 return true;
00164 }
00165 return VideoOutputOpenGL::CreateBuffers();
00166 }
00167
00168 void* VideoOutputOpenGLVAAPI::GetDecoderContext(unsigned char* buf, uint8_t*& id)
00169 {
00170 if (m_ctx)
00171 {
00172 id = GetSurfaceIDPointer(buf);
00173 return &m_ctx->m_ctx;
00174 }
00175 return NULL;
00176 }
00177
00178 uint8_t* VideoOutputOpenGLVAAPI::GetSurfaceIDPointer(void* buf)
00179 {
00180 if (m_ctx)
00181 return m_ctx->GetSurfaceIDPointer(buf);
00182 return NULL;
00183 }
00184
00185 void VideoOutputOpenGLVAAPI::SetProfile(void)
00186 {
00187 if (db_vdisp_profile)
00188 db_vdisp_profile->SetVideoRenderer("openglvaapi");
00189 }
00190
00191 bool VideoOutputOpenGLVAAPI::ApproveDeintFilter(const QString &filtername) const
00192 {
00193 return filtername.contains("vaapi");
00194 }
00195
00196 bool VideoOutputOpenGLVAAPI::SetDeinterlacingEnabled(bool enable)
00197 {
00198 m_deinterlacing = enable;
00199 SetupDeinterlace(enable);
00200 return m_deinterlacing;
00201 }
00202
00203 bool VideoOutputOpenGLVAAPI::SetupDeinterlace(bool i, const QString& ovrf)
00204 {
00205
00206
00207 m_deinterlacing = i;
00208 return m_deinterlacing;
00209 }
00210
00211 void VideoOutputOpenGLVAAPI::InitPictureAttributes(void)
00212 {
00213 if (codec_is_vaapi(video_codec_id))
00214 {
00215 if (m_ctx)
00216 m_ctx->InitPictureAttributes(videoColourSpace);
00217 return;
00218 }
00219 VideoOutputOpenGL::InitPictureAttributes();
00220 }
00221
00222 int VideoOutputOpenGLVAAPI::SetPictureAttribute(PictureAttribute attribute,
00223 int newValue)
00224 {
00225 int val = newValue;
00226 if (codec_is_vaapi(video_codec_id) && m_ctx)
00227 val = m_ctx->SetPictureAttribute(attribute, newValue);
00228 return VideoOutput::SetPictureAttribute(attribute, val);
00229 }
00230
00231 void VideoOutputOpenGLVAAPI::UpdatePauseFrame(int64_t &disp_timecode)
00232 {
00233 if (codec_is_std(video_codec_id))
00234 {
00235 VideoOutputOpenGL::UpdatePauseFrame(disp_timecode);
00236 return;
00237 }
00238
00239 vbuffers.begin_lock(kVideoBuffer_used);
00240 if (vbuffers.size(kVideoBuffer_used))
00241 {
00242 VideoFrame *frame = vbuffers.head(kVideoBuffer_used);
00243 m_pauseBuffer = frame->buf;
00244 disp_timecode = frame->disp_timecode;
00245 }
00246 else
00247 LOG(VB_PLAYBACK, LOG_WARNING, LOC +
00248 "Could not update pause frame - no used frames.");
00249
00250 vbuffers.end_lock();
00251 }
00252
00253 void VideoOutputOpenGLVAAPI::ProcessFrame(VideoFrame *frame, OSD *osd,
00254 FilterChain *filterList,
00255 const PIPMap &pipPlayers,
00256 FrameScanType scan)
00257 {
00258 QMutexLocker locker(&gl_context_lock);
00259 VideoOutputOpenGL::ProcessFrame(frame, osd, filterList, pipPlayers, scan);
00260
00261 if (codec_is_vaapi(video_codec_id) && m_ctx && gl_videochain)
00262 {
00263 gl_context->makeCurrent();
00264 m_ctx->CopySurfaceToTexture(frame ? frame->buf : m_pauseBuffer,
00265 gl_videochain->GetInputTexture(),
00266 gl_videochain->GetTextureType(), scan);
00267 gl_videochain->SetInputUpdated();
00268 gl_context->doneCurrent();
00269 }
00270 }
00271
00272 QStringList VideoOutputOpenGLVAAPI::GetAllowedRenderers(
00273 MythCodecID myth_codec_id, const QSize &video_dim)
00274 {
00275 (void) video_dim;
00276 QStringList list;
00277 if ((codec_is_std(myth_codec_id) || (codec_is_vaapi(myth_codec_id))) &&
00278 !getenv("NO_VAAPI"))
00279 {
00280 list += "openglvaapi";
00281 }
00282 return list;
00283 }
00284
00285 MythCodecID VideoOutputOpenGLVAAPI::GetBestSupportedCodec(
00286 uint width, uint height, const QString &decoder,
00287 uint stream_type, bool no_acceleration,
00288 PixelFormat &pix_fmt)
00289 {
00290 QSize size(width, height);
00291 bool use_cpu = no_acceleration;
00292 PixelFormat fmt = PIX_FMT_YUV420P;
00293 MythCodecID test_cid = (MythCodecID)(kCodec_MPEG1_VAAPI + (stream_type - 1));
00294 if (codec_is_vaapi(test_cid) && decoder == "vaapi" && !getenv("NO_VAAPI"))
00295 use_cpu |= !VAAPIContext::IsFormatAccelerated(size, test_cid, fmt);
00296 else
00297 use_cpu = true;
00298
00299 if (use_cpu)
00300 return (MythCodecID)(kCodec_MPEG1 + (stream_type - 1));
00301
00302 pix_fmt = fmt;
00303 return test_cid;
00304 }