Ticket #8593: vaapi_v1.diff

File vaapi_v1.diff, 40.4 KB (added by markk, 10 years ago)

Initial VA API patch

  • configure

     
    128128  --enable-xvmc-vld        enable XvMC VLD accel. for the Unichrome (Pro) chipset
    129129  --xvmc-lib=LIB           XvMC library override (for crosscompiling)
    130130  --enable-vdpau           enable NVidia VDPAU hardware acceleration.
     131  --enable-vaapi           enable VAAPI hardware acceleration
    131132  --disable-opengl-video   disable OpenGL based video display
    132133  --enable-mac-accel       enable Mac OS X MPEG acceleration
    133134  --disable-opengl-vsync   disable OpenGL vsync method
     
    13361337    dvdv
    13371338    opengl
    13381339    vdpau
     1340    vaapi
    13391341'
    13401342
    13411343CMDLINE_SELECT="
     
    16781680xvmc_deps="xv X11_extensions_XvMClib_h"
    16791681xvmc_vld_deps="xvmc X11_extensions_vldXvMC_h"
    16801682xvmcw_deps="xvmc"
     1683vaapi_deps="opengl_video"
    16811684
    16821685# default parameters
    16831686pre_logfile="config.ep"
     
    33943397check_header termios.h
    33953398check_header vdpau/vdpau.h
    33963399check_header vdpau/vdpau_x11.h
     3400check_header va/va.h
     3401check_header va/va_x11.h
    33973402check_header X11/extensions/XvMClib.h
    33983403
    33993404check_struct dxva2api.h DXVA_PictureParameters wDecodedPictureIndex
     
    36623667      disable vdpau; }
    36633668fi
    36643669
     3670if ! disabled vaapi && enabled va_va_h; then
     3671    enable vaapi
     3672fi
     3673
    36653674enabled debug && add_cflags -g"$debuglevel" && add_asflags -g"$debuglevel"
    36663675enabled debug && add_cxxflags -g"$debuglevel"
    36673676
     
    42194228  echo "XvMC libs                 $VENDOR_XVMC_LIBS"
    42204229fi
    42214230  echo "VDPAU support             ${vdpau-no}"
     4231  echo "VAAPI support             ${vaapi-no}"
    42224232fi
    42234233  echo "OpenGL video              ${opengl_video-no}"
    42244234  if test x"$target_os" = x"darwin" ; then
  • libs/libmythtv/videoout_openglvaapi.h

     
     1#ifndef VIDEOOUTPUTOPENGLVAAPI_H
     2#define VIDEOOUTPUTOPENGLVAAPI_H
     3
     4#include "videoout_opengl.h"
     5#include "vaapicontext.h"
     6
     7class VideoOutputOpenGLVAAPI : public VideoOutputOpenGL
     8{
     9  public:
     10    static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
     11
     12    VideoOutputOpenGLVAAPI(MythCodecID codec_id);
     13   ~VideoOutputOpenGLVAAPI();
     14
     15    bool  Init(int width, int height, float aspect, WId winid,
     16               int winx, int winy, int winw, int winh, WId embedid = 0);
     17    bool  InitVAAPIContext(QSize size);
     18    bool  CreateBuffers(void);
     19    void* GetVAAPIContext(void);
     20    void  SetProfile(void);
     21    virtual void TearDown(void);
     22    virtual bool InputChanged(const QSize &input_size, float aspect,
     23                              MythCodecID  av_codec_id, void *codec_private,
     24                              bool &aspect_only);
     25    uint8_t* GetSurfaceIDPointer(void* buf);
     26    void ProcessFrame(VideoFrame *frame, OSD *osd,
     27                              FilterChain *filterList,
     28                              const PIPMap &pipPlayers,
     29                              FrameScanType scan);
     30    void Show(FrameScanType );
     31
     32    static QStringList GetAllowedRenderers(MythCodecID myth_codec_id,
     33                                           const QSize &video_dim);
     34    static MythCodecID GetBestSupportedCodec(uint width, uint height,
     35                                             uint stream_type,
     36                                             bool no_acceleration,
     37                                             PixelFormat &pix_fmt);
     38
     39  private:
     40    MythCodecID   m_codec_id;
     41    VAAPIContext *m_ctx;
     42};
     43
     44#endif // VIDEOOUTPUTOPENGLVAAPI_H
     45
  • libs/libmythtv/videoout_opengl.cpp

     
    99#include "mythuihelper.h"
    1010
    1111#define LOC      QString("VidOutOGL: ")
    12 #define LOC_ERR  QString("VidOutOGL: ")
     12#define LOC_ERR  QString("VidOutOGL Error: ")
    1313
    1414void VideoOutputOpenGL::GetRenderOptions(render_opts &opts,
    1515                                         QStringList &cpudeints)
    1616{
    1717    opts.renderers->append("opengl");
    1818    opts.deints->insert("opengl", cpudeints);
    19     (*opts.deints)["opengl"].append("opengllinearblend");
    20     (*opts.deints)["opengl"].append("openglonefield");
    21     (*opts.deints)["opengl"].append("openglkerneldeint");
    2219    (*opts.deints)["opengl"].append("bobdeint");
    23     (*opts.deints)["opengl"].append("openglbobdeint");
    24     (*opts.deints)["opengl"].append("opengldoubleratelinearblend");
    25     (*opts.deints)["opengl"].append("opengldoubleratekerneldeint");
    26     (*opts.deints)["opengl"].append("opengldoubleratefieldorder");
    27     (*opts.deints)["opengl"].append("opengldoublerateyadif");
    28     (*opts.deints)["opengl"].append("openglyadif");
     20    opts.deints->insert("opengl", VideoOutputOpenGL::GetOpenGLDeints());
    2921    (*opts.osds)["opengl"].append("softblend");
    3022    (*opts.osds)["opengl"].append("opengl2");
    3123    (*opts.safe_renderers)["dummy"].append("opengl");
     
    3729    opts.priorities->insert("opengl", 65);
    3830}
    3931
     32QStringList VideoOutputOpenGL::GetOpenGLDeints(void)
     33{
     34    QStringList result;
     35    result.append("opengllinearblend");
     36    result.append("openglonefield");
     37    result.append("openglkerneldeint");
     38    result.append("openglbobdeint");
     39    result.append("opengldoubleratelinearblend");
     40    result.append("opengldoubleratekerneldeint");
     41    result.append("opengldoubleratefieldorder");
     42    result.append("opengldoublerateyadif");
     43    result.append("openglyadif");
     44    return result;
     45}
     46
    4047VideoOutputOpenGL::VideoOutputOpenGL(void)
    4148    : VideoOutput(),
    4249    gl_context_lock(QMutex::Recursive),
     
    123130                      winid, winx, winy, winw, winh,
    124131                      embedid);
    125132
    126     if (db_vdisp_profile)
    127         db_vdisp_profile->SetVideoRenderer("opengl");
     133    SetProfile();
    128134
    129135    success &= SetupContext();
    130136    InitDisplayMeasurements(width, height, false);
    131137    success &= CreateBuffers();
     138    success &= CreatePauseFrame();
    132139    success &= SetupOpenGL();
    133140
    134141    InitOSD();
     
    144151    return success;
    145152}
    146153
     154void VideoOutputOpenGL::SetProfile(void)
     155{
     156    if (db_vdisp_profile)
     157        db_vdisp_profile->SetVideoRenderer("opengl");
     158}
     159
    147160bool VideoOutputOpenGL::InputChanged(const QSize &input_size,
    148161                                     float        aspect,
    149162                                     MythCodecID  av_codec_id,
     
    276289bool VideoOutputOpenGL::CreateBuffers(void)
    277290{
    278291    QMutexLocker locker(&gl_context_lock);
    279 
    280     bool success = true;
    281292    vbuffers.Init(31, true, 1, 12, 4, 2, false);
    282     success &= vbuffers.CreateBuffers(windows[0].GetVideoDim().width(),
    283                                       windows[0].GetVideoDim().height());
     293    return vbuffers.CreateBuffers(windows[0].GetVideoDim().width(),
     294                                  windows[0].GetVideoDim().height());
     295}
    284296
     297bool VideoOutputOpenGL::CreatePauseFrame(void)
     298{
    285299    av_pause_frame.height = vbuffers.GetScratchFrame()->height;
    286300    av_pause_frame.width  = vbuffers.GetScratchFrame()->width;
    287301    av_pause_frame.bpp    = vbuffers.GetScratchFrame()->bpp;
     
    290304    av_pause_frame.frameNumber = vbuffers.GetScratchFrame()->frameNumber;
    291305
    292306    if (!av_pause_frame.buf)
    293     {
    294         success = false;
    295     }
    296     else
    297     {
    298         int size = av_pause_frame.width * av_pause_frame.height;
    299         memset(av_pause_frame.buf, 0,   size);
    300         memset(av_pause_frame.buf + size, 127, size / 2);
    301     }
     307        return false;
    302308
    303     return success;
     309    int size = av_pause_frame.width * av_pause_frame.height;
     310    memset(av_pause_frame.buf, 0,   size);
     311    memset(av_pause_frame.buf + size, 127, size / 2);
     312    return true;
    304313}
    305314
    306315void VideoOutputOpenGL::ProcessFrame(VideoFrame *frame, OSD *osd,
     
    371380    framesPlayed = buffer->frameNumber + 1;
    372381    gl_context_lock.unlock();
    373382
    374     if (buffer->codec != FMT_YV12)
    375         return;
     383    //if (buffer->codec != FMT_YV12)
     384    //    return;
    376385
    377386    gl_videochain->SetVideoRect(vsz_enabled ? vsz_desired_display_rect :
    378387                                              windows[0].GetDisplayVideoRect(),
  • libs/libmythtv/avformatdecoder.cpp

     
    4949}
    5050#endif // USING_VDPAU
    5151
     52#ifdef USING_VAAPI
     53#include "videoout_openglvaapi.h"
     54#endif // USING_VAAPI
     55
    5256extern "C" {
    5357#include "avutil.h"
    5458#include "ac3_parser.h"
     
    9296void render_slice_vdpau(struct AVCodecContext *s, const AVFrame *src,
    9397                        int offset[4], int y, int type, int height);
    9498
     99int  get_avf_buffer_vaapi(struct AVCodecContext *c, AVFrame *pic);
     100
    95101static AVCodec *find_vdpau_decoder(AVCodec *c, enum CodecID id)
    96102{
    97103    AVCodec *codec = c;
     
    461467    opts.decoders->append("vdpau");
    462468    (*opts.equiv_decoders)["vdpau"].append("dummy");
    463469#endif
     470
     471#ifdef USING_VAAPI
     472    opts.decoders->append("vaapi");
     473    (*opts.equiv_decoders)["vaapi"].append("dummy");
     474#endif
    464475}
    465476
    466477AvFormatDecoder::AvFormatDecoder(NuppelVideoPlayer *parent,
     
    13681379    return fmt[i];
    13691380}
    13701381
     1382static bool IS_VAAPI_PIX_FMT(enum PixelFormat fmt)
     1383{
     1384    return fmt == PIX_FMT_VAAPI_MOCO ||
     1385           fmt == PIX_FMT_VAAPI_IDCT ||
     1386           fmt == PIX_FMT_VAAPI_VLD;
     1387}
     1388
     1389static enum PixelFormat get_format_vaapi(struct AVCodecContext *avctx,
     1390                                         const enum PixelFormat *fmt)
     1391{
     1392    if (!fmt)
     1393        return PIX_FMT_NONE;
     1394    int i = 0;
     1395    for (; fmt[i] != PIX_FMT_NONE ; i++)
     1396        if (IS_VAAPI_PIX_FMT(fmt[i]))
     1397            break;
     1398    return fmt[i];
     1399}
     1400
    13711401static bool IS_DR1_PIX_FMT(const enum PixelFormat fmt)
    13721402{
    13731403    switch (fmt)
     
    14391469        directrendering = true;
    14401470        if (
    14411471        !gCoreContext->GetNumSetting("DecodeExtraAudio", 0) &&
    1442         !CODEC_IS_HWACCEL(codec))
     1472        !CODEC_IS_HWACCEL(codec)) // FIXME - no VAAPI
    14431473    {
    14441474        SetLowBuffers(false);
    14451475    }
     
    14731503        enc->draw_horiz_band = render_slice_vdpau;
    14741504        enc->slice_flags     = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
    14751505    }
     1506    else if (codec && IS_VAAPI_PIX_FMT(enc->pix_fmt))
     1507    {
     1508        enc->get_buffer      = get_avf_buffer_vaapi;
     1509        enc->get_format      = get_format_vaapi;
     1510        enc->release_buffer  = release_avf_buffer;
     1511        enc->slice_flags     = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD; // is this correct?
     1512    }
    14761513    else if (codec && codec->capabilities & CODEC_CAP_DR1)
    14771514    {
    14781515        enc->flags          |= CODEC_FLAG_EMU_EDGE;
     
    19551992                        handled = true;
    19561993                    }
    19571994#endif // USING_VDPAU
     1995#ifdef USING_VAAPI
     1996                    MythCodecID vaapi_mcid;
     1997                    PixelFormat pix_fmt = PIX_FMT_YUV420P;
     1998                    vaapi_mcid = VideoOutputOpenGLVAAPI::GetBestSupportedCodec(
     1999                        width, height, mpeg_version(enc->codec_id),
     2000                        no_hardware_decoders, pix_fmt);
     2001
     2002                    if (vaapi_mcid >= video_codec_id)
     2003                    {
     2004                        enc->codec_id = (CodecID)myth2av_codecid(vaapi_mcid);
     2005                        video_codec_id = vaapi_mcid;
     2006                        handled = true;
     2007                        enc->pix_fmt = pix_fmt;
     2008                        if (!no_hardware_decoders &&
     2009                            codec_is_vaapi_hw(video_codec_id))
     2010                        {
     2011                            enc->pix_fmt = pix_fmt;
     2012                        }
     2013                    }
     2014#endif // USING_VAAPI
    19582015#ifdef USING_XVMC
    19592016
    19602017                    bool force_xv = no_hardware_decoders;
     
    26732730    }
    26742731}
    26752732
     2733int get_avf_buffer_vaapi(struct AVCodecContext *c, AVFrame *pic)
     2734{
     2735    AvFormatDecoder *nd = (AvFormatDecoder *)(c->opaque);
     2736    VideoFrame *frame = nd->GetNVP()->GetNextVideoFrame(false);
     2737
     2738    pic->data[0] = frame->buf;
     2739    pic->data[1] = frame->priv[0];
     2740    pic->data[2] = frame->priv[1];
     2741
     2742    pic->linesize[0] = 0;
     2743    pic->linesize[1] = 0;
     2744    pic->linesize[2] = 0;
     2745
     2746    pic->opaque = frame;
     2747    pic->type = FF_BUFFER_TYPE_USER;
     2748
     2749    pic->age = 256 * 256 * 256 * 64;
     2750
     2751    frame->pix_fmt = c->pix_fmt;
     2752
     2753#ifdef USING_VAAPI
     2754    if (nd->GetNVP()->getVideoOutput())
     2755    {
     2756        VideoOutputOpenGLVAAPI *vo =
     2757            dynamic_cast<VideoOutputOpenGLVAAPI*>(nd->GetNVP()->getVideoOutput());
     2758        c->hwaccel_context = (vaapi_context*)vo->GetVAAPIContext();
     2759        pic->data[3] = vo->GetSurfaceIDPointer(frame->buf);
     2760    }
     2761#endif
     2762
     2763    return 0;
     2764}
     2765
    26762766void AvFormatDecoder::DecodeDTVCC(const uint8_t *buf, uint len)
    26772767{
    26782768    if (!len)
  • libs/libmythtv/videoout_openglvaapi.cpp

     
     1#include "videoout_openglvaapi.h"
     2
     3#define LOC      QString("VidOutVAAPI: ")
     4#define LOC_ERR  QString("VidOutVAAPI Error: ")
     5
     6void VideoOutputOpenGLVAAPI::GetRenderOptions(render_opts &opts,
     7                                              QStringList &cpudeints)
     8{
     9    opts.renderers->append("openglvaapi");
     10    opts.deints->insert("openglvaapi", VideoOutputOpenGL::GetOpenGLDeints());
     11    (*opts.osds)["openglvaapi"].append("opengl2");
     12
     13    if (opts.decoders->contains("vaapi"))
     14        (*opts.safe_renderers)["vaapi"].append("openglvaapi");
     15
     16    opts.priorities->insert("openglvaapi", 110);
     17}
     18
     19VideoOutputOpenGLVAAPI::VideoOutputOpenGLVAAPI(MythCodecID codec_id)
     20  : VideoOutputOpenGL(), m_codec_id(codec_id), m_ctx(NULL)
     21{
     22    if (gCoreContext->GetNumSetting("UseVideoModes", 0))
     23        display_res = DisplayRes::GetDisplayRes(true);
     24}
     25
     26VideoOutputOpenGLVAAPI::~VideoOutputOpenGLVAAPI()
     27{
     28    TearDown();
     29}
     30
     31void VideoOutputOpenGLVAAPI::TearDown(void)
     32{
     33    VideoOutputOpenGL::TearDown();
     34    delete m_ctx;
     35}
     36
     37bool VideoOutputOpenGLVAAPI::Init(int width, int height, float aspect,
     38                                  WId winid, int winx, int winy, int winw,
     39                                  int winh, WId embedid)
     40{
     41    if (!InitVAAPIContext(QSize(width, height)))
     42        return false;
     43    return VideoOutputOpenGL::Init(width, height, aspect, winid, winx, winy,
     44                                   winw, winh, embedid);
     45}
     46
     47bool VideoOutputOpenGLVAAPI::InputChanged(const QSize &input_size, float aspect,
     48                              MythCodecID  av_codec_id, void *codec_private,
     49                              bool &aspect_only)
     50{
     51    VERBOSE(VB_PLAYBACK, LOC + QString("InputChanged(%1,%2,%3) %4")
     52            .arg(input_size.width()).arg(input_size.height()).arg(aspect)
     53            .arg(toString(av_codec_id)));
     54
     55    QMutexLocker locker(&gl_context_lock);
     56
     57    if (!codec_is_vaapi_hw(av_codec_id))
     58    {
     59        VERBOSE(VB_IMPORTANT, LOC_ERR +
     60            QString("New video codec is not supported."));
     61        errorState = kError_Unknown;
     62        return false;
     63    }
     64
     65    if (input_size == windows[0].GetVideoDim())
     66    {
     67        if (windows[0].GetVideoAspect() != aspect)
     68        {
     69            aspect_only = true;
     70            VideoAspectRatioChanged(aspect);
     71            MoveResize();
     72        }
     73        return true;
     74    }
     75
     76    TearDown();
     77    QRect disp = windows[0].GetDisplayVisibleRect();
     78    if (Init(input_size.width(), input_size.height(),
     79             aspect, gl_parent_win, disp.left(),  disp.top(),
     80             disp.width(), disp.height(), gl_embed_win))
     81    {
     82        BestDeint();
     83        return true;
     84    }
     85
     86    VERBOSE(VB_IMPORTANT, LOC_ERR +
     87        QString("Failed to re-initialise video output."));
     88    errorState = kError_Unknown;
     89
     90    return false;
     91}
     92
     93bool VideoOutputOpenGLVAAPI::InitVAAPIContext(QSize size)
     94{
     95    m_ctx = new VAAPIContext(m_codec_id);
     96    if (m_ctx && m_ctx->Create(size))
     97        return true;
     98    return false;
     99}
     100
     101bool VideoOutputOpenGLVAAPI::CreateBuffers(void)
     102{
     103    if (!codec_is_vaapi_hw(m_codec_id) || !m_ctx)
     104        return false;
     105
     106    QMutexLocker locker(&gl_context_lock);
     107    int num_buffers = m_ctx->GetNumBuffers();
     108    const QSize video_dim = windows[0].GetVideoDim();
     109    vbuffers.Init(num_buffers, true, 2, 1, 4, 1, false); // shouldn't need pause frame
     110
     111    bool ok = true;
     112    for (int i = 0; i < num_buffers; i++)
     113    {
     114        ok &= vbuffers.CreateBuffer(video_dim.width(),
     115                                    video_dim.height(), i,
     116                                    m_ctx->GetVideoSurface(i));
     117    }
     118    return ok;
     119}
     120
     121void* VideoOutputOpenGLVAAPI::GetVAAPIContext(void)
     122{
     123    if (m_ctx)
     124        return &m_ctx->m_ctx;
     125    return NULL;
     126}
     127
     128void VideoOutputOpenGLVAAPI::SetProfile(void)
     129{
     130    if (db_vdisp_profile)
     131        db_vdisp_profile->SetVideoRenderer("openglvaapi");
     132}
     133
     134uint8_t* VideoOutputOpenGLVAAPI::GetSurfaceIDPointer(void* buf)
     135{
     136    if (m_ctx)
     137        return m_ctx->GetSurfaceIDPointer(buf);
     138    return NULL;
     139}
     140
     141void VideoOutputOpenGLVAAPI::ProcessFrame(VideoFrame *frame, OSD *osd,
     142                                          FilterChain *filterList,
     143                                          const PIPMap &pipPlayers,
     144                                          FrameScanType scan)
     145{
     146    QMutexLocker locker(&gl_context_lock);
     147    if (!gl_videochain || !gl_context)
     148        return;
     149
     150    OpenGLLocker ctx_lock(gl_context);
     151
     152    if (!frame)
     153    {
     154        frame = vbuffers.GetScratchFrame();
     155        CopyFrame(vbuffers.GetScratchFrame(), &av_pause_frame);
     156    }
     157
     158    if (!windows[0].IsEmbedding())
     159    {
     160        gl_pipchain_active = NULL;
     161        ShowPIPs(frame, pipPlayers);
     162    }
     163
     164    if (m_ctx)
     165    {
     166        QRect disp = windows[0].GetDisplayVideoRect();
     167        m_ctx->ShowSurface(gl_parent_win, disp, frame->buf);
     168    }
     169}
     170
     171void VideoOutputOpenGLVAAPI::Show(FrameScanType scan)
     172{
     173}
     174
     175QStringList VideoOutputOpenGLVAAPI::GetAllowedRenderers(
     176    MythCodecID myth_codec_id, const QSize &video_dim)
     177{
     178    (void) video_dim;
     179    QStringList list;
     180    if ((codec_is_std(myth_codec_id) || codec_is_vaapi_hw(myth_codec_id)) &&
     181         !getenv("NO_VAAPI"))
     182    {
     183        list += "openglvaapi";
     184    }
     185    return list;
     186}
     187
     188MythCodecID VideoOutputOpenGLVAAPI::GetBestSupportedCodec(
     189    uint width,       uint height,
     190    uint stream_type, bool no_acceleration,
     191    PixelFormat &pix_fmt)
     192{
     193    QSize size(width, height);
     194    bool use_cpu = no_acceleration;
     195    VideoDisplayProfile vdp;
     196    vdp.SetInput(size);
     197    QString dec = vdp.GetDecoder();
     198
     199    MythCodecID test_cid = (MythCodecID)(kCodec_MPEG1_VAAPI + (stream_type-1));
     200    use_cpu |= !codec_is_vaapi_hw(test_cid);
     201    use_cpu |= !VAAPIContext::IsFormatAccelerated(size, test_cid, pix_fmt);
     202    if ((dec != "vaapi") || getenv("NO_VAAPI") || use_cpu)
     203        return (MythCodecID)(kCodec_MPEG1 + (stream_type-1));
     204
     205    return test_cid;
     206}
  • libs/libmythtv/libmythtv.pro

     
    344344
    345345    using_glx_proc_addr_arb:DEFINES += USING_GLX_PROC_ADDR_ARB
    346346
     347    using_vaapi: DEFINES += USING_VAAPI
     348    using_vaapi: DEFINES += videoout_openglvaapi.h   vaapicontext.h
     349    using_vaapi: SOURCES += videoout_openglvaapi.cpp vaapicontext.cpp
     350    using_vaapi: LIBS    += -lva -lva-x11
     351
    347352    # Misc. frontend
    348353    HEADERS += DetectLetterbox.h
    349354    SOURCES += DetectLetterbox.cpp
  • libs/libmythtv/vaapicontext.cpp

     
     1#include "mythverbose.h"
     2#include "mythxdisplay.h"
     3#include "mythcodecid.h"
     4
     5#include "vaapicontext.h"
     6
     7#define LOC     QString("VAAPI: ")
     8#define LOC_ERR QString("VAAPI Error: ")
     9#define NUM_VAAPI_BUFFERS 20
     10
     11#define INIT_ST \
     12  VAStatus va_status; \
     13  bool ok = true;
     14
     15#define CHECK_ST \
     16  ok &= (va_status == VA_STATUS_SUCCESS); \
     17  if (!ok) { \
     18      VERBOSE(VB_GENERAL, LOC_ERR + QString("Error at %1:%2 (#%3, %4)") \
     19              .arg(__FILE__).arg( __LINE__).arg(va_status) \
     20              .arg(vaErrorStr(va_status))); \
     21  }
     22
     23#define CREATE_CHECK(arg1, arg2) \
     24  if (ok) \
     25  { \
     26      ok = arg1; \
     27      if (!ok) \
     28          VERBOSE(VB_IMPORTANT, LOC_ERR + arg2); \
     29  }
     30
     31QString profileToString(VAProfile profile)
     32{
     33    if (VAProfileMPEG2Simple == profile)         return "MPEG2Simple";
     34    if (VAProfileMPEG2Main == profile)           return "MPEG2Main";
     35    if (VAProfileMPEG4Simple == profile)         return "MPEG4Simple";
     36    if (VAProfileMPEG4AdvancedSimple == profile) return "MPEG4AdvSimple";
     37    if (VAProfileMPEG4Main == profile)           return "MPEG4Main";
     38    if (VAProfileH264Baseline == profile)        return "H264Base";
     39    if (VAProfileH264Main == profile)            return "H264Main";
     40    if (VAProfileH264High == profile)            return "H264High";
     41    if (VAProfileVC1Simple == profile)           return "VC1Simple";
     42    if (VAProfileVC1Main == profile)             return "VC1Main";
     43    if (VAProfileVC1Advanced == profile)         return "VC1Advanced";
     44    if (VAProfileH263Baseline == profile)        return "H263Base";
     45    return "Unknown";
     46}
     47
     48QString entryToString(VAEntrypoint entry)
     49{
     50    if (VAEntrypointVLD == entry)        return "VLD ";
     51    if (VAEntrypointIZZ == entry)        return "IZZ ";
     52    if (VAEntrypointIDCT == entry)       return "IDCT ";
     53    if (VAEntrypointMoComp == entry)     return "MC ";
     54    if (VAEntrypointDeblocking == entry) return "Deblock (UNSUPPORTED) ";
     55    if (VAEntrypointEncSlice == entry)   return "EncSlice (UNSUPPORTED) ";
     56    return "Unknown";
     57}
     58
     59VAProfile preferredProfile(MythCodecID codec)
     60{
     61    // FIXME handle unsupported codecs properly
     62    if (kCodec_H263_VAAPI  == codec) return VAProfileH263Baseline;
     63    if (kCodec_MPEG4_VAAPI == codec) return VAProfileMPEG4AdvancedSimple;
     64    if (kCodec_H264_VAAPI  == codec) return VAProfileH264High;
     65    if (kCodec_VC1_VAAPI   == codec) return VAProfileVC1Advanced;
     66    if (kCodec_WMV3_VAAPI  == codec) return VAProfileVC1Main;
     67    return VAProfileMPEG2Main;
     68}
     69
     70bool VAAPIContext::IsFormatAccelerated(QSize size, MythCodecID codec,
     71                                       PixelFormat &pix_fmt)
     72{
     73    bool result = false;
     74    VAAPIContext *ctx = new VAAPIContext(codec);
     75    if (ctx)
     76    {
     77        result  = ctx->CreateDummy(size);
     78        pix_fmt = ctx->GetPixelFormat();
     79    }
     80    delete ctx;
     81    return result;
     82}
     83
     84VAAPIContext::VAAPIContext(MythCodecID codec)
     85  : m_codec(codec), m_display(NULL),
     86    m_vaProfile(VAProfileMPEG2Main)/* ?? */,
     87    m_vaEntrypoint(VAEntrypointEncSlice),
     88    m_pix_fmt(PIX_FMT_YUV420P), m_numSurfaces(NUM_VAAPI_BUFFERS),
     89    m_surfaces(NULL), m_surfaceData(NULL)
     90{
     91    memset(&m_ctx, 0, sizeof(vaapi_context));
     92}
     93
     94VAAPIContext::~VAAPIContext()
     95{
     96    INIT_ST
     97
     98    if (m_ctx.context_id)
     99    {
     100        va_status = vaDestroyContext(m_ctx.display, m_ctx.context_id);
     101        CHECK_ST
     102    }
     103    if (m_ctx.config_id)
     104    {
     105        va_status = vaDestroyConfig(m_ctx.display, m_ctx.config_id);
     106        CHECK_ST
     107    }
     108    if (m_surfaces)
     109    {
     110        va_status = vaDestroySurfaces(m_ctx.display, m_surfaces, m_numSurfaces);
     111        CHECK_ST
     112    }
     113
     114    if (m_ctx.display)
     115    {
     116        va_status = vaTerminate(m_ctx.display);
     117        CHECK_ST
     118    }
     119
     120    if (m_surfaces)
     121        delete [] m_surfaces;
     122    if (m_surfaceData)
     123        delete [] m_surfaceData;
     124
     125    delete m_display;
     126}
     127
     128bool VAAPIContext::CreateDummy(QSize size)\
     129{
     130    m_size = size;
     131    bool ok = true;
     132    m_display = OpenMythXDisplay();
     133    CREATE_CHECK(!m_size.isEmpty(), "Invalid size")
     134    CREATE_CHECK(m_display != NULL, "Invalid display")
     135    CREATE_CHECK(InitDisplay(), "Invalid VADisplay")
     136    CREATE_CHECK(InitProfiles(), "No supported profiles")
     137    return ok;
     138}
     139
     140bool VAAPIContext::Create(QSize size)
     141{
     142    m_size = size;
     143    bool ok = true;
     144    m_display = OpenMythXDisplay();
     145    CREATE_CHECK(!m_size.isEmpty(), "Invalid size")
     146    CREATE_CHECK(m_display != NULL, "Invalid display")
     147    CREATE_CHECK(InitDisplay(), "Invalid VADisplay")
     148    CREATE_CHECK(InitProfiles(), "No supported profiles")
     149    CREATE_CHECK(InitBuffers(), "Failed to create buffers.")
     150    CREATE_CHECK(InitContext(), "Failed to create context")
     151    return ok;
     152}
     153
     154bool VAAPIContext::InitDisplay(void)
     155{
     156    int major_ver, minor_ver;
     157    m_ctx.display = vaGetDisplay(m_display->GetDisplay());
     158    INIT_ST
     159    va_status = vaInitialize(m_ctx.display, &major_ver, &minor_ver);
     160    CHECK_ST
     161
     162    static bool debugged = false;
     163    if (ok && !debugged)
     164    {
     165        debugged = true;
     166        VERBOSE(VB_IMPORTANT, LOC + QString("Version: %1.%2")
     167                                    .arg(major_ver).arg(minor_ver));
     168        VERBOSE(VB_IMPORTANT, LOC + QString("Vendor : %1")
     169                                    .arg(vaQueryVendorString(m_ctx.display)));
     170    }
     171    return ok;
     172}
     173
     174bool VAAPIContext::InitProfiles(void)
     175{
     176    if (!codec_is_vaapi_hw(m_codec) || !m_ctx.display)
     177        return false;
     178
     179    int max_profiles, max_entrypoints;
     180    VAProfile profile_wanted = preferredProfile(m_codec);
     181    VAProfile profile_found  = VAProfileMPEG2Main;   // FIXME
     182    VAEntrypoint entry_found = VAEntrypointEncSlice; // unsupported value
     183
     184    max_profiles          = vaMaxNumProfiles(m_ctx.display);
     185    max_entrypoints       = vaMaxNumEntrypoints(m_ctx.display);
     186    VAProfile *profiles   = new VAProfile[max_profiles];
     187    VAEntrypoint *entries = new VAEntrypoint[max_entrypoints];
     188
     189    static bool debugged = false;
     190    if (profiles && entries)
     191    {
     192        INIT_ST
     193        int act_profiles, act_entries;
     194        va_status = vaQueryConfigProfiles(m_ctx.display,
     195                                          profiles,
     196                                         &act_profiles);
     197        CHECK_ST
     198        if (ok && act_profiles > 0)
     199        {
     200            for (int i = 0; i < act_profiles; i++)
     201            {
     202                va_status = vaQueryConfigEntrypoints(m_ctx.display,
     203                                                     profiles[i],
     204                                                     entries,
     205                                                    &act_entries);
     206                if (va_status == VA_STATUS_SUCCESS && act_entries > 0)
     207                {
     208                    if (profiles[i] == profile_wanted)
     209                    {
     210                        profile_found = profile_wanted;
     211                        for (int j = 0; j < act_entries; j++)
     212                            if (entries[j] < entry_found)
     213                                entry_found = entries[j];
     214                    }
     215
     216                    if (!debugged)
     217                    {
     218                        QString entrylist = "Entrypoints: ";
     219                        for (int j = 0; j < act_entries; j++)
     220                            entrylist += entryToString(entries[j]);
     221                        VERBOSE(VB_IMPORTANT, LOC + QString("Profile: %1 %2")
     222                            .arg(profileToString(profiles[i])).arg(entrylist));
     223                    }
     224                }
     225            }
     226        }
     227        debugged = true;
     228    }
     229    delete profiles;
     230    delete entries;
     231
     232    VERBOSE(VB_PLAYBACK, LOC + QString("Desired profile for '%1': %2")
     233        .arg(toString(m_codec)).arg(profileToString(profile_wanted)));
     234    VERBOSE(VB_PLAYBACK, LOC + QString("Found profile %1 with entry %2")
     235        .arg(profileToString(profile_found)).arg(entryToString(entry_found)));
     236
     237    if (profile_wanted != profile_found)
     238    {
     239        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to find supported profile.");
     240        return false;
     241    }
     242
     243    if (entry_found > VAEntrypointMoComp)
     244    {
     245        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to find suitable entry point.");
     246        return false;
     247    }
     248
     249    m_vaProfile = profile_wanted;
     250    m_vaEntrypoint = entry_found;
     251    if (VAEntrypointVLD == m_vaEntrypoint)
     252        m_pix_fmt = PIX_FMT_VAAPI_VLD;
     253    else if (VAEntrypointIDCT == m_vaEntrypoint)
     254        m_pix_fmt = PIX_FMT_VAAPI_IDCT;
     255    else if (VAEntrypointMoComp == m_vaEntrypoint)
     256        m_pix_fmt = PIX_FMT_VAAPI_MOCO;
     257    return true;
     258}
     259
     260bool VAAPIContext::InitBuffers(void)
     261{
     262    m_surfaces = new VASurfaceID[m_numSurfaces];
     263    m_surfaceData = new vaapi_surface[m_numSurfaces];
     264
     265    if (!m_surfaces || !m_surfaceData)
     266        return false;
     267
     268    INIT_ST
     269    va_status = vaCreateSurfaces(m_ctx.display, m_size.width(), m_size.height(),
     270                                 VA_RT_FORMAT_YUV420, m_numSurfaces,
     271                                 m_surfaces);
     272    CHECK_ST
     273
     274    for (int i =0; i < m_numSurfaces; i++)
     275        m_surfaceData[i].m_id = m_surfaces[i];
     276
     277    return ok;
     278}
     279
     280bool VAAPIContext::InitContext(void)
     281{
     282    if (!m_ctx.display || m_vaEntrypoint > VAEntrypointMoComp)
     283        return false;
     284
     285    VAConfigAttrib attrib;
     286    attrib.type = VAConfigAttribRTFormat;
     287    INIT_ST
     288    va_status = vaGetConfigAttributes(m_ctx.display, m_vaProfile,
     289                                      m_vaEntrypoint, &attrib, 1);
     290    CHECK_ST
     291
     292    if (!ok || !(attrib.value & VA_RT_FORMAT_YUV420))
     293    {
     294        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to confirm YUV420 chroma");
     295        return false;
     296    }
     297
     298    va_status = vaCreateConfig(m_ctx.display, m_vaProfile, m_vaEntrypoint,
     299                               &attrib, 1, &m_ctx.config_id);
     300    CHECK_ST
     301    if (!ok)
     302    {
     303        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create decoder config.");
     304        return false;
     305    }
     306
     307    va_status = vaCreateContext(m_ctx.display, m_ctx.config_id,
     308                                m_size.width(), m_size.height(), VA_PROGRESSIVE,
     309                                m_surfaces, m_numSurfaces,
     310                                &m_ctx.context_id);
     311    CHECK_ST
     312    if (!ok)
     313    {
     314        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create decoder context.");
     315        return false;
     316    }
     317    return true;
     318}
     319
     320void* VAAPIContext::GetVideoSurface(int i)
     321{
     322    if (i < 0 || i >= m_numSurfaces)
     323        return NULL;
     324    return &m_surfaceData[i];
     325}
     326
     327uint8_t* VAAPIContext::GetSurfaceIDPointer(void* buf)
     328{
     329    if (!buf)
     330        return NULL;
     331    const vaapi_surface *surf = (vaapi_surface*)buf;
     332    return (uint8_t*)(uintptr_t)surf->m_id;
     333}
     334
     335void VAAPIContext::ShowSurface(int win, QRect &rect, void* buf)
     336{
     337    if (!buf)
     338        return;
     339
     340    const vaapi_surface *surf = (vaapi_surface*)buf;
     341    INIT_ST
     342    va_status = vaPutSurface(m_ctx.display, surf->m_id, win, 0, 0,
     343                             m_size.width(), m_size.height(),
     344                             rect.left(), rect.top(),
     345                             rect.width(), rect.height(),
     346                             NULL, 0, 0);
     347    CHECK_ST
     348}
  • libs/libmythtv/videoout_opengl.h

     
    1010{
    1111  public:
    1212    static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
     13    static QStringList GetOpenGLDeints(void);
    1314    VideoOutputOpenGL();
    14    ~VideoOutputOpenGL();
     15    virtual ~VideoOutputOpenGL();
    1516
    16     bool Init(int width, int height, float aspect, WId winid,
    17               int winx, int winy, int winw, int winh, WId embedid = 0);
    18     void TearDown(void);
     17    virtual bool Init(int width, int height, float aspect, WId winid,
     18                      int winx, int winy, int winw, int winh, WId embedid = 0);
     19    virtual void SetProfile(void);
     20    virtual void TearDown(void);
    1921
    2022    void PrepareFrame(VideoFrame *buffer, FrameScanType, OSD *osd);
    21     void ProcessFrame(VideoFrame *frame, OSD *osd,
    22                       FilterChain *filterList,
    23                       const PIPMap &pipPlayers,
    24                       FrameScanType scan);
    25     void Show(FrameScanType );
    26     bool InputChanged(const QSize &input_size, float aspect,
    27                       MythCodecID  av_codec_id, void *codec_private,
    28                       bool &aspect_only);
     23    virtual void ProcessFrame(VideoFrame *frame, OSD *osd,
     24                              FilterChain *filterList,
     25                              const PIPMap &pipPlayers,
     26                              FrameScanType scan);
     27    virtual void Show(FrameScanType );
     28    virtual bool InputChanged(const QSize &input_size, float aspect,
     29                              MythCodecID  av_codec_id, void *codec_private,
     30                              bool &aspect_only);
    2931    DisplayInfo GetDisplayInfo(void);
    3032    void UpdatePauseFrame(void);
    3133    void DrawUnusedRects(bool) { }
     
    5153    virtual bool ApproveDeintFilter(const QString& filtername) const;
    5254    virtual MythPainter *GetOSDPainter(void)  { return (MythPainter*)gl_painter; }
    5355
    54   private:
    55     bool CreateBuffers(void);
     56  protected:
     57    virtual bool CreateBuffers(void);
     58    bool CreatePauseFrame(void);
    5659    bool SetupContext(void);
    5760    bool SetupOpenGL(void);
    5861    void InitOSD(void);
  • libs/libmythtv/mythcodecid.h

     
    7676
    7777    kCodec_VDPAU_END,
    7878
     79    kCodec_VAAPI_BEGIN = kCodec_VDPAU_END,
     80
     81    kCodec_MPEG1_VAAPI,
     82    kCodec_MPEG2_VAAPI,
     83    kCodec_H263_VAAPI,
     84    kCodec_MPEG4_VAAPI,
     85    kCodec_H264_VAAPI,
     86    kCodec_VC1_VAAPI,
     87    kCodec_WMV3_VAAPI,
     88
     89    kCodec_VAAPI_END,
    7990} MythCodecID;
    8091
    8192// MythCodecID convenience functions
     
    93104                              (id < kCodec_VDPAU_END)
    94105#define codec_is_vdpau_hw(id) (codec_is_vdpau(id) &&\
    95106                              (id != kCodec_H263_VDPAU))
     107#define codec_is_vaapi(id)    (id > kCodec_VAAPI_BEGIN) &&\
     108                              (id < kCodec_VAAPI_END)
     109#define codec_is_vaapi_hw(id) (codec_is_vaapi(id) &&\
     110                              (id != kCodec_H263_VAAPI))
    96111
    97112QString get_encoding_type(MythCodecID codecid);
    98113QString get_decoder_name(MythCodecID codec_id, bool libmpeg2);
  • libs/libmythtv/mythcodecid.cpp

     
    9292        case kCodec_WMV3_VDPAU:
    9393            return "WMV3 VDPAU";
    9494
     95        case kCodec_MPEG1_VAAPI:
     96            return "MPEG1 VAAPI";
     97        case kCodec_MPEG2_VAAPI:
     98            return "MPEG2 VAAPI";
     99        case kCodec_H263_VAAPI:
     100            return "H.263 VAAPI";
     101        case kCodec_MPEG4_VAAPI:
     102            return "MPEG4 VAAPI";
     103        case kCodec_H264_VAAPI:
     104            return "H.264 VAAPI";
     105        case kCodec_VC1_VAAPI:
     106            return "VC1 VAAPI";
     107        case kCodec_WMV3_VAAPI:
     108            return "WMV3 VAAPI";
     109
    95110        default:
    96111            break;
    97112    }
     
    228243            vdpau = true;
    229244            break;
    230245
     246        case kCodec_MPEG1_VAAPI:
     247            ret = CODEC_ID_MPEG1VIDEO;
     248            vld = idct = mc = true;
     249            break;
     250        case kCodec_MPEG2_VAAPI:
     251            ret = CODEC_ID_MPEG2VIDEO;
     252            vld = idct = mc = true;
     253            break;
     254        case kCodec_H263_VAAPI:
     255            VERBOSE(VB_IMPORTANT, "Error: VAAPI H.263 not supported by ffmpeg");
     256            break;
     257        case kCodec_MPEG4_VAAPI:
     258            ret = CODEC_ID_MPEG4;
     259            vld = true;
     260            break;
     261        case kCodec_H264_VAAPI:
     262            ret = CODEC_ID_H264;
     263            vld = true;
     264            break;
     265        case kCodec_VC1_VAAPI:
     266            ret = CODEC_ID_VC1;
     267            vld = true;
     268            break;
     269        case kCodec_WMV3_VAAPI:
     270            ret = CODEC_ID_WMV3;
     271            vld = true;
     272            break;
     273
    231274        default:
    232275            VERBOSE(VB_IMPORTANT,
    233276                    QString("Error: MythCodecID %1 has not been "
     
    283326        case kCodec_MPEG2_VLD:
    284327        case kCodec_MPEG2_DVDV:
    285328        case kCodec_MPEG2_VDPAU:
     329        case kCodec_MPEG2_VAAPI:
    286330            return "MPEG-2";
    287331
    288332        case kCodec_H263:
     
    291335        case kCodec_H263_VLD:
    292336        case kCodec_H263_DVDV:
    293337        case kCodec_H263_VDPAU:
     338        case kCodec_H263_VAAPI:
    294339            return "H.263";
    295340
    296341        case kCodec_NUV_MPEG4:
     
    300345        case kCodec_MPEG4_VLD:
    301346        case kCodec_MPEG4_DVDV:
    302347        case kCodec_MPEG4_VDPAU:
     348        case kCodec_MPEG4_VAAPI:
    303349            return "MPEG-4";
    304350
    305351        case kCodec_H264:
     
    338384    if (codec_is_vdpau(codec_id))
    339385        return "vdpau";
    340386
     387    if (codec_is_vaapi(codec_id))
     388        return "vaapi";
     389
    341390    return "ffmpeg";
    342391}
  • libs/libmythtv/videooutbase.cpp

     
    4040#include "videoout_vdpau.h"
    4141#endif
    4242
     43#ifdef USING_VAAPI
     44#include "videoout_openglvaapi.h"
     45#endif
     46
    4347#include "videoout_null.h"
    4448#include "dithertable.h"
    4549
     
    96100#ifdef USING_VDPAU
    97101    VideoOutputVDPAU::GetRenderOptions(opts);
    98102#endif // USING_VDPAU
     103
     104#ifdef USING_VAAPI
     105    VideoOutputOpenGLVAAPI::GetRenderOptions(opts, cpudeints);
     106#endif // USING_VAAPI
    99107}
    100108
    101109/**
     
    143151    renderers += VideoOutputVDPAU::GetAllowedRenderers(codec_id, video_dim);
    144152#endif // USING_VDPAU
    145153
     154#ifdef USING_VAAPI
     155    renderers += VideoOutputOpenGLVAAPI::GetAllowedRenderers(codec_id, video_dim);
     156#endif // USING_VAAPI
     157
    146158    VERBOSE(VB_PLAYBACK, LOC + "Allowed renderers: " +
    147159            to_comma_list(renderers));
    148160
     
    205217            vo = new VideoOutputVDPAU(codec_id);
    206218#endif // USING_VDPAU
    207219
     220#ifdef USING_VAAPI
     221        if (renderer == "openglvaapi")
     222            vo = new VideoOutputOpenGLVAAPI(codec_id);
     223#endif // USING_VAAPI
     224
    208225#ifdef USING_XV
    209226        if (xvlist.contains(renderer))
    210227            vo = new VideoOutputXv(codec_id);
  • libs/libmythtv/vaapicontext.h

     
     1#ifndef VAAPICONTEXT_H
     2#define VAAPICONTEXT_H
     3
     4extern "C" {
     5#include "libavcodec/vaapi.h"
     6}
     7
     8#include "va/va.h"
     9#include "va/va_x11.h"
     10
     11struct vaapi_surface
     12{
     13    VASurfaceID m_id;
     14};
     15
     16class VAAPIContext
     17{
     18  public:
     19    static bool IsFormatAccelerated(QSize size, MythCodecID codec,
     20                                    PixelFormat &pix_fmt);
     21    VAAPIContext(MythCodecID codec);
     22   ~VAAPIContext();
     23
     24    bool  Create(QSize size);
     25    bool  CreateDummy(QSize size);
     26    void* GetVideoSurface(int i);
     27    int   GetNumBuffers(void)        { return m_numSurfaces; }
     28    PixelFormat GetPixelFormat(void) { return m_pix_fmt;     }
     29    uint8_t* GetSurfaceIDPointer(void* buf);
     30
     31    // temp hack
     32    void  ShowSurface(int win, QRect &rect, void* buf);
     33
     34    bool InitDisplay(void);
     35    bool InitProfiles(void);
     36    bool InitBuffers(void);
     37    bool InitContext(void);
     38
     39    vaapi_context  m_ctx;
     40    MythCodecID    m_codec;
     41    QSize          m_size;
     42    MythXDisplay  *m_display;
     43    VAProfile      m_vaProfile;
     44    VAEntrypoint   m_vaEntrypoint;
     45    PixelFormat    m_pix_fmt;
     46    int            m_numSurfaces;
     47    VASurfaceID   *m_surfaces;
     48    vaapi_surface *m_surfaceData;
     49};
     50
     51#endif // VAAPICONTEXT_H
  • libs/libmythtv/videodisplayprofile.cpp

     
    642642        dec_name["xvmc-vld"] = QObject::tr("VIA XvMC");
    643643        dec_name["macaccel"] = QObject::tr("Mac hardware acceleration");
    644644        dec_name["vdpau"]    = QObject::tr("NVidia VDPAU acceleration");
     645        dec_name["vaapi"]    = QObject::tr("VA API");
    645646    }
    646647
    647648    QString ret = decoder;
     
    691692            "VDPAU will attempt to use the graphics hardware to "
    692693            "accelerate video decoding and playback.");
    693694
     695    if (decoder == "vaapi")
     696        msg += QObject::tr(
     697            "VAAPI will attempt to use the graphics hardware to "
     698            "accelerate video decoding and playback.");
     699
    694700    return msg;
    695701}
    696702
     
    12371243            "This is the only video renderer for NVidia VDPAU decoding.");
    12381244    }
    12391245
     1246    if (renderer == "openglvaapi")
     1247    {
     1248        msg = QObject::tr(
     1249            "This is the only video renderer for VAAPI decoding.");
     1250    }
     1251
    12401252    return msg;
    12411253}