|
MythTV
0.26-pre
|
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 }
1.7.6.1