MythTV  0.26-pre
videoout_openglvaapi.cpp
Go to the documentation of this file.
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     // FIXME During a video stream change this is called from the decoder
00118     // thread - which breaks all other efforts to remove non-UI thread
00119     // access to the OpenGL context. There is no obvious fix however - if we
00120     // don't delete and re-create the VAAPI decoder context immediately then
00121     // the decoder fails and playback exits.
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     //m_deintfiltername = !db_vdisp_profile ? "" :
00206     //                     db_vdisp_profile->GetFilteredDeint(ovrf);
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends