Ticket #8593: vaapi-working.diff
| File vaapi-working.diff, 37.9 KB (added by markk, 11 months ago) |
|---|
-
mythtv/configure
diff --git a/mythtv/configure b/mythtv/configure index 667aadc..b5165f6 100755
a b Advanced options (experts only): 122 122 --disable-xv disable XVideo (X11 video output accel.) 123 123 --enable-vdpau enable NVidia VDPAU hardware acceleration. 124 124 --enable-crystalhd enable Broadcom CrystalHD hardware decoder support 125 --enablevaapi enable VAAPI hardware accelerated video decoding 125 126 --enable-dxva2 enable hardware accelerated decoding on windows 126 127 --disable-opengl-video disable OpenGL based video display 127 128 --disable-quartz-video disable Mac OS X CoreVideo based video display … … USING_LIST=' 1399 1400 dxva2 1400 1401 opengl 1401 1402 opengles 1403 vaapi 1402 1404 vdpau 1403 1405 ' 1404 1406 … … v4l1_deps="backend v4l2 linux_videodev_h" 1775 1777 vdpau_deps="opengl vdpau_vdpau_h vdpau_vdpau_x11_h" 1776 1778 xrandr_deps="x11" 1777 1779 xv_deps="x11" 1780 vaapi_deps="x11 opengl" 1778 1781 asi_deps="backend" 1779 1782 1780 1783 <<BLOCKQUOTE … … check_header sys/select.h 3635 3638 check_header termios.h 3636 3639 check_header vdpau/vdpau.h 3637 3640 check_header vdpau/vdpau_x11.h 3641 check_header va/va.h 3642 check_header va/va_x11.h 3643 check_header va/va_glx.h 3638 3644 3639 3645 check_struct dxva2api.h DXVA_PictureParameters wDecodedPictureIndex 3640 3646 … … if enabled crystalhd; then 3914 3920 disable crystalhd; 3915 3921 fi 3916 3922 3923 if enabled vaapi; then 3924 enabled va_va_h && enabled va_va_glx_h && enabled va_va_x11_h || disable vaapi 3925 if enabled vaapi; then 3926 # TODO check for SDS versions 3927 check_cpp_condition va/va.h "VA_VERSION_HEX >= 0x001F0000" || 3928 { echolog "VAAPI requires libva >= 0.31.1" && disable vaapi; } 3929 fi 3930 else 3931 disable vaapi 3932 fi 3933 3917 3934 if enabled dxva2; then 3918 3935 enabled dxva2api_h && enabled windows || disable dxva2 3919 3936 else … … if enabled x11 ; then 4473 4490 echo "xrandr support ${xrandr-no}" 4474 4491 echo "xv support ${xv-no}" 4475 4492 echo "VDPAU support ${vdpau-no}" 4493 echo "VAAPI support ${vaapi-no}" 4476 4494 echo "CrystalHD support ${crystalhd-no}" 4477 4495 fi 4478 4496 echo "OpenGL video ${opengl_video-no}" -
mythtv/libs/libmythtv/avformatdecoder.cpp
diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp index d18dcf6..788154c 100644
a b extern "C" { 53 53 #include "videoout_d3d.h" 54 54 #endif 55 55 56 #ifdef USING_VAAPI 57 #include "videoout_openglvaapi.h" 58 #include "vaapicontext.h" 59 #endif // USING_VAAPI 60 56 61 extern "C" { 57 62 #include "libavutil/avutil.h" 58 63 #include "libavcodec/ac3_parser.h" … … void release_avf_buffer_vdpau(struct AVCodecContext *c, AVFrame *pic); 125 130 void render_slice_vdpau(struct AVCodecContext *s, const AVFrame *src, 126 131 int offset[4], int y, int type, int height); 127 132 int get_avf_buffer_dxva2(struct AVCodecContext *c, AVFrame *pic); 133 int get_avf_buffer_vaapi(struct AVCodecContext *c, AVFrame *pic); 128 134 129 135 static AVCodec *find_vdpau_decoder(AVCodec *c, enum CodecID id) 130 136 { … … void AvFormatDecoder::GetDecoders(render_opts &opts) 238 244 (*opts.equiv_decoders)["dxva2"].append("dummy"); 239 245 #endif 240 246 247 #ifdef USING_VAAPI 248 opts.decoders->append("vaapi"); 249 (*opts.equiv_decoders)["vaapi"].append("dummy"); 250 #endif 251 241 252 PrivateDecoder::GetDecoders(opts); 242 253 } 243 254 … … void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc, 1275 1286 enc->get_format = get_format_dxva2; 1276 1287 enc->release_buffer = release_avf_buffer; 1277 1288 } 1289 else if (CODEC_IS_VAAPI(codec, enc)) 1290 { 1291 enc->get_buffer = get_avf_buffer_vaapi; 1292 enc->get_format = get_format_vaapi; 1293 enc->release_buffer = release_avf_buffer; 1294 enc->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD; 1295 } 1278 1296 else if (codec && codec->capabilities & CODEC_CAP_DR1) 1279 1297 { 1280 1298 enc->flags |= CODEC_FLAG_EMU_EDGE; … … int AvFormatDecoder::ScanStreams(bool novideo) 1810 1828 handled = true; 1811 1829 } 1812 1830 #endif // USING_VDPAU 1831 #ifdef USING_VAAPI 1832 MythCodecID vaapi_mcid; 1833 PixelFormat pix_fmt = PIX_FMT_YUV420P; 1834 vaapi_mcid = VideoOutputOpenGLVAAPI::GetBestSupportedCodec( 1835 width, height, mpeg_version(enc->codec_id), 1836 no_hardware_decoders, pix_fmt); 1837 1838 if (vaapi_mcid >= video_codec_id) 1839 { 1840 enc->codec_id = (CodecID)myth2av_codecid(vaapi_mcid); 1841 video_codec_id = vaapi_mcid; 1842 handled = true; 1843 if (!no_hardware_decoders && 1844 codec_is_vaapi(video_codec_id)) 1845 { 1846 enc->pix_fmt = pix_fmt; 1847 } 1848 } 1849 #endif // USING_VAAPI 1813 1850 #ifdef USING_DXVA2 1814 1851 MythCodecID dxva2_mcid; 1815 1852 PixelFormat pix_fmt = PIX_FMT_YUV420P; … … int get_avf_buffer_dxva2(struct AVCodecContext *c, AVFrame *pic) 2399 2436 return 0; 2400 2437 } 2401 2438 2439 int get_avf_buffer_vaapi(struct AVCodecContext *c, AVFrame *pic) 2440 { 2441 AvFormatDecoder *nd = (AvFormatDecoder *)(c->opaque); 2442 VideoFrame *frame = nd->GetPlayer()->GetNextVideoFrame(); 2443 2444 pic->data[0] = frame->buf; 2445 pic->data[1] = NULL; 2446 pic->data[2] = NULL; 2447 pic->data[3] = NULL; 2448 pic->linesize[0] = 0; 2449 pic->linesize[1] = 0; 2450 pic->linesize[2] = 0; 2451 pic->linesize[3] = 0; 2452 pic->opaque = frame; 2453 pic->type = FF_BUFFER_TYPE_USER; 2454 pic->age = 256 * 256 * 256 * 64; 2455 frame->pix_fmt = c->pix_fmt; 2456 2457 #ifdef USING_VAAPI 2458 if (nd->GetPlayer()->getVideoOutput()) 2459 { 2460 VideoOutputOpenGLVAAPI *vo = 2461 dynamic_cast<VideoOutputOpenGLVAAPI*>(nd->GetPlayer()->getVideoOutput()); 2462 c->hwaccel_context = (vaapi_context*)vo->GetVAAPIContext(); 2463 pic->data[3] = vo->GetSurfaceIDPointer(frame->buf); 2464 } 2465 #endif 2466 2467 return 0; 2468 } 2469 2402 2470 void AvFormatDecoder::DecodeDTVCC(const uint8_t *buf, uint len) 2403 2471 { 2404 2472 if (!len) -
mythtv/libs/libmythtv/libmythtv.pro
diff --git a/mythtv/libs/libmythtv/libmythtv.pro b/mythtv/libs/libmythtv/libmythtv.pro index 7f03f79..f87d629 100644
a b using_frontend { 370 370 using_opengl_video:HEADERS += openglvideo.h videoout_opengl.h 371 371 using_opengl_video:SOURCES += openglvideo.cpp videoout_opengl.cpp 372 372 373 using_vaapi: DEFINES += USING_VAAPI 374 using_vaapi: DEFINES += vaapicontext.h videoout_openglvaapi.h 375 using_vaapi: SOURCES += vaapicontext.cpp videoout_openglvaapi.cpp 376 using_vaapi: LIBS += -lva -lva-x11 -lva-glx 377 373 378 # Misc. frontend 374 379 HEADERS += DetectLetterbox.h 375 380 SOURCES += DetectLetterbox.cpp -
mythtv/libs/libmythtv/videodisplayprofile.cpp
diff --git a/mythtv/libs/libmythtv/videodisplayprofile.cpp b/mythtv/libs/libmythtv/videodisplayprofile.cpp index f78c5c1..bb31bb0 100644
a b QString VideoDisplayProfile::GetDecoderName(const QString &decoder) 639 639 dec_name["ffmpeg"] = QObject::tr("Standard"); 640 640 dec_name["macaccel"] = QObject::tr("Mac hardware acceleration"); 641 641 dec_name["vdpau"] = QObject::tr("NVidia VDPAU acceleration"); 642 dec_name["vaapi"] = QObject::tr("VAAPI acceleration"); 642 643 dec_name["dxva2"] = QObject::tr("Windows hardware acceleration"); 643 644 } 644 645 … … QString VideoDisplayProfile::GetDecoderHelp(QString decoder) 680 681 "accelerate video decoding and playback " 681 682 "(requires Windows Vista or later)."); 682 683 684 if (decoder == "vaapi") 685 msg += QObject::tr( 686 "VAAPI will attempt to use the graphics hardware to " 687 "accelerate video decoding."); 683 688 return msg; 684 689 } 685 690 … … QString VideoDisplayProfile::GetDeinterlacerName(const QString short_name) 737 742 return QObject::tr("Advanced (1x, HW)"); 738 743 else if ("vdpauadvanceddoublerate" == short_name) 739 744 return QObject::tr("Advanced (2x, HW)"); 745 else if ("vaapionefield" == short_name) 746 return QObject::tr("One Field (1x, HW)"); 747 else if ("vaapibobdeint" == short_name) 748 return QObject::tr("Bob (2x, HW)"); 740 749 741 750 return ""; 742 751 } … … QString VideoDisplayProfile::GetVideoRendererHelp(const QString &renderer) 1167 1176 "This is the only video renderer for NVidia VDPAU decoding."); 1168 1177 } 1169 1178 1179 if (renderer == "openglvaapi") 1180 { 1181 msg = QObject::tr( 1182 "This video renderer uses VAAPI for video decoding and " 1183 "OpenGL for scaling and color conversion."); 1184 } 1185 1170 1186 return msg; 1171 1187 } 1172 1188 … … QString VideoDisplayProfile::GetDeinterlacerHelp(const QString &deint) 1300 1316 msg = kBasicMsg + " " + kDoubleRateMsg + " " + kUsingGPU; 1301 1317 else if (deint == "vdpauadvanceddoublerate") 1302 1318 msg = kAdvMsg + " " + kDoubleRateMsg + " " + kUsingGPU; 1319 else if (deint == "vaapionefield") 1320 msg = kOneFieldMsg + " " + kUsingGPU; 1321 else if (deint == "vaapibobdeint") 1322 msg = kBobMsg + " " + kUsingGPU; 1303 1323 else 1304 1324 msg = QObject::tr("'%1' has not been documented yet.").arg(deint); 1305 1325 -
mythtv/libs/libmythtv/videoout_opengl.cpp
diff --git a/mythtv/libs/libmythtv/videoout_opengl.cpp b/mythtv/libs/libmythtv/videoout_opengl.cpp index 6ff024b..50e823b 100644
a b bool VideoOutputOpenGL::SetupContext(void) 213 213 return false; 214 214 } 215 215 216 //gl_context = dynamic_cast<MythRenderOpenGL*>(win->GetRenderDevice());216 gl_context = dynamic_cast<MythRenderOpenGL*>(win->GetRenderDevice()); 217 217 if (gl_context) 218 218 { 219 219 gl_context->UpRef(); -
mythtv/libs/libmythtv/videooutbase.cpp
diff --git a/mythtv/libs/libmythtv/videooutbase.cpp b/mythtv/libs/libmythtv/videooutbase.cpp index 158fce8..3ab5b9e 100644
a b 36 36 #include "videoout_vdpau.h" 37 37 #endif 38 38 39 #ifdef USING_VAAPI 40 #include "videoout_openglvaapi.h" 41 #endif 42 39 43 #include "videoout_null.h" 40 44 #include "dithertable.h" 41 45 … … void VideoOutput::GetRenderOptions(render_opts &opts) 88 92 #ifdef USING_VDPAU 89 93 VideoOutputVDPAU::GetRenderOptions(opts); 90 94 #endif // USING_VDPAU 95 96 #ifdef USING_VAAPI 97 VideoOutputOpenGLVAAPI::GetRenderOptions(opts); 98 #endif // USING_VAAPI 91 99 } 92 100 93 101 /** … … VideoOutput *VideoOutput::Create( 131 139 renderers += VideoOutputVDPAU::GetAllowedRenderers(codec_id, video_dim); 132 140 #endif // USING_VDPAU 133 141 142 #ifdef USING_VAAPI 143 const QStringList vaapilist 144 = VideoOutputOpenGLVAAPI::GetAllowedRenderers(codec_id, video_dim); 145 renderers += vaapilist; 146 #endif // USING_VAAPI 147 134 148 VERBOSE(VB_PLAYBACK, LOC + "Allowed renderers: " + 135 149 to_comma_list(renderers)); 136 150 … … VideoOutput *VideoOutput::Create( 188 202 vo = new VideoOutputVDPAU(); 189 203 #endif // USING_VDPAU 190 204 205 #ifdef USING_VAAPI 206 if (renderer == "openglvaapi") 207 vo = new VideoOutputOpenGLVAAPI(); 208 #endif // USING_VAAPI 209 191 210 #ifdef USING_XV 192 211 if (xvlist.contains(renderer)) 193 212 vo = new VideoOutputXv(); -
new file mythtv/libs/libmythtv/vaapicontext.cpp
diff --git a/mythtv/libs/libmythtv/vaapicontext.cpp b/mythtv/libs/libmythtv/vaapicontext.cpp new file mode 100644 index 0000000..b698c8e
- + 1 #include "openglvideo.h" 2 #include "mythverbose.h" 3 #include "mythxdisplay.h" 4 #include "mythcodecid.h" 5 #include "frame.h" 6 #include "vaapicontext.h" 7 #include "mythmainwindow.h" 8 9 #define LOC QString("VAAPI: ") 10 #define ERR QString("VAAPI Error: ") 11 #define NUM_VAAPI_BUFFERS 24 12 13 #define INIT_ST \ 14 VAStatus va_status; \ 15 bool ok = true; 16 17 #define CHECK_ST \ 18 ok &= (va_status == VA_STATUS_SUCCESS); \ 19 if (!ok) { \ 20 VERBOSE(VB_IMPORTANT, ERR + QString("Error at %1:%2 (#%3, %4)") \ 21 .arg(__FILE__).arg( __LINE__).arg(va_status) \ 22 .arg(vaErrorStr(va_status))); \ 23 } 24 25 #define CREATE_CHECK(arg1, arg2) \ 26 if (ok) \ 27 { \ 28 ok = arg1; \ 29 if (!ok) \ 30 VERBOSE(VB_IMPORTANT, ERR + arg2); \ 31 } 32 33 QString profileToString(VAProfile profile); 34 QString entryToString(VAEntrypoint entry); 35 VAProfile preferredProfile(MythCodecID codec); 36 37 QString profileToString(VAProfile profile) 38 { 39 if (VAProfileMPEG2Simple == profile) return "MPEG2Simple"; 40 if (VAProfileMPEG2Main == profile) return "MPEG2Main"; 41 if (VAProfileMPEG4Simple == profile) return "MPEG4Simple"; 42 if (VAProfileMPEG4AdvancedSimple == profile) return "MPEG4AdvSimple"; 43 if (VAProfileMPEG4Main == profile) return "MPEG4Main"; 44 if (VAProfileH264Baseline == profile) return "H264Base"; 45 if (VAProfileH264Main == profile) return "H264Main"; 46 if (VAProfileH264High == profile) return "H264High"; 47 if (VAProfileVC1Simple == profile) return "VC1Simple"; 48 if (VAProfileVC1Main == profile) return "VC1Main"; 49 if (VAProfileVC1Advanced == profile) return "VC1Advanced"; 50 if (VAProfileH263Baseline == profile) return "H263Base"; 51 return "Unknown"; 52 } 53 54 QString entryToString(VAEntrypoint entry) 55 { 56 if (VAEntrypointVLD == entry) return "VLD "; 57 if (VAEntrypointIZZ == entry) return "IZZ (UNSUPPORTED) "; 58 if (VAEntrypointIDCT == entry) return "IDCT (UNSUPPORTED) "; 59 if (VAEntrypointMoComp == entry) return "MC (UNSUPPORTED) "; 60 if (VAEntrypointDeblocking == entry) return "Deblock (UNSUPPORTED) "; 61 if (VAEntrypointEncSlice == entry) return "EncSlice (UNSUPPORTED) "; 62 return "Unknown"; 63 } 64 65 VAProfile preferredProfile(MythCodecID codec) 66 { 67 // FIXME handle unsupported codecs properly 68 if (kCodec_H263_VAAPI == codec) return VAProfileMPEG4AdvancedSimple; 69 if (kCodec_MPEG4_VAAPI == codec) return VAProfileMPEG4AdvancedSimple; 70 if (kCodec_H264_VAAPI == codec) return VAProfileH264High; 71 if (kCodec_VC1_VAAPI == codec) return VAProfileVC1Advanced; 72 if (kCodec_WMV3_VAAPI == codec) return VAProfileVC1Main; 73 return VAProfileMPEG2Main; 74 } 75 76 class VAAPIDisplay 77 { 78 protected: 79 VAAPIDisplay() : m_va_disp(NULL), m_x_disp(NULL), m_ref_count(0) { } 80 public: 81 ~VAAPIDisplay() 82 { 83 if (m_va_disp) 84 { 85 INIT_ST 86 XLOCK(m_x_disp, va_status = vaTerminate(m_va_disp)); 87 CHECK_ST 88 } 89 if (m_x_disp) 90 { 91 m_x_disp->Sync(true); 92 delete m_x_disp; 93 } 94 } 95 96 bool Create(void) 97 { 98 MythMainWindow *mw = GetMythMainWindow(); 99 if (!mw) 100 return false; 101 102 MythRenderOpenGL *gl = static_cast<MythRenderOpenGL*>(mw->GetRenderDevice()); 103 if (!gl) 104 { 105 VERBOSE(VB_PLAYBACK, LOC + 106 QString("Failed to get OpenGL context - you must use the " 107 "OpenGL UI painter for VAAPI support.")); 108 return false; 109 } 110 gl->makeCurrent(); 111 display = glXGetCurrentDisplay(); 112 gl->doneCurrent(); 113 114 m_x_disp = OpenMythXDisplay(); 115 if (!m_x_disp) 116 return false; 117 118 MythXLocker locker(m_x_disp); 119 int major_ver, minor_ver; 120 121 //m_va_disp = vaGetDisplayGLX(m_x_disp->GetDisplay()); 122 m_va_disp = vaGetDisplayGLX(display); 123 124 if (!m_va_disp) 125 { 126 VERBOSE(VB_IMPORTANT, ERR + "Failed to create VADisplay"); 127 return false; 128 } 129 130 INIT_ST 131 va_status = vaInitialize(m_va_disp, &major_ver, &minor_ver); 132 CHECK_ST 133 134 static bool debugged = false; 135 if (ok && !debugged) 136 { 137 debugged = true; 138 VERBOSE(VB_IMPORTANT, LOC + QString("Version: %1.%2") 139 .arg(major_ver).arg(minor_ver)); 140 VERBOSE(VB_IMPORTANT, LOC + QString("Vendor : %1") 141 .arg(vaQueryVendorString(m_va_disp))); 142 } 143 if (ok) 144 { 145 UpRef(); 146 VERBOSE(VB_PLAYBACK, LOC + QString("Created VAAPI GLX display")); 147 } 148 return ok; 149 } 150 151 void UpRef(void) 152 { 153 XLOCK(m_x_disp, m_ref_count++) 154 } 155 156 void DownRef(void) 157 { 158 m_x_disp->Lock(); 159 m_ref_count--; 160 if (m_ref_count <= 0) 161 { 162 if (gVAAPIDisplay == this) 163 gVAAPIDisplay = NULL; 164 VERBOSE(VB_PLAYBACK, LOC + "Deleting VAAPI display."); 165 m_x_disp->Unlock(); 166 delete this; 167 return; 168 } 169 m_x_disp->Unlock(); 170 } 171 172 static VAAPIDisplay* GetDisplay(void) 173 { 174 if (gVAAPIDisplay) 175 { 176 gVAAPIDisplay->UpRef(); 177 return gVAAPIDisplay; 178 } 179 180 gVAAPIDisplay = new VAAPIDisplay(); 181 if (gVAAPIDisplay && gVAAPIDisplay->Create()) 182 return gVAAPIDisplay; 183 184 delete gVAAPIDisplay; 185 gVAAPIDisplay = NULL; 186 return NULL; 187 } 188 189 static VAAPIDisplay *gVAAPIDisplay; 190 void *m_va_disp; 191 MythXDisplay *m_x_disp; 192 Display *display; 193 int m_ref_count; 194 }; 195 196 VAAPIDisplay* VAAPIDisplay::gVAAPIDisplay = NULL; 197 198 bool VAAPIContext::IsFormatAccelerated(QSize size, MythCodecID codec, 199 PixelFormat &pix_fmt) 200 { 201 bool result = false; 202 VAAPIContext *ctx = new VAAPIContext(codec); 203 if (ctx && ctx->CreateDisplay(size)) 204 { 205 pix_fmt = ctx->GetPixelFormat(); 206 result = pix_fmt == PIX_FMT_VAAPI_VLD; 207 } 208 delete ctx; 209 return result; 210 } 211 212 VAAPIContext::VAAPIContext(MythCodecID codec) 213 : m_codec(codec), 214 m_vaProfile(VAProfileMPEG2Main)/* ?? */, 215 m_vaEntrypoint(VAEntrypointEncSlice), 216 m_pix_fmt(PIX_FMT_YUV420P), m_numSurfaces(NUM_VAAPI_BUFFERS), 217 m_surfaces(NULL), m_surfaceData(NULL) 218 { 219 memset(&m_ctx, 0, sizeof(vaapi_context)); 220 } 221 222 VAAPIContext::~VAAPIContext() 223 { 224 if (m_display) 225 { 226 m_display->m_x_disp->Lock(); 227 228 for (int i = 0; i < m_numSurfaces && m_surfaceData; i++) 229 { 230 INIT_ST 231 va_status = vaDestroySurfaceGLX(m_ctx.display, 232 m_surfaceData[i].m_glx_surface); 233 CHECK_ST 234 } 235 236 INIT_ST 237 if (m_ctx.context_id) 238 { 239 va_status = vaDestroyContext(m_ctx.display, m_ctx.context_id); 240 CHECK_ST 241 } 242 if (m_ctx.config_id) 243 { 244 va_status = vaDestroyConfig(m_ctx.display, m_ctx.config_id); 245 CHECK_ST 246 } 247 if (m_surfaces) 248 { 249 va_status = vaDestroySurfaces(m_ctx.display, m_surfaces, m_numSurfaces); 250 CHECK_ST 251 } 252 } 253 254 if (m_surfaces) 255 delete [] m_surfaces; 256 if (m_surfaceData) 257 delete [] m_surfaceData; 258 259 if (m_display) 260 { 261 m_display->m_x_disp->Unlock(); 262 m_display->DownRef(); 263 } 264 265 VERBOSE(VB_PLAYBACK, LOC + "Deleted context"); 266 } 267 268 bool VAAPIContext::CreateDisplay(QSize size) 269 { 270 m_size = size; 271 bool ok = true; 272 m_display = VAAPIDisplay::GetDisplay(); 273 CREATE_CHECK(!m_size.isEmpty(), "Invalid size") 274 CREATE_CHECK(m_display != NULL, "Invalid display") 275 CREATE_CHECK(InitDisplay(), "Invalid VADisplay") 276 CREATE_CHECK(InitProfiles(), "No supported profiles") 277 if (ok) 278 VERBOSE(VB_PLAYBACK, LOC + QString("Created context (%1x%2->%3x%4)") 279 .arg(size.width()).arg(size.height()) 280 .arg(m_size.width()).arg(m_size.height())); 281 return ok; 282 } 283 284 bool VAAPIContext::CreateBuffers(void) 285 { 286 bool ok = true; 287 CREATE_CHECK(!m_size.isEmpty(), "Invalid size") 288 CREATE_CHECK(InitBuffers(), "Failed to create buffers.") 289 CREATE_CHECK(InitContext(), "Failed to create context") 290 if (ok) 291 VERBOSE(VB_PLAYBACK, LOC + QString("Created %1 buffers").arg(m_numSurfaces)); 292 return ok; 293 } 294 295 bool VAAPIContext::InitDisplay(void) 296 { 297 if (!m_display) 298 return false; 299 m_ctx.display = m_display->m_va_disp; 300 return m_ctx.display; 301 } 302 303 bool VAAPIContext::InitProfiles(void) 304 { 305 if (!(codec_is_vaapi(m_codec)) || !m_ctx.display) 306 return false; 307 308 MythXLocker locker(m_display->m_x_disp); 309 int max_profiles, max_entrypoints; 310 VAProfile profile_wanted = preferredProfile(m_codec); 311 VAProfile profile_found = VAProfileMPEG2Main; // FIXME 312 VAEntrypoint entry_found = VAEntrypointEncSlice; // unsupported value 313 314 max_profiles = vaMaxNumProfiles(m_ctx.display); 315 max_entrypoints = vaMaxNumEntrypoints(m_ctx.display); 316 VAProfile *profiles = new VAProfile[max_profiles]; 317 VAEntrypoint *entries = new VAEntrypoint[max_entrypoints]; 318 319 static bool debugged = false; 320 if (profiles && entries) 321 { 322 INIT_ST 323 int act_profiles, act_entries; 324 va_status = vaQueryConfigProfiles(m_ctx.display, 325 profiles, 326 &act_profiles); 327 CHECK_ST 328 if (ok && act_profiles > 0) 329 { 330 for (int i = 0; i < act_profiles; i++) 331 { 332 va_status = vaQueryConfigEntrypoints(m_ctx.display, 333 profiles[i], 334 entries, 335 &act_entries); 336 if (va_status == VA_STATUS_SUCCESS && act_entries > 0) 337 { 338 if (profiles[i] == profile_wanted) 339 { 340 profile_found = profile_wanted; 341 for (int j = 0; j < act_entries; j++) 342 if (entries[j] < entry_found) 343 entry_found = entries[j]; 344 } 345 346 if (!debugged) 347 { 348 QString entrylist = "Entrypoints: "; 349 for (int j = 0; j < act_entries; j++) 350 entrylist += entryToString(entries[j]); 351 VERBOSE(VB_IMPORTANT, LOC + QString("Profile: %1 %2") 352 .arg(profileToString(profiles[i])).arg(entrylist)); 353 } 354 } 355 } 356 } 357 debugged = true; 358 } 359 delete [] profiles; 360 delete [] entries; 361 362 VERBOSE(VB_PLAYBACK, LOC + QString("Desired profile for '%1': %2") 363 .arg(toString(m_codec)).arg(profileToString(profile_wanted))); 364 VERBOSE(VB_PLAYBACK, LOC + QString("Found profile %1 with entry %2") 365 .arg(profileToString(profile_found)).arg(entryToString(entry_found))); 366 367 if (profile_wanted != profile_found) 368 { 369 VERBOSE(VB_IMPORTANT, ERR + "Failed to find supported profile."); 370 return false; 371 } 372 373 if (entry_found > VAEntrypointVLD) 374 { 375 VERBOSE(VB_IMPORTANT, ERR + "Failed to find suitable entry point."); 376 return false; 377 } 378 379 m_vaProfile = profile_wanted; 380 m_vaEntrypoint = entry_found; 381 if (VAEntrypointVLD == m_vaEntrypoint) 382 m_pix_fmt = PIX_FMT_VAAPI_VLD; 383 return true; 384 } 385 386 bool VAAPIContext::InitBuffers(void) 387 { 388 if (!m_ctx.display) 389 return false; 390 391 MythXLocker locker(m_display->m_x_disp); 392 m_surfaces = new VASurfaceID[m_numSurfaces]; 393 m_surfaceData = new vaapi_surface[m_numSurfaces]; 394 395 if (!m_surfaces || !m_surfaceData) 396 return false; 397 398 memset(m_surfaces, 0, sizeof(m_surfaces)); 399 memset(m_surfaceData, 0, sizeof(m_surfaceData)); 400 401 INIT_ST 402 va_status = vaCreateSurfaces(m_ctx.display, m_size.width(), m_size.height(), 403 VA_RT_FORMAT_YUV420, m_numSurfaces, 404 m_surfaces); 405 CHECK_ST 406 407 for (int i = 0; i < m_numSurfaces; i++) 408 m_surfaceData[i].m_id = m_surfaces[i]; 409 return ok; 410 } 411 412 bool VAAPIContext::CreateGLXSurfaces(uint tex, uint type) 413 { 414 if (!m_ctx.display || !m_surfaces || !m_surfaceData) 415 return false; 416 417 void * glx_surface = NULL; 418 INIT_ST 419 va_status = vaCreateSurfaceGLX(m_ctx.display, type, tex, &glx_surface); 420 CHECK_ST 421 422 for (int i = 0; i < m_numSurfaces; i++) 423 { 424 m_surfaceData[i].m_glx_surface = glx_surface; 425 } 426 return ok; 427 } 428 429 bool VAAPIContext::InitContext(void) 430 { 431 if (!m_ctx.display || m_vaEntrypoint > VAEntrypointVLD) 432 return false; 433 434 MythXLocker locker(m_display->m_x_disp); 435 VAConfigAttrib attrib; 436 attrib.type = VAConfigAttribRTFormat; 437 INIT_ST 438 va_status = vaGetConfigAttributes(m_ctx.display, m_vaProfile, 439 m_vaEntrypoint, &attrib, 1); 440 CHECK_ST 441 442 if (!ok || !(attrib.value & VA_RT_FORMAT_YUV420)) 443 { 444 VERBOSE(VB_IMPORTANT, ERR + "Failed to confirm YUV420 chroma"); 445 return false; 446 } 447 448 va_status = vaCreateConfig(m_ctx.display, m_vaProfile, m_vaEntrypoint, 449 &attrib, 1, &m_ctx.config_id); 450 CHECK_ST 451 if (!ok) 452 { 453 VERBOSE(VB_IMPORTANT, ERR + "Failed to create decoder config."); 454 return false; 455 } 456 457 va_status = vaCreateContext(m_ctx.display, m_ctx.config_id, 458 m_size.width(), m_size.height(), VA_PROGRESSIVE, 459 m_surfaces, m_numSurfaces, 460 &m_ctx.context_id); 461 CHECK_ST 462 if (!ok) 463 { 464 VERBOSE(VB_IMPORTANT, ERR + "Failed to create decoder context."); 465 return false; 466 } 467 return true; 468 } 469 470 void* VAAPIContext::GetVideoSurface(int i) 471 { 472 if (i < 0 || i >= m_numSurfaces) 473 return NULL; 474 return &m_surfaceData[i]; 475 } 476 477 uint8_t* VAAPIContext::GetSurfaceIDPointer(void* buf) 478 { 479 if (!buf) 480 return NULL; 481 482 const vaapi_surface *surf = (vaapi_surface*)buf; 483 if (!surf->m_id) 484 return NULL; 485 486 INIT_ST 487 va_status = vaSyncSurface(m_ctx.display, surf->m_id); 488 CHECK_ST 489 return (uint8_t*)(uintptr_t)surf->m_id; 490 } 491 492 bool VAAPIContext::CopySurfaceToTexture(const void* buf, FrameScanType scan) 493 { 494 if (!buf) 495 return false; 496 497 const vaapi_surface *surf = (vaapi_surface*)buf; 498 if (!surf) 499 return false; 500 if (!surf->m_glx_surface) 501 return false; 502 503 int field = VA_FRAME_PICTURE; 504 //if (scan == kScan_Interlaced) 505 // field = VA_TOP_FIELD; 506 //else if (scan == kScan_Intr2ndField) 507 // field = VA_BOTTOM_FIELD; 508 509 INIT_ST 510 va_status = vaSyncSurface(m_ctx.display, surf->m_id); 511 CHECK_ST 512 513 va_status = vaCopySurfaceGLX(m_ctx.display, surf->m_glx_surface, 514 surf->m_id, field); 515 CHECK_ST 516 return true; 517 } 518 -
new file mythtv/libs/libmythtv/vaapicontext.h
diff --git a/mythtv/libs/libmythtv/vaapicontext.h b/mythtv/libs/libmythtv/vaapicontext.h new file mode 100644 index 0000000..6b42d4d
- + 1 #ifndef VAAPICONTEXT_H 2 #define VAAPICONTEXT_H 3 4 extern "C" { 5 #include "libavcodec/vaapi.h" 6 } 7 #include "va/va_glx.h" 8 9 struct vaapi_surface 10 { 11 VASurfaceID m_id; 12 void* m_glx_surface; 13 }; 14 15 class VAAPIDisplay; 16 class OpenGLVideo; 17 18 class VAAPIContext 19 { 20 public: 21 static bool IsFormatAccelerated(QSize size, MythCodecID codec, 22 PixelFormat &pix_fmt); 23 VAAPIContext(MythCodecID codec); 24 ~VAAPIContext(); 25 26 bool CreateDisplay(QSize size); 27 bool CreateBuffers(void); 28 bool CreateGLXSurfaces(uint tex, uint type); 29 void* GetVideoSurface(int i); 30 uint8_t* GetSurfaceIDPointer(void* buf); 31 32 int GetNumBuffers(void) { return m_numSurfaces; } 33 PixelFormat GetPixelFormat(void) { return m_pix_fmt; } 34 35 bool CopySurfaceToTexture(const void* buf, FrameScanType scan); 36 37 bool InitDisplay(void); 38 bool InitProfiles(void); 39 bool InitBuffers(void); 40 bool InitContext(void); 41 42 vaapi_context m_ctx; 43 MythCodecID m_codec; 44 QSize m_size; 45 VAAPIDisplay *m_display; 46 VAProfile m_vaProfile; 47 VAEntrypoint m_vaEntrypoint; 48 PixelFormat m_pix_fmt; 49 int m_numSurfaces; 50 VASurfaceID *m_surfaces; 51 vaapi_surface *m_surfaceData; 52 }; 53 54 #endif // VAAPICONTEXT_H -
new file mythtv/libs/libmythtv/videoout_openglvaapi.cpp
diff --git a/mythtv/libs/libmythtv/videoout_openglvaapi.cpp b/mythtv/libs/libmythtv/videoout_openglvaapi.cpp new file mode 100644 index 0000000..6c1a105
- + 1 #include "videoout_openglvaapi.h" 2 #include "vaapicontext.h" 3 4 #define LOC QString("VidOutGLVAAPI: ") 5 #define ERR QString("VidOutGLVAAPI Error: ") 6 7 void VideoOutputOpenGLVAAPI::GetRenderOptions(render_opts &opts) 8 { 9 opts.renderers->append("openglvaapi"); 10 11 (*opts.deints)["openglvaapi"].append("vaapionefield"); 12 (*opts.deints)["openglvaapi"].append("vaapibobdeint"); 13 (*opts.deints)["openglvaapi"].append("none"); 14 (*opts.osds)["openglvaapi"].append("opengl2"); 15 16 if (opts.decoders->contains("vaapi")) 17 (*opts.safe_renderers)["vaapi"].append("openglvaapi"); 18 19 if (opts.decoders->contains("ffmpeg")) 20 (*opts.safe_renderers)["ffmpeg"].append("openglvaapi"); 21 22 (*opts.safe_renderers)["dummy"].append("openglvaapi"); 23 (*opts.safe_renderers)["nuppel"].append("openglvaapi"); 24 25 opts.priorities->insert("openglvaapi", 120); 26 } 27 28 VideoOutputOpenGLVAAPI::VideoOutputOpenGLVAAPI() 29 : VideoOutputOpenGL(), m_ctx(NULL) 30 { 31 } 32 33 VideoOutputOpenGLVAAPI::~VideoOutputOpenGLVAAPI() 34 { 35 TearDown(); 36 } 37 38 void VideoOutputOpenGLVAAPI::TearDown(void) 39 { 40 DeleteVAAPIContext(); 41 } 42 43 bool VideoOutputOpenGLVAAPI::InputChanged(const QSize &input_size, float aspect, 44 MythCodecID av_codec_id, void *codec_private, 45 bool &aspect_only) 46 { 47 VERBOSE(VB_PLAYBACK, LOC + QString("InputChanged(%1,%2,%3) %4->%5") 48 .arg(input_size.width()).arg(input_size.height()).arg(aspect) 49 .arg(toString(video_codec_id)).arg(toString(av_codec_id))); 50 51 if (!codec_is_vaapi(av_codec_id)) 52 return VideoOutputOpenGL::InputChanged(input_size, aspect, av_codec_id, 53 codec_private, aspect_only); 54 55 QMutexLocker locker(&gl_context_lock); 56 bool cid_changed = (video_codec_id != av_codec_id); 57 bool res_changed = input_size != window.GetActualVideoDim(); 58 bool asp_changed = aspect != window.GetVideoAspect(); 59 60 if (!res_changed && !cid_changed) 61 { 62 if (asp_changed) 63 { 64 aspect_only = true; 65 VideoAspectRatioChanged(aspect); 66 MoveResize(); 67 } 68 return true; 69 } 70 71 TearDown(); 72 QRect disp = window.GetDisplayVisibleRect(); 73 if (Init(input_size.width(), input_size.height(), 74 aspect, gl_parent_win, disp.left(), disp.top(), 75 disp.width(), disp.height(), av_codec_id, gl_embed_win)) 76 { 77 BestDeint(); 78 return true; 79 } 80 81 VERBOSE(VB_IMPORTANT, ERR + QString("Failed to re-initialise video output.")); 82 errorState = kError_Unknown; 83 84 return false; 85 } 86 87 bool VideoOutputOpenGLVAAPI::Init(int width, int height, float aspect, 88 WId winid, int winx, int winy, int winw, 89 int winh, MythCodecID codec_id, WId embedid) 90 { 91 bool ok = VideoOutputOpenGL::Init(width, height, aspect, winid, winx, winy, 92 winw, winh, codec_id, embedid); 93 if (ok && codec_is_vaapi(video_codec_id)) 94 return CreateVAAPIContext(QSize(width, height)); 95 return ok; 96 } 97 98 bool VideoOutputOpenGLVAAPI::CreateVAAPIContext(QSize size) 99 { 100 if (m_ctx) 101 DeleteVAAPIContext(); 102 103 OpenGLLocker ctx_lock(gl_context); 104 105 m_ctx = new VAAPIContext(video_codec_id); 106 if (m_ctx && m_ctx->CreateDisplay(size) && m_ctx->CreateBuffers()) 107 { 108 if (m_ctx->CreateGLXSurfaces(gl_videochain->GetInputTexture(), 109 gl_videochain->GetTextureType())) 110 { 111 int num_buffers = m_ctx->GetNumBuffers(); 112 const QSize video_dim = window.GetActualVideoDim(); 113 114 bool ok = true; 115 for (int i = 0; i < num_buffers; i++) 116 { 117 ok &= vbuffers.CreateBuffer(video_dim.width(), 118 video_dim.height(), i, 119 m_ctx->GetVideoSurface(i), 120 FMT_VAAPI); 121 } 122 return ok; 123 return true; 124 } 125 } 126 127 VERBOSE(VB_IMPORTANT, ERR + QString("Failed to create VAAPI context.")); 128 errorState = kError_Unknown; 129 return false; 130 } 131 132 void VideoOutputOpenGLVAAPI::DeleteVAAPIContext(void) 133 { 134 delete m_ctx; 135 m_ctx = NULL; 136 } 137 138 bool VideoOutputOpenGLVAAPI::CreateBuffers(void) 139 { 140 if (codec_is_vaapi(video_codec_id)) 141 { 142 vbuffers.Init(24, true, 2, 1, 4, 1); 143 return true; 144 } 145 return VideoOutputOpenGL::CreateBuffers(); 146 } 147 148 void* VideoOutputOpenGLVAAPI::GetVAAPIContext(void) 149 { 150 if (m_ctx) 151 return &m_ctx->m_ctx; 152 return NULL; 153 } 154 155 uint8_t* VideoOutputOpenGLVAAPI::GetSurfaceIDPointer(void* buf) 156 { 157 if (m_ctx) 158 return m_ctx->GetSurfaceIDPointer(buf); 159 return NULL; 160 } 161 162 void VideoOutputOpenGLVAAPI::SetProfile(void) 163 { 164 if (db_vdisp_profile) 165 db_vdisp_profile->SetVideoRenderer("openglvaapi"); 166 } 167 168 bool VideoOutputOpenGLVAAPI::ApproveDeintFilter(const QString &filtername) const 169 { 170 return filtername.contains("vaapi"); 171 } 172 173 bool VideoOutputOpenGLVAAPI::SetDeinterlacingEnabled(bool enable) 174 { 175 m_deinterlacing = enable; 176 SetupDeinterlace(enable); 177 return m_deinterlacing; 178 } 179 180 bool VideoOutputOpenGLVAAPI::SetupDeinterlace(bool i, const QString& ovrf) 181 { 182 //m_deintfiltername = !db_vdisp_profile ? "" : 183 // db_vdisp_profile->GetFilteredDeint(ovrf); 184 m_deinterlacing = i; 185 return m_deinterlacing; 186 } 187 188 void VideoOutputOpenGLVAAPI::ProcessFrame(VideoFrame *frame, OSD *osd, 189 FilterChain *filterList, 190 const PIPMap &pipPlayers, 191 FrameScanType scan) 192 { 193 VideoOutputOpenGL::ProcessFrame(frame, osd, filterList, pipPlayers, scan); 194 195 if (codec_is_vaapi(video_codec_id) && m_ctx && gl_videochain && frame) 196 { 197 gl_context->makeCurrent(); 198 m_ctx->CopySurfaceToTexture(frame->buf, scan); 199 gl_videochain->SetInputUpdated(); 200 gl_context->doneCurrent(); 201 } 202 } 203 204 QStringList VideoOutputOpenGLVAAPI::GetAllowedRenderers( 205 MythCodecID myth_codec_id, const QSize &video_dim) 206 { 207 (void) video_dim; 208 QStringList list; 209 if ((codec_is_std(myth_codec_id) || (codec_is_vaapi(myth_codec_id))) && 210 !getenv("NO_VAAPI")) 211 { 212 list += "openglvaapi"; 213 } 214 return list; 215 } 216 217 MythCodecID VideoOutputOpenGLVAAPI::GetBestSupportedCodec( 218 uint width, uint height, 219 uint stream_type, bool no_acceleration, 220 PixelFormat &pix_fmt) 221 { 222 QSize size(width, height); 223 bool use_cpu = no_acceleration; 224 VideoDisplayProfile vdp; 225 vdp.SetInput(size); 226 QString dec = vdp.GetDecoder(); 227 228 PixelFormat fmt = PIX_FMT_YUV420P; 229 MythCodecID test_cid = (MythCodecID)(kCodec_MPEG1_VAAPI + (stream_type - 1)); 230 if (codec_is_vaapi(test_cid)) 231 use_cpu |= !VAAPIContext::IsFormatAccelerated(size, test_cid, fmt); 232 else 233 use_cpu = true; 234 235 if ((dec != "vaapi") || getenv("NO_VAAPI") || use_cpu) 236 return (MythCodecID)(kCodec_MPEG1 + (stream_type - 1)); 237 238 pix_fmt = fmt; 239 return test_cid; 240 } -
new file mythtv/libs/libmythtv/videoout_openglvaapi.h
diff --git a/mythtv/libs/libmythtv/videoout_openglvaapi.h b/mythtv/libs/libmythtv/videoout_openglvaapi.h new file mode 100644 index 0000000..24488fe
- + 1 #ifndef VIDEOOUTPUTOPENGLVAAPI_H 2 #define VIDEOOUTPUTOPENGLVAAPI_H 3 4 #include "videoout_opengl.h" 5 6 class VAAPIContext; 7 8 class VideoOutputOpenGLVAAPI : public VideoOutputOpenGL 9 { 10 public: 11 static void GetRenderOptions(render_opts &opts); 12 13 VideoOutputOpenGLVAAPI(); 14 ~VideoOutputOpenGLVAAPI(); 15 16 bool Init(int width, int height, float aspect, WId winid, 17 int winx, int winy, int winw, int winh, 18 MythCodecID codec_id, WId embedid = 0); 19 bool CreateVAAPIContext(QSize size); 20 void DeleteVAAPIContext(void); 21 bool CreateBuffers(void); 22 void* GetVAAPIContext(void); 23 uint8_t* GetSurfaceIDPointer(void* buf); 24 void SetProfile(void); 25 void TearDown(void); 26 bool InputChanged(const QSize &input_size, float aspect, 27 MythCodecID av_codec_id, void *codec_private, 28 bool &aspect_only); 29 void ProcessFrame(VideoFrame *frame, OSD *osd, 30 FilterChain *filterList, 31 const PIPMap &pipPlayers, 32 FrameScanType scan); 33 bool ApproveDeintFilter(const QString& filtername) const; 34 bool SetDeinterlacingEnabled(bool enable); 35 bool SetupDeinterlace(bool i, const QString& ovrf=""); 36 void InitPictureAttributes(void) { } 37 38 static QStringList GetAllowedRenderers(MythCodecID myth_codec_id, 39 const QSize &video_dim); 40 static MythCodecID GetBestSupportedCodec(uint width, uint height, 41 uint stream_type, 42 bool no_acceleration, 43 PixelFormat &pix_fmt); 44 45 private: 46 VAAPIContext *m_ctx; 47 }; 48 #endif // VIDEOOUTPUTOPENGLVAAPI_H 49
