Ticket #8593: vaapi_v118_aka_sticking_needles_in_your_eyes.diff

File vaapi_v118_aka_sticking_needles_in_your_eyes.diff, 51.7 KB (added by markk, 10 years ago)
  • home/mark/trunk/mythtv/configure

     
    125125  --enable-xvmc-vld        enable XvMC VLD accel. for the Unichrome (Pro) chipset
    126126  --xvmc-lib=LIB           XvMC library override (for crosscompiling)
    127127  --enable-vdpau           enable NVidia VDPAU hardware acceleration.
     128  --enable-vaapi           enable VAAPI hardware acceleration
    128129  --enable-crystalhd       enable Broadcom CrystalHD hardware decoder support
    129130  --disable-opengl-video   disable OpenGL based video display
    130131  --disable-quartz-video   disable Mac OS X CoreVideo based video display
     
    13581359    mythtranscode
    13591360    opengl
    13601361    vdpau
     1362    vaapi
    13611363'
    13621364
    13631365CMDLINE_SELECT="
     
    17201722xvmc_deps="xv X11_extensions_XvMClib_h"
    17211723xvmc_vld_deps="xvmc X11_extensions_vldXvMC_h"
    17221724xvmcw_deps="xvmc"
     1725vaapi_deps="x11 opengl"
    17231726
    17241727<<BLOCKQUOTE
    17251728# tests
     
    35663569check_header termios.h
    35673570check_header vdpau/vdpau.h
    35683571check_header vdpau/vdpau_x11.h
     3572check_header va/va.h
     3573check_header va/va_x11.h
     3574check_header va/va_glx.h
    35693575check_header X11/extensions/XvMClib.h
    35703576
    35713577check_struct dxva2api.h DXVA_PictureParameters wDecodedPictureIndex
     
    38443850        disable crystalhd;
    38453851fi
    38463852
     3853if enabled vaapi; then
     3854    enabled va_va_h && enabled va_va_glx_h && enabled va_va_x11_h || disable vaapi
     3855    if enabled vaapi; then
     3856        # TODO check for SDS versions
     3857        check_cpp_condition va/va.h "VA_VERSION_HEX >= 0x001F0000" ||
     3858        { echolog "VAAPI requires libva >= 0.31.1" && disable vaapi; }
     3859    fi
     3860else
     3861    disable vaapi
     3862fi
     3863
    38473864enabled debug && add_cflags -g"$debuglevel" && add_asflags -g"$debuglevel"
    38483865enabled debug && add_cxxflags -g"$debuglevel"
    38493866
     
    44054422  echo "XvMC libs                 $VENDOR_XVMC_LIBS"
    44064423fi
    44074424  echo "VDPAU support             ${vdpau-no}"
     4425  echo "VAAPI support             ${vaapi-no}"
    44084426  echo "CrystalHD support         ${crystalhd-no}"
    44094427fi
    44104428  echo "OpenGL video              ${opengl_video-no}"
  • home/mark/trunk/mythtv/external/FFmpeg/libavutil/libm.h

     
    5959#endif /* HAVE_LOG2F */
    6060
    6161#if !HAVE_LRINT
    62 static av_always_inline av_const long int lrint(double x)
    63 {
    64     return rint(x);
    65 }
     62//static av_always_inline av_const long int lrint(double x)
     63//{
     64//    return rint(x);
     65//  }
    6666#endif /* HAVE_LRINT */
    6767
    6868#if !HAVE_LRINTF
     
    7373#endif /* HAVE_LRINTF */
    7474
    7575#if !HAVE_ROUND
    76 static av_always_inline av_const double round(double x)
    77 {
    78     return (x > 0) ? floor(x + 0.5) : ceil(x - 0.5);
    79 }
     76//static av_always_inline av_const double round(double x)
     77//{
     78//    return (x > 0) ? floor(x + 0.5) : ceil(x - 0.5);
     79//}
    8080#endif /* HAVE_ROUND */
    8181
    8282#if !HAVE_ROUNDF
  • home/mark/trunk/mythtv/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);
     11
     12    VideoOutputOpenGLVAAPI(bool direct_update = false);
     13   ~VideoOutputOpenGLVAAPI();
     14
     15    bool  Init(int width, int height, float aspect, WId winid,
     16               int winx, int winy, int winw, int winh,
     17               MythCodecID codec_id, WId embedid = 0);
     18    bool  CreateVAAPIContext(QSize size);
     19    void  DeleteVAAPIContext(void);
     20    bool  CreateBuffers(void);
     21    void* GetVAAPIContext(void);
     22    uint8_t* GetSurfaceIDPointer(void* buf);
     23    void  SetProfile(void);
     24    void  TearDown(void);
     25    bool  InputChanged(const QSize &input_size, float aspect,
     26                       MythCodecID  av_codec_id, void *codec_private,
     27                       bool &aspect_only);
     28    void  ProcessFrame(VideoFrame *frame, OSD *osd,
     29                       FilterChain *filterList,
     30                       const PIPMap &pipPlayers,
     31                       FrameScanType scan);
     32    bool  ApproveDeintFilter(const QString& filtername) const;
     33    bool  SetDeinterlacingEnabled(bool enable);
     34    bool  SetupDeinterlace(bool i, const QString& ovrf="");
     35   
     36    static QStringList GetAllowedRenderers(MythCodecID myth_codec_id,
     37                                           const QSize &video_dim);
     38    static MythCodecID GetBestSupportedCodec(uint width, uint height,
     39                                             uint stream_type,
     40                                             bool no_acceleration,
     41                                             PixelFormat &pix_fmt);
     42
     43  private:
     44    VAAPIContext *m_ctx;
     45};
     46
     47#endif // VIDEOOUTPUTOPENGLVAAPI_H
     48
  • home/mark/trunk/mythtv/libs/libmythtv/videoout_opengl.cpp

     
    3939    opts.priorities->insert("opengl", 65);
    4040}
    4141
    42 VideoOutputOpenGL::VideoOutputOpenGL()
     42VideoOutputOpenGL::VideoOutputOpenGL(bool direct_update)
    4343    : VideoOutput(),
    4444    gl_context_lock(QMutex::Recursive),
    4545    gl_context(NULL), gl_videochain(NULL), gl_pipchain_active(NULL),
    46     gl_parent_win(0), gl_embed_win(0), gl_painter(NULL)
     46    gl_parent_win(0), gl_embed_win(0), gl_painter(NULL),
     47    gl_direct_update(direct_update)
    4748{
    4849    bzero(&av_pause_frame, sizeof(av_pause_frame));
    4950    av_pause_frame.buf = NULL;
     
    246247    OpenGLLocker ctx_lock(gl_context);
    247248    gl_videochain = new OpenGLVideo();
    248249    success = gl_videochain->Init(gl_context, db_use_picture_controls,
    249                                   window.GetVideoDim(), dvr,
     250                                  window.GetActualVideoDim(), dvr,
    250251                                  window.GetDisplayVideoRect(),
    251252                                  window.GetVideoRect(), true,
    252                                   GetFilters(), !codec_is_std(video_codec_id),
     253                                  GetFilters(), gl_direct_update,
    253254                                  db_letterbox_colour);
    254255    if (success)
    255256    {
  • home/mark/trunk/mythtv/libs/libmythtv/avformatdecoder.cpp

     
    5252}
    5353#endif // USING_VDPAU
    5454
     55#ifdef USING_VAAPI
     56#include "videoout_openglvaapi.h"
     57#endif // USING_VAAPI
     58
    5559extern "C" {
    5660#include "libavutil/avutil.h"
    5761#include "libavcodec/ac3_parser.h"
     
    126130void render_slice_vdpau(struct AVCodecContext *s, const AVFrame *src,
    127131                        int offset[4], int y, int type, int height);
    128132
     133int  get_avf_buffer_vaapi(struct AVCodecContext *c, AVFrame *pic);
     134
    129135static AVCodec *find_vdpau_decoder(AVCodec *c, enum CodecID id)
    130136{
    131137    AVCodec *codec = c;
     
    238244    (*opts.equiv_decoders)["vdpau"].append("dummy");
    239245#endif
    240246
     247#ifdef USING_VAAPI
     248    opts.decoders->append("vaapi");
     249    (*opts.equiv_decoders)["vaapi"].append("dummy");
     250#endif
     251
    241252    PrivateDecoder::GetDecoders(opts);
    242253}
    243254
     
    12561267        enc->draw_horiz_band = render_slice_vdpau;
    12571268        enc->slice_flags     = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
    12581269    }
     1270    else if (CODEC_IS_VAAPI(codec, enc))
     1271    {
     1272        enc->get_buffer      = get_avf_buffer_vaapi;
     1273        enc->get_format      = get_format_vaapi;
     1274        enc->release_buffer  = release_avf_buffer;
     1275        enc->slice_flags     = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
     1276    }
    12591277    else if (codec && codec->capabilities & CODEC_CAP_DR1)
    12601278    {
    12611279        enc->flags          |= CODEC_FLAG_EMU_EDGE;
     
    18011819                        handled = true;
    18021820                    }
    18031821#endif // USING_VDPAU
     1822#ifdef USING_VAAPI
     1823                    MythCodecID vaapi_mcid;
     1824                    PixelFormat pix_fmt = PIX_FMT_YUV420P;
     1825                    vaapi_mcid = VideoOutputOpenGLVAAPI::GetBestSupportedCodec(
     1826                        width, height, mpeg_version(enc->codec_id),
     1827                        no_hardware_decoders, pix_fmt);
     1828
     1829                    if (vaapi_mcid >= video_codec_id)
     1830                    {
     1831                        enc->codec_id = (CodecID)myth2av_codecid(vaapi_mcid);
     1832                        video_codec_id = vaapi_mcid;
     1833                        handled = true;
     1834                        if (!no_hardware_decoders &&
     1835                            codec_is_vaapi(video_codec_id))
     1836                        {
     1837                            enc->pix_fmt = pix_fmt;
     1838                        }
     1839                    }
     1840#endif // USING_VAAPI
    18041841#ifdef USING_XVMC
    18051842
    18061843                    bool force_xv = no_hardware_decoders;
     
    25152552    }
    25162553}
    25172554
     2555int get_avf_buffer_vaapi(struct AVCodecContext *c, AVFrame *pic)
     2556{
     2557    AvFormatDecoder *nd = (AvFormatDecoder *)(c->opaque);
     2558    VideoFrame *frame = nd->GetPlayer()->GetNextVideoFrame(false);
     2559
     2560    pic->data[0]     = frame->buf;
     2561    pic->data[1]     = NULL;
     2562    pic->data[2]     = NULL;
     2563    pic->data[3]     = NULL;
     2564    pic->linesize[0] = 0;
     2565    pic->linesize[1] = 0;
     2566    pic->linesize[2] = 0;
     2567    pic->linesize[3] = 0;
     2568    pic->opaque      = frame;
     2569    pic->type        = FF_BUFFER_TYPE_USER;
     2570    pic->age         = 256 * 256 * 256 * 64;
     2571    frame->pix_fmt   = c->pix_fmt;
     2572
     2573#ifdef USING_VAAPI
     2574    if (nd->GetPlayer()->getVideoOutput())
     2575    {
     2576        VideoOutputOpenGLVAAPI *vo =
     2577            dynamic_cast<VideoOutputOpenGLVAAPI*>(nd->GetPlayer()->getVideoOutput());
     2578        c->hwaccel_context = (vaapi_context*)vo->GetVAAPIContext();
     2579        pic->data[3] = vo->GetSurfaceIDPointer(frame->buf);
     2580    }
     2581#endif
     2582
     2583    return 0;
     2584}
     2585
    25182586void AvFormatDecoder::DecodeDTVCC(const uint8_t *buf, uint len)
    25192587{
    25202588    if (!len)
  • home/mark/trunk/mythtv/libs/libmythtv/videoout_openglvaapi.cpp

     
     1#include "videoout_openglvaapi.h"
     2
     3#define LOC  QString("VidOutGLVAAPI: ")
     4#define ERR  QString("VidOutGLVAAPI Error: ")
     5
     6void VideoOutputOpenGLVAAPI::GetRenderOptions(render_opts &opts)
     7{
     8    opts.renderers->append("openglvaapi");
     9    opts.renderers->append("openglvaapiglx");
     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    (*opts.deints)["openglvaapiglx"].append("vaapionefield");
     17    (*opts.deints)["openglvaapiglx"].append("vaapibobdeint");
     18    (*opts.deints)["openglvaapiglx"].append("none");
     19    (*opts.osds)["openglvaapiglx"].append("opengl2");
     20
     21    if (opts.decoders->contains("vaapi"))
     22    {
     23        (*opts.safe_renderers)["vaapi"].append("openglvaapi");
     24        (*opts.safe_renderers)["vaapi"].append("openglvaapiglx");
     25    }
     26    if (opts.decoders->contains("ffmpeg"))
     27    {
     28        (*opts.safe_renderers)["ffmpeg"].append("openglvaapi");
     29        (*opts.safe_renderers)["ffmpeg"].append("openglvaapiglx");
     30    }
     31    if (opts.decoders->contains("libmpeg2"))
     32    {
     33        (*opts.safe_renderers)["libmpeg2"].append("openglvaapi");
     34        (*opts.safe_renderers)["libmpeg2"].append("openglvaapiglx");
     35    }
     36
     37    (*opts.safe_renderers)["dummy"].append("openglvaapi");
     38    (*opts.safe_renderers)["nuppel"].append("openglvaapi");
     39    (*opts.safe_renderers)["dummy"].append("openglvaapiglx");
     40    (*opts.safe_renderers)["nuppel"].append("openglvaapiglx");
     41
     42    opts.priorities->insert("openglvaapi", 100);
     43    opts.priorities->insert("openglvaapiglx", 110);
     44}
     45
     46VideoOutputOpenGLVAAPI::VideoOutputOpenGLVAAPI(bool direct_update)
     47  : VideoOutputOpenGL(direct_update), m_ctx(NULL)
     48{
     49    if (gCoreContext->GetNumSetting("UseVideoModes", 0))
     50        display_res = DisplayRes::GetDisplayRes(true);
     51}
     52
     53VideoOutputOpenGLVAAPI::~VideoOutputOpenGLVAAPI()
     54{
     55    TearDown();
     56}
     57
     58void VideoOutputOpenGLVAAPI::TearDown(void)
     59{
     60    DeleteVAAPIContext();
     61}
     62
     63bool VideoOutputOpenGLVAAPI::InputChanged(const QSize &input_size, float aspect,
     64                              MythCodecID  av_codec_id, void *codec_private,
     65                              bool &aspect_only)
     66{
     67    VERBOSE(VB_PLAYBACK, LOC + QString("InputChanged(%1,%2,%3) %4->%5")
     68            .arg(input_size.width()).arg(input_size.height()).arg(aspect)
     69            .arg(toString(video_codec_id)).arg(toString(av_codec_id)));
     70
     71    if (!codec_is_vaapi(av_codec_id))
     72        return VideoOutputOpenGL::InputChanged(input_size, aspect, av_codec_id,
     73                                               codec_private, aspect_only);
     74                                                   
     75    QMutexLocker locker(&gl_context_lock);
     76    bool cid_changed = (video_codec_id != av_codec_id);
     77    bool res_changed = input_size  != window.GetActualVideoDim();
     78    bool asp_changed = aspect      != window.GetVideoAspect();
     79   
     80    if (!res_changed && !cid_changed)
     81    {
     82        if (asp_changed)
     83        {
     84            aspect_only = true;
     85            VideoAspectRatioChanged(aspect);
     86            MoveResize();
     87        }
     88        return true;
     89    }
     90
     91    TearDown();
     92    QRect disp = window.GetDisplayVisibleRect();
     93    if (Init(input_size.width(), input_size.height(),
     94             aspect, gl_parent_win, disp.left(),  disp.top(),
     95             disp.width(), disp.height(), av_codec_id, gl_embed_win))
     96    {
     97        BestDeint();
     98        return true;
     99    }
     100
     101    VERBOSE(VB_IMPORTANT, ERR + QString("Failed to re-initialise video output."));
     102    errorState = kError_Unknown;
     103
     104    return false;
     105}
     106
     107bool VideoOutputOpenGLVAAPI::Init(int width, int height, float aspect,
     108                                  WId winid, int winx, int winy, int winw,
     109                                  int winh, MythCodecID codec_id, WId embedid)
     110{
     111    if (codec_is_vaapi(codec_id))
     112    {
     113        video_codec_id = codec_id;
     114        if (!CreateVAAPIContext(QSize(width, height)))
     115            return false;
     116    }
     117
     118    return VideoOutputOpenGL::Init(width, height, aspect, winid, winx, winy,
     119                                   winw, winh, video_codec_id, embedid);
     120}
     121
     122bool VideoOutputOpenGLVAAPI::CreateVAAPIContext(QSize size)
     123{
     124    if (m_ctx)
     125        DeleteVAAPIContext();
     126    m_ctx = new VAAPIContext(video_codec_id, gl_direct_update);
     127    if (m_ctx && m_ctx->CreateDisplay(size) && m_ctx->CreateBuffers())
     128        return true;
     129    VERBOSE(VB_IMPORTANT, ERR + QString("Failed to create VAAPI context."));
     130    errorState = kError_Unknown;
     131    return false;
     132}
     133
     134void VideoOutputOpenGLVAAPI::DeleteVAAPIContext(void)
     135{
     136    delete m_ctx;
     137    m_ctx = NULL;
     138}
     139
     140bool VideoOutputOpenGLVAAPI::CreateBuffers(void)
     141{
     142    if ((!codec_is_vaapi(video_codec_id)) || !m_ctx)
     143        return VideoOutputOpenGL::CreateBuffers();
     144
     145    QMutexLocker locker(&gl_context_lock);
     146    int num_buffers = m_ctx->GetNumBuffers();
     147    const QSize video_dim = window.GetActualVideoDim();
     148    vbuffers.Init(num_buffers, true, 2, 1, 4, 1, false); // shouldn't need pause frame
     149
     150    bool ok = true;
     151    for (int i = 0; i < num_buffers; i++)
     152    {
     153        ok &= vbuffers.CreateBuffer(video_dim.width(),
     154                                    video_dim.height(), i,
     155                                    m_ctx->GetVideoSurface(i), FMT_VAAPI);
     156    }
     157    return ok;
     158}
     159
     160void* VideoOutputOpenGLVAAPI::GetVAAPIContext(void)
     161{
     162    if (m_ctx)
     163        return &m_ctx->m_ctx;
     164    return NULL;
     165}
     166
     167uint8_t* VideoOutputOpenGLVAAPI::GetSurfaceIDPointer(void* buf)
     168{
     169    if (m_ctx)
     170        return m_ctx->GetSurfaceIDPointer(buf);
     171    return NULL;
     172}
     173
     174void VideoOutputOpenGLVAAPI::SetProfile(void)
     175{
     176    if (db_vdisp_profile)
     177        db_vdisp_profile->SetVideoRenderer("openglvaapi");
     178}
     179
     180bool VideoOutputOpenGLVAAPI::ApproveDeintFilter(const QString &filtername) const
     181{
     182    return filtername.contains("vaapi");
     183}
     184
     185bool VideoOutputOpenGLVAAPI::SetDeinterlacingEnabled(bool enable)
     186{
     187    m_deinterlacing = enable;
     188    SetupDeinterlace(enable);
     189    return m_deinterlacing;
     190}
     191
     192bool VideoOutputOpenGLVAAPI::SetupDeinterlace(bool i, const QString& ovrf)
     193{
     194    m_deinterlacing = i;
     195    return m_deinterlacing;
     196}
     197
     198void VideoOutputOpenGLVAAPI::ProcessFrame(VideoFrame *frame, OSD *osd,
     199                                          FilterChain *filterList,
     200                                          const PIPMap &pipPlayers,
     201                                          FrameScanType scan)
     202{
     203    VideoOutputOpenGL::ProcessFrame(frame, osd, filterList, pipPlayers, scan);
     204
     205    QMutexLocker locker(&gl_context_lock);
     206    if (codec_is_vaapi(video_codec_id) && m_ctx && gl_videochain && frame)
     207    {
     208        bool success = false;
     209        if (gl_direct_update)
     210        {
     211            gl_context->makeCurrent();
     212            uint tex = gl_videochain->GetInputTexture();
     213            gl_context->EnableTextures(tex);           
     214            success = m_ctx->CopySurfaceToTexture(frame->buf, tex,
     215                                                  gl_videochain->GetTextureType(),
     216                                                  scan);
     217            if (success)
     218                gl_videochain->SetInputUpdated();
     219            gl_context->doneCurrent();
     220        }
     221        else
     222        {
     223            gl_context->makeCurrent();
     224            success = m_ctx->FillFrame(frame, gl_videochain);
     225            gl_context->doneCurrent();
     226        }
     227        if (!success)
     228            VERBOSE(VB_PLAYBACK, ERR + "Failed to update video texture.");
     229    }
     230}
     231
     232QStringList VideoOutputOpenGLVAAPI::GetAllowedRenderers(
     233    MythCodecID myth_codec_id, const QSize &video_dim)
     234{
     235    (void) video_dim;
     236    QStringList list;
     237    if ((codec_is_std(myth_codec_id) || (codec_is_vaapi(myth_codec_id))) &&
     238         !getenv("NO_VAAPI"))
     239    {
     240        list += "openglvaapi";
     241        list += "openglvaapiglx";
     242    }
     243    return list;
     244}
     245
     246MythCodecID VideoOutputOpenGLVAAPI::GetBestSupportedCodec(
     247    uint width,       uint height,
     248    uint stream_type, bool no_acceleration,
     249    PixelFormat &pix_fmt)
     250{
     251    static bool debug = true;
     252    if (debug)
     253    {
     254        VERBOSE(VB_IMPORTANT, LOC + "Testing VAAPI codec support");
     255        debug = false;
     256    }
     257
     258    QSize size(width, height);
     259    bool use_cpu = no_acceleration;
     260    VideoDisplayProfile vdp;
     261    vdp.SetInput(size);
     262    QString dec = vdp.GetDecoder();
     263
     264    MythCodecID test_cid = (MythCodecID)(kCodec_MPEG1_VAAPI + (stream_type-1));
     265    if (codec_is_vaapi(test_cid))
     266        use_cpu |= !VAAPIContext::IsFormatAccelerated(size, test_cid, pix_fmt);
     267    else
     268        use_cpu = true;
     269
     270    if ((dec != "vaapi") || getenv("NO_VAAPI") || use_cpu)
     271        return (MythCodecID)(kCodec_MPEG1 + (stream_type-1));
     272
     273    return test_cid;
     274}
  • home/mark/trunk/mythtv/libs/libmythtv/libmythtv.pro

     
    354354    using_opengl_video:HEADERS += openglvideo.h   videoout_opengl.h
    355355    using_opengl_video:SOURCES += openglvideo.cpp videoout_opengl.cpp
    356356
     357    using_vaapi: DEFINES += USING_VAAPI
     358    using_vaapi: DEFINES += vaapicontext.h   videoout_openglvaapi.h
     359    using_vaapi: SOURCES += vaapicontext.cpp videoout_openglvaapi.cpp
     360    using_vaapi: LIBS    += -lva -lva-x11 -lva-glx
     361
    357362    # Misc. frontend
    358363    HEADERS += DetectLetterbox.h
    359364    SOURCES += DetectLetterbox.cpp
  • home/mark/trunk/mythtv/libs/libmythtv/vaapicontext.cpp

     
     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 "myth_imgconvert.h"
     8
     9#define LOC QString("VAAPI: ")
     10#define ERR QString("VAAPI Error: ")
     11#define NUM_VAAPI_BUFFERS 20
     12
     13#ifndef VA_FOURCC_I420
     14#define VA_FOURCC_I420 0x30323449
     15#endif
     16
     17#define INIT_ST \
     18  VAStatus va_status; \
     19  bool ok = true;
     20
     21#define CHECK_ST \
     22  ok &= (va_status == VA_STATUS_SUCCESS); \
     23  if (!ok) { \
     24      VERBOSE(VB_IMPORTANT, ERR + QString("Error at %1:%2 (#%3, %4)") \
     25              .arg(__FILE__).arg( __LINE__).arg(va_status) \
     26              .arg(vaErrorStr(va_status))); \
     27  }
     28
     29#define CREATE_CHECK(arg1, arg2) \
     30  if (ok) \
     31  { \
     32      ok = arg1; \
     33      if (!ok) \
     34          VERBOSE(VB_IMPORTANT, ERR + arg2); \
     35  }
     36
     37QString profileToString(VAProfile profile);
     38QString entryToString(VAEntrypoint entry);
     39VAProfile preferredProfile(MythCodecID codec);
     40
     41QString profileToString(VAProfile profile)
     42{
     43    if (VAProfileMPEG2Simple == profile)         return "MPEG2Simple";
     44    if (VAProfileMPEG2Main == profile)           return "MPEG2Main";
     45    if (VAProfileMPEG4Simple == profile)         return "MPEG4Simple";
     46    if (VAProfileMPEG4AdvancedSimple == profile) return "MPEG4AdvSimple";
     47    if (VAProfileMPEG4Main == profile)           return "MPEG4Main";
     48    if (VAProfileH264Baseline == profile)        return "H264Base";
     49    if (VAProfileH264Main == profile)            return "H264Main";
     50    if (VAProfileH264High == profile)            return "H264High";
     51    if (VAProfileVC1Simple == profile)           return "VC1Simple";
     52    if (VAProfileVC1Main == profile)             return "VC1Main";
     53    if (VAProfileVC1Advanced == profile)         return "VC1Advanced";
     54    if (VAProfileH263Baseline == profile)        return "H263Base";
     55    return "Unknown";
     56}
     57
     58QString entryToString(VAEntrypoint entry)
     59{
     60    if (VAEntrypointVLD == entry)        return "VLD ";
     61    if (VAEntrypointIZZ == entry)        return "IZZ (UNSUPPORTED) ";
     62    if (VAEntrypointIDCT == entry)       return "IDCT (UNSUPPORTED) ";
     63    if (VAEntrypointMoComp == entry)     return "MC (UNSUPPORTED) ";
     64    if (VAEntrypointDeblocking == entry) return "Deblock (UNSUPPORTED) ";
     65    if (VAEntrypointEncSlice == entry)   return "EncSlice (UNSUPPORTED) ";
     66    return "Unknown";
     67}
     68
     69VAProfile preferredProfile(MythCodecID codec)
     70{
     71    // FIXME handle unsupported codecs properly
     72    if (kCodec_H263_VAAPI  == codec) return VAProfileMPEG4AdvancedSimple;
     73    if (kCodec_MPEG4_VAAPI == codec) return VAProfileMPEG4AdvancedSimple;
     74    if (kCodec_H264_VAAPI  == codec) return VAProfileH264High;
     75    if (kCodec_VC1_VAAPI   == codec) return VAProfileVC1Advanced;
     76    if (kCodec_WMV3_VAAPI  == codec) return VAProfileVC1Main;
     77    return VAProfileMPEG2Main;
     78}
     79
     80class VAAPIDisplay
     81{
     82  public:
     83    VAAPIDisplay() : m_va_disp(NULL), m_x_disp(NULL), m_ref_count(0) { }
     84   ~VAAPIDisplay()
     85    {
     86        if (m_va_disp)
     87        {
     88            INIT_ST
     89            XLOCK(m_x_disp, va_status = vaTerminate(m_va_disp));
     90            CHECK_ST
     91        }
     92        if (m_x_disp)
     93        {
     94            m_x_disp->Sync(true);
     95            delete m_x_disp;
     96        }
     97    }
     98
     99    bool Create(bool use_glx)
     100    {
     101        m_x_disp = OpenMythXDisplay();
     102        if (!m_x_disp)
     103            return false;
     104
     105        MythXLocker locker(m_x_disp);
     106        int major_ver, minor_ver;
     107
     108        if (use_glx)
     109            m_va_disp = vaGetDisplayGLX(m_x_disp->GetDisplay());
     110        else
     111            m_va_disp = vaGetDisplay(m_x_disp->GetDisplay());
     112
     113        if (!m_va_disp)
     114        {
     115            VERBOSE(VB_IMPORTANT, ERR + "Failed to create VADisplay");
     116            return false;
     117        }
     118
     119        INIT_ST
     120        va_status = vaInitialize(m_va_disp, &major_ver, &minor_ver);
     121        CHECK_ST
     122
     123        static bool debugged = false;
     124        if (ok && !debugged)
     125        {
     126            debugged = true;
     127            VERBOSE(VB_IMPORTANT, LOC + QString("Version: %1.%2")
     128                                        .arg(major_ver).arg(minor_ver));
     129            VERBOSE(VB_IMPORTANT, LOC + QString("Vendor : %1")
     130                                        .arg(vaQueryVendorString(m_va_disp)));
     131        }
     132        if (ok)
     133        {
     134            UpRef();
     135            VERBOSE(VB_PLAYBACK, LOC +
     136                    QString("Created VAAPI display (GLX: %1)").arg(use_glx));
     137        }
     138        return ok;
     139    }
     140
     141    void UpRef(void)
     142    {
     143        XLOCK(m_x_disp, m_ref_count++)
     144    }
     145
     146    void DownRef(void)
     147    {
     148        m_x_disp->Lock();
     149        m_ref_count--;
     150        if (m_ref_count <= 0)
     151        {
     152            if (gVAAPIDisplay == this)
     153                gVAAPIDisplay = NULL;
     154            VERBOSE(VB_PLAYBACK, LOC + "Deleting VAAPI display.");
     155            m_x_disp->Unlock();
     156            delete this;
     157            return;
     158        }
     159        m_x_disp->Unlock();
     160    }
     161
     162    static VAAPIDisplay* GetDisplay(bool use_glx)
     163    {
     164        if (gVAAPIDisplay)
     165        {
     166            gVAAPIDisplay->UpRef();
     167            return gVAAPIDisplay;
     168        }
     169
     170        gVAAPIDisplay = new VAAPIDisplay();
     171        if (gVAAPIDisplay && gVAAPIDisplay->Create(use_glx))
     172            return gVAAPIDisplay;
     173
     174        delete gVAAPIDisplay;
     175        gVAAPIDisplay = NULL;
     176        return NULL;
     177    }
     178
     179    static VAAPIDisplay *gVAAPIDisplay;
     180    void                *m_va_disp;
     181    MythXDisplay        *m_x_disp;
     182    int                  m_ref_count;
     183};
     184
     185VAAPIDisplay* VAAPIDisplay::gVAAPIDisplay = NULL;
     186
     187bool VAAPIContext::IsFormatAccelerated(QSize size, MythCodecID codec,
     188                                       PixelFormat &pix_fmt)
     189{
     190    bool result = false;
     191    VAAPIContext *ctx = new VAAPIContext(codec, false);
     192    if (ctx)
     193    {
     194        result  = ctx->CreateDisplay(size);
     195        pix_fmt = ctx->GetPixelFormat();
     196    }
     197    delete ctx;
     198    return result;
     199}
     200
     201VAAPIContext::VAAPIContext(MythCodecID codec, bool use_glx)
     202  : m_use_glx(use_glx), m_codec(codec),
     203    m_vaProfile(VAProfileMPEG2Main)/* ?? */,
     204    m_vaEntrypoint(VAEntrypointEncSlice),
     205    m_pix_fmt(PIX_FMT_YUV420P), m_numSurfaces(NUM_VAAPI_BUFFERS),
     206    m_surfaces(NULL), m_surfaceData(NULL)
     207{
     208    memset(&m_ctx, 0, sizeof(vaapi_context));
     209    memset(&m_image, 0, sizeof(VAImage));
     210    init(&m_frame, FMT_NONE, NULL, 0, 0, 0);
     211}
     212
     213VAAPIContext::~VAAPIContext()
     214{
     215    if (m_frame.buf)
     216        delete [] m_frame.buf;
     217
     218    ClearGLXSurfaces();
     219
     220    if (m_display)
     221    {
     222        m_display->m_x_disp->Lock();
     223
     224        INIT_ST
     225        if (m_image.image_id != VA_INVALID_ID)
     226        {
     227            va_status = vaDestroyImage(m_ctx.display, m_image.image_id);
     228            CHECK_ST
     229        }
     230        if (m_ctx.context_id)
     231        {
     232            va_status = vaDestroyContext(m_ctx.display, m_ctx.context_id);
     233            CHECK_ST
     234        }
     235        if (m_ctx.config_id)
     236        {
     237            va_status = vaDestroyConfig(m_ctx.display, m_ctx.config_id);
     238            CHECK_ST
     239        }
     240        if (m_surfaces)
     241        {
     242            va_status = vaDestroySurfaces(m_ctx.display, m_surfaces, m_numSurfaces);
     243            CHECK_ST
     244        }
     245    }
     246
     247    if (m_surfaces)
     248        delete [] m_surfaces;
     249    if (m_surfaceData)
     250        delete [] m_surfaceData;
     251
     252    if (m_display)
     253    {
     254        m_display->m_x_disp->Unlock();
     255        m_display->DownRef();
     256    }
     257
     258    VERBOSE(VB_PLAYBACK, LOC + "Deleted context");
     259}
     260
     261bool VAAPIContext::CreateDisplay(QSize size)\
     262{
     263    m_size = size;
     264    bool ok = true;
     265    m_display = VAAPIDisplay::GetDisplay(m_use_glx);
     266    CREATE_CHECK(!m_size.isEmpty(), "Invalid size")
     267    CREATE_CHECK(m_display != NULL, "Invalid display")
     268    CREATE_CHECK(InitDisplay(),     "Invalid VADisplay")
     269    CREATE_CHECK(InitProfiles(),    "No supported profiles")
     270    if (ok)
     271        VERBOSE(VB_PLAYBACK, LOC + QString("Created ctx display (%1x%2->%3x%4)")
     272            .arg(size.width()).arg(size.height())
     273            .arg(m_size.width()).arg(m_size.height()));
     274    return ok;
     275}
     276
     277bool VAAPIContext::CreateBuffers(void)
     278{
     279    bool ok = true;
     280    CREATE_CHECK(!m_size.isEmpty(), "Invalid size")
     281    CREATE_CHECK(InitBuffers(),     "Failed to create buffers.")
     282    CREATE_CHECK(InitContext(),     "Failed to create context")
     283    if (!m_use_glx)
     284        CREATE_CHECK(InitImage(), "Failed to create VAImage.")
     285    if (ok)
     286        VERBOSE(VB_PLAYBACK, LOC + "Created buffers");
     287    return ok;
     288}
     289
     290bool VAAPIContext::InitDisplay(void)
     291{
     292    if (!m_display)
     293        return false;
     294    m_ctx.display = m_display->m_va_disp;
     295    return m_ctx.display;
     296}
     297
     298bool VAAPIContext::InitProfiles(void)
     299{
     300    if (!(codec_is_vaapi(m_codec)) || !m_ctx.display)
     301        return false;
     302
     303    MythXLocker locker(m_display->m_x_disp);
     304    int max_profiles, max_entrypoints;
     305    VAProfile profile_wanted = preferredProfile(m_codec);
     306    VAProfile profile_found  = VAProfileMPEG2Main;   // FIXME
     307    VAEntrypoint entry_found = VAEntrypointEncSlice; // unsupported value
     308
     309    max_profiles          = vaMaxNumProfiles(m_ctx.display);
     310    max_entrypoints       = vaMaxNumEntrypoints(m_ctx.display);
     311    VAProfile *profiles   = new VAProfile[max_profiles];
     312    VAEntrypoint *entries = new VAEntrypoint[max_entrypoints];
     313
     314    static bool debugged = false;
     315    if (profiles && entries)
     316    {
     317        INIT_ST
     318        int act_profiles, act_entries;
     319        va_status = vaQueryConfigProfiles(m_ctx.display,
     320                                          profiles,
     321                                         &act_profiles);
     322        CHECK_ST
     323        if (ok && act_profiles > 0)
     324        {
     325            for (int i = 0; i < act_profiles; i++)
     326            {
     327                va_status = vaQueryConfigEntrypoints(m_ctx.display,
     328                                                     profiles[i],
     329                                                     entries,
     330                                                    &act_entries);
     331                if (va_status == VA_STATUS_SUCCESS && act_entries > 0)
     332                {
     333                    if (profiles[i] == profile_wanted)
     334                    {
     335                        profile_found = profile_wanted;
     336                        for (int j = 0; j < act_entries; j++)
     337                            if (entries[j] < entry_found)
     338                                entry_found = entries[j];
     339                    }
     340
     341                    if (!debugged)
     342                    {
     343                        QString entrylist = "Entrypoints: ";
     344                        for (int j = 0; j < act_entries; j++)
     345                            entrylist += entryToString(entries[j]);
     346                        VERBOSE(VB_IMPORTANT, LOC + QString("Profile: %1 %2")
     347                            .arg(profileToString(profiles[i])).arg(entrylist));
     348                    }
     349                }
     350            }
     351        }
     352        debugged = true;
     353    }
     354    delete profiles;
     355    delete entries;
     356
     357    VERBOSE(VB_PLAYBACK, LOC + QString("Desired profile for '%1': %2")
     358        .arg(toString(m_codec)).arg(profileToString(profile_wanted)));
     359    VERBOSE(VB_PLAYBACK, LOC + QString("Found profile %1 with entry %2")
     360        .arg(profileToString(profile_found)).arg(entryToString(entry_found)));
     361
     362    if (profile_wanted != profile_found)
     363    {
     364        VERBOSE(VB_IMPORTANT, ERR + "Failed to find supported profile.");
     365        return false;
     366    }
     367
     368    if (entry_found > VAEntrypointVLD)
     369    {
     370        VERBOSE(VB_IMPORTANT, ERR + "Failed to find suitable entry point.");
     371        return false;
     372    }
     373
     374    m_vaProfile = profile_wanted;
     375    m_vaEntrypoint = entry_found;
     376    if (VAEntrypointVLD == m_vaEntrypoint)
     377        m_pix_fmt = PIX_FMT_VAAPI_VLD;
     378    return true;
     379}
     380
     381bool VAAPIContext::InitBuffers(void)
     382{
     383    if (!m_ctx.display)
     384        return false;
     385       
     386    MythXLocker locker(m_display->m_x_disp);
     387    m_surfaces    = new VASurfaceID[m_numSurfaces];
     388    m_surfaceData = new vaapi_surface[m_numSurfaces];
     389
     390    if (!m_surfaces || !m_surfaceData)
     391        return false;
     392
     393    INIT_ST
     394    va_status = vaCreateSurfaces(m_ctx.display, m_size.width(), m_size.height(),
     395                                 VA_RT_FORMAT_YUV420, m_numSurfaces,
     396                                 m_surfaces);
     397    CHECK_ST
     398
     399    for (int i = 0; i < m_numSurfaces; i++)
     400        m_surfaceData[i].m_id = m_surfaces[i];
     401    return ok;
     402}
     403
     404bool VAAPIContext::InitContext(void)
     405{
     406    if (!m_ctx.display || m_vaEntrypoint > VAEntrypointVLD)
     407        return false;
     408
     409    MythXLocker locker(m_display->m_x_disp);
     410    VAConfigAttrib attrib;
     411    attrib.type = VAConfigAttribRTFormat;
     412    INIT_ST
     413    va_status = vaGetConfigAttributes(m_ctx.display, m_vaProfile,
     414                                      m_vaEntrypoint, &attrib, 1);
     415    CHECK_ST
     416
     417    if (!ok || !(attrib.value & VA_RT_FORMAT_YUV420))
     418    {
     419        VERBOSE(VB_IMPORTANT, ERR + "Failed to confirm YUV420 chroma");
     420        return false;
     421    }
     422
     423    va_status = vaCreateConfig(m_ctx.display, m_vaProfile, m_vaEntrypoint,
     424                               &attrib, 1, &m_ctx.config_id);
     425    CHECK_ST
     426    if (!ok)
     427    {
     428        VERBOSE(VB_IMPORTANT, ERR + "Failed to create decoder config.");
     429        return false;
     430    }
     431
     432    va_status = vaCreateContext(m_ctx.display, m_ctx.config_id,
     433                                m_size.width(), m_size.height(), VA_PROGRESSIVE,
     434                                m_surfaces, m_numSurfaces,
     435                                &m_ctx.context_id);
     436    CHECK_ST
     437    if (!ok)
     438    {
     439        VERBOSE(VB_IMPORTANT, ERR + "Failed to create decoder context.");
     440        return false;
     441    }
     442    return true;
     443}
     444
     445bool VAAPIContext::InitImage(void)
     446{
     447    int count = vaMaxNumImageFormats(m_ctx.display);
     448    if (!count)
     449        return false;
     450
     451    INIT_ST
     452    VAImageFormat *fmts = new VAImageFormat[count];
     453    va_status = vaQueryImageFormats(m_ctx.display, fmts, &count);
     454    CHECK_ST
     455    if (!ok)
     456    {
     457        delete [] fmts;
     458        return false;
     459    }
     460
     461    for (int i = 0; i < count; i++)
     462    {
     463        if (!(fmts[i].fourcc == VA_FOURCC_YV12 ||
     464              fmts[i].fourcc == VA_FOURCC_NV12 ||
     465              fmts[i].fourcc == VA_FOURCC_I420))
     466        {
     467            continue;
     468        }
     469
     470        VERBOSE(VB_PLAYBACK, LOC + QString("Testing image format %1: %2")
     471                .arg(i+1).arg(fourcc_str(fmts[i].fourcc)));
     472
     473        INIT_ST
     474        va_status = vaCreateImage(m_ctx.display, &fmts[i],
     475                                  m_size.width(), m_size.height(), &m_image);
     476        CHECK_ST
     477        if (m_image.image_id == VA_INVALID_ID)
     478        {
     479            VERBOSE(VB_IMPORTANT, LOC + "Failed to create VAImage");
     480            continue;
     481        }
     482
     483        if (m_image.width != m_size.width() || m_image.height != m_size.height())
     484            VERBOSE(VB_IMPORTANT, LOC + "VAImage size does not match frame size.");
     485
     486        va_status = vaGetImage(m_ctx.display, m_surfaces[0], 0, 0,
     487                               m_image.width, m_image.height,
     488                               m_image.image_id);
     489        if (VA_STATUS_SUCCESS == va_status)
     490        {
     491            VERBOSE(VB_PLAYBACK, LOC + QString("Using %1 image format")
     492                    .arg(fourcc_str(fmts[i].fourcc)));
     493
     494            init(&m_frame, FMT_YV12, NULL, m_image.width, m_image.height,
     495                 (m_image.width * m_image.height * 3) / 2);
     496
     497            if (m_image.format.fourcc == VA_FOURCC_NV12)
     498            {
     499                m_frame.buf = new unsigned char[m_frame.size];
     500            }
     501            else
     502            {
     503                m_frame.pitches[0] = (int)m_image.pitches[0];
     504                m_frame.offsets[0] = (int)m_image.offsets[0];
     505                int u = m_image.format.fourcc == VA_FOURCC_I420 ? 1 : 2;
     506                int v = m_image.format.fourcc == VA_FOURCC_I420 ? 2 : 1;
     507                m_frame.pitches[1] = (int)m_image.pitches[u];
     508                m_frame.pitches[2] = (int)m_image.pitches[v];
     509                m_frame.offsets[1] = (int)m_image.offsets[u];
     510                m_frame.offsets[2] = (int)m_image.offsets[v];
     511            }
     512            return true;
     513        }
     514        vaDestroyImage(m_ctx.display, m_image.image_id);
     515    }
     516    return false;
     517}
     518
     519void* VAAPIContext::GetVideoSurface(int i)
     520{
     521    if (i < 0 || i >= m_numSurfaces)
     522        return NULL;
     523    return &m_surfaceData[i];
     524}
     525
     526uint8_t* VAAPIContext::GetSurfaceIDPointer(void* buf)
     527{
     528    if (!buf)
     529        return NULL;
     530
     531    const vaapi_surface *surf = (vaapi_surface*)buf;
     532    INIT_ST
     533    va_status = vaSyncSurface(m_ctx.display, surf->m_id);
     534    CHECK_ST
     535    return (uint8_t*)(uintptr_t)surf->m_id;
     536}
     537
     538bool VAAPIContext::FillFrame(VideoFrame *frame, OpenGLVideo *chain)
     539{
     540    if (!frame || !chain || m_use_glx)
     541        return false;
     542
     543    const vaapi_surface *surf = (vaapi_surface*)frame->buf;
     544    if (!surf)
     545        return false;
     546
     547    VASurfaceID id = surf->m_id;
     548
     549    INIT_ST
     550    VASurfaceStatus status;
     551    va_status = vaQuerySurfaceStatus(m_ctx.display, id, &status);
     552    CHECK_ST
     553    if (VASurfaceReady != status)
     554    {
     555        VERBOSE(VB_PLAYBACK, LOC + QString("Surface not ready %1")
     556                .arg(status));
     557        return true;
     558    }
     559
     560    m_display->m_x_disp->Lock();
     561    va_status = vaGetImage(m_ctx.display, id, 0, 0,
     562                           m_image.width, m_image.height,
     563                           m_image.image_id);
     564    if (!ok)
     565        return false;
     566
     567    uint8_t *buffer = NULL;
     568    va_status = vaMapBuffer(m_ctx.display, m_image.buf, (void**)&buffer);
     569    CHECK_ST
     570    if (!buffer)
     571        return false;
     572
     573    if (m_image.format.fourcc == VA_FOURCC_NV12)
     574    {
     575        AVPicture img_in, img_out;
     576        avpicture_fill(&img_out, (uint8_t *)m_frame.buf, PIX_FMT_YUV420P,
     577                       m_image.width, m_image.height);
     578        avpicture_fill(&img_in, buffer, PIX_FMT_NV12,
     579                       m_image.width, m_image.height);
     580        myth_sws_img_convert(&img_out, PIX_FMT_YUV420P, &img_in, PIX_FMT_NV12,
     581                       m_image.width, m_image.height);
     582    }
     583    else
     584        m_frame.buf = (unsigned char*)buffer;
     585
     586    m_frame.interlaced_frame = frame->interlaced_frame;
     587    chain->UpdateInputFrame(&m_frame, false);
     588    va_status = vaUnmapBuffer(m_ctx.display, m_image.buf);
     589    m_display->m_x_disp->Unlock();
     590
     591    if (m_image.format.fourcc != VA_FOURCC_NV12)
     592        m_frame.buf = NULL;
     593    CHECK_ST
     594    return true;
     595}
     596
     597bool VAAPIContext::CopySurfaceToTexture(const void* buf, uint texture,
     598                                        uint texture_type,
     599                                        FrameScanType scan)
     600{
     601    if (!buf || !texture || !m_use_glx)
     602        return false;
     603
     604    const vaapi_surface *surf = (vaapi_surface*)buf;
     605    void* glx_surface = GetGLXSurface(texture, texture_type);
     606    if (!glx_surface)
     607        return false;
     608
     609    int field = VA_FRAME_PICTURE;
     610    if (scan == kScan_Interlaced)
     611        field = VA_TOP_FIELD;
     612    else if (scan == kScan_Intr2ndField)
     613        field = VA_BOTTOM_FIELD;
     614    INIT_ST
     615    XLOCK(m_display->m_x_disp,
     616          va_status = vaCopySurfaceGLX(m_ctx.display, glx_surface,
     617                                       surf->m_id, field));
     618    CHECK_ST
     619    return true;
     620}
     621
     622void* VAAPIContext::GetGLXSurface(uint texture, uint texture_type)
     623{
     624    if (m_glxSurfaces.contains(texture))
     625        return m_glxSurfaces.value(texture);
     626
     627    void *glx_surface = NULL;
     628    INIT_ST
     629    XLOCK(m_display->m_x_disp,
     630          va_status = vaCreateSurfaceGLX(m_ctx.display, texture_type,
     631                                         texture, &glx_surface));
     632    CHECK_ST
     633    if (!glx_surface)
     634    {
     635        VERBOSE(VB_IMPORTANT, ERR + "Failed to create GLX surface.");
     636        return NULL;
     637    }
     638
     639    m_glxSurfaces.insert(texture, glx_surface);
     640
     641    VERBOSE(VB_PLAYBACK, LOC + QString("Number of VAAPI GLX surfaces: %1")
     642        .arg(m_glxSurfaces.size()));
     643    return glx_surface;
     644}
     645
     646void VAAPIContext::ClearGLXSurfaces(void)
     647{
     648    if (!m_display)
     649        return;
     650
     651    m_display->m_x_disp->Lock();
     652    INIT_ST
     653    foreach (void* surface, m_glxSurfaces)
     654    {
     655        va_status = vaDestroySurfaceGLX(m_ctx.display, surface);
     656        CHECK_ST
     657    }
     658    m_glxSurfaces.clear();
     659    m_display->m_x_disp->Unlock();
     660}
  • home/mark/trunk/mythtv/libs/libmythtv/videoout_opengl.h

     
    1010{
    1111  public:
    1212    static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
    13     VideoOutputOpenGL();
     13    VideoOutputOpenGL(bool direct_update = false);
    1414    virtual ~VideoOutputOpenGL();
    1515
    1616    virtual bool Init(int width, int height, float aspect, WId winid,
     
    7070    VideoFrame        av_pause_frame;
    7171
    7272    MythOpenGLPainter *gl_painter;
     73    bool               gl_direct_update;
    7374};
    7475
    7576#endif
  • home/mark/trunk/mythtv/libs/libmythtv/openglvideo.h

     
    4444              QSize videoDim, QRect displayVisibleRect,
    4545              QRect displayVideoRect, QRect videoRect,
    4646              bool viewport_control,  QString options,
    47               bool hwaccel,
     47              bool force_rgbatex,
    4848              LetterBoxColour letterbox_colour = kLetterBoxColour_Black);
    4949
    5050    uint GetInputTexture(void);
     
    128128    OpenGLFilterType defaultUpsize;
    129129    uint           gl_features;
    130130    bool           using_ycbcrtex;
    131     bool           using_hardwaretex;
     131    bool           using_rgbatex;
    132132    LetterBoxColour gl_letterbox_colour;
    133133};
    134134#endif // _OPENGL_VIDEO_H__
  • home/mark/trunk/mythtv/libs/libmythtv/openglvideo.cpp

     
    8484    textureRects(false),      textureType(GL_TEXTURE_2D),
    8585    helperTexture(0),         defaultUpsize(kGLFilterResize),
    8686    gl_features(0),           using_ycbcrtex(false),
    87     using_hardwaretex(false),
     87    using_rgbatex(false),
    8888    gl_letterbox_colour(kLetterBoxColour_Black)
    8989{
    9090}
     
    140140                       QSize videoDim, QRect displayVisibleRect,
    141141                       QRect displayVideoRect, QRect videoRect,
    142142                       bool viewport_control, QString options,
    143                        bool hw_accel,
     143                       bool force_rgbatex,
    144144                       LetterBoxColour letterbox_colour)
    145145{
    146146    gl_context            = glcontext;
     
    177177
    178178    SetViewPort(display_visible_rect.size());
    179179
    180     using_hardwaretex   = hw_accel;
    181     bool use_pbo        = !using_hardwaretex && (gl_features & kGLExtPBufObj);
     180    using_rgbatex       = force_rgbatex;
     181    bool use_pbo        = gl_features & kGLExtPBufObj;
    182182    bool basic_features = gl_features & kGLExtFragProg;
    183183    bool full_features  = basic_features && (gl_features & kGLExtFBufObj);
    184     using_ycbcrtex      = !using_hardwaretex && !full_features &&
     184    using_ycbcrtex      = !using_rgbatex && !full_features &&
    185185                          (gl_features & kGLMesaYCbCr);
    186186
    187187    if (using_ycbcrtex)
     
    196196                QString("No OpenGL feature support for Bicubic filter."));
    197197    }
    198198
    199     if (!using_hardwaretex &&
     199    if (!using_rgbatex &&
    200200        (defaultUpsize != kGLFilterBicubic) && (gl_features & kGLExtRect))
    201201        textureType = gl_context->GetTextureType(textureRects);
    202202
    203203    GLuint tex = 0;
    204204    bool    ok = false;
    205205
    206     if (basic_features && !using_hardwaretex)
     206    if (basic_features && !using_rgbatex)
    207207    {
    208208        tex = CreateVideoTexture(actual_video_dim, inputTextureSize, use_pbo);
    209209        ok = tex && AddFilter(kGLFilterYUV2RGB);
    210210    }
    211     else if (using_ycbcrtex || using_hardwaretex)
     211    else if (using_ycbcrtex || using_rgbatex)
    212212    {
    213213        tex = CreateVideoTexture(actual_video_dim,
    214214                                 inputTextureSize, use_pbo);
     
    216216        if (ok && using_ycbcrtex)
    217217            VERBOSE(VB_PLAYBACK, LOC + QString("Using GL_MESA_ycbcr_texture for"
    218218                                               " colorspace conversion."));
    219         else if (ok && using_hardwaretex)
     219        else if (ok && using_rgbatex)
    220220            VERBOSE(VB_PLAYBACK, LOC + QString("Using plain RGBA tex for hw accel."));
    221221        else
    222222        {
    223223            using_ycbcrtex = false;
    224             using_hardwaretex = false;
     224            using_rgbatex = false;
    225225        }
    226226    }
    227227
     
    717717        tmp_tex = gl_context->CreateTexture(size, use_pbo, textureType,
    718718                                            GL_UNSIGNED_SHORT_8_8_MESA,
    719719                                            GL_YCBCR_MESA, GL_YCBCR_MESA);
    720     else if (using_hardwaretex)
    721         tmp_tex = gl_context->CreateTexture(size, use_pbo, textureType,
    722                                             GL_UNSIGNED_BYTE, GL_RGBA,
    723                                             GL_RGBA, GL_LINEAR,
    724                                             GL_CLAMP_TO_EDGE);
    725720    else
    726721        tmp_tex = gl_context->CreateTexture(size, use_pbo, textureType);
    727722    tex_size = gl_context->GetTextureSize(textureType, size);
     
    785780    {
    786781        return;
    787782    }
     783
    788784    if (hardwareDeinterlacing)
    789785        RotateTextures();
    790786
  • home/mark/trunk/mythtv/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);
     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    const QStringList vaapilist
     156            = VideoOutputOpenGLVAAPI::GetAllowedRenderers(codec_id, video_dim);
     157    renderers += vaapilist;
     158#endif // USING_VAAPI
     159
    146160    VERBOSE(VB_PLAYBACK, LOC + "Allowed renderers: " +
    147161            to_comma_list(renderers));
    148162
     
    205219            vo = new VideoOutputVDPAU();
    206220#endif // USING_VDPAU
    207221
     222#ifdef USING_VAAPI
     223        if (renderer == "openglvaapi")
     224            vo = new VideoOutputOpenGLVAAPI();
     225        if (renderer == "openglvaapiglx")
     226            vo = new VideoOutputOpenGLVAAPI(true);
     227#endif // USING_VAAPI
     228
    208229#ifdef USING_XV
    209230        if (xvlist.contains(renderer))
    210231            vo = new VideoOutputXv();
  • home/mark/trunk/mythtv/libs/libmythtv/vaapicontext.h

     
     1#ifndef VAAPICONTEXT_H
     2#define VAAPICONTEXT_H
     3
     4#include <QHash>
     5
     6extern "C" {
     7#include "libavcodec/vaapi.h"
     8}
     9#include "va/va.h"
     10#include "va/va_x11.h"
     11#include "va/va_glx.h"
     12
     13struct vaapi_surface
     14{
     15    VASurfaceID m_id;
     16};
     17
     18class VAAPIDisplay;
     19class OpenGLVideo;
     20
     21class VAAPIContext
     22{
     23  public:
     24    static bool IsFormatAccelerated(QSize size, MythCodecID codec,
     25                                    PixelFormat &pix_fmt);
     26    VAAPIContext(MythCodecID codec, bool use_glx);
     27   ~VAAPIContext();
     28
     29    bool  CreateDisplay(QSize size);
     30    bool  CreateBuffers(void);
     31    void* GetVideoSurface(int i);
     32    uint8_t* GetSurfaceIDPointer(void* buf);
     33   
     34    int   GetNumBuffers(void)        { return m_numSurfaces; }
     35    PixelFormat GetPixelFormat(void) { return m_pix_fmt;     }
     36
     37    bool FillFrame(VideoFrame *frame, OpenGLVideo *chain);
     38
     39    bool  CopySurfaceToTexture(const void* buf, uint texture, uint texture_type,
     40                               FrameScanType scan);
     41    void* GetGLXSurface(uint texture, uint texture_type);
     42    void  ClearGLXSurfaces(void);
     43
     44    bool InitDisplay(void);
     45    bool InitProfiles(void);
     46    bool InitBuffers(void);
     47    bool InitContext(void);
     48    bool InitImage(void);
     49
     50    bool           m_use_glx;
     51    vaapi_context  m_ctx;
     52    MythCodecID    m_codec;
     53    QSize          m_size;
     54    VAAPIDisplay  *m_display;
     55    VAProfile      m_vaProfile;
     56    VAEntrypoint   m_vaEntrypoint;
     57    PixelFormat    m_pix_fmt;
     58    int            m_numSurfaces;
     59    VASurfaceID   *m_surfaces;
     60    vaapi_surface *m_surfaceData;
     61    QHash<uint, void*> m_glxSurfaces;
     62    VAImage        m_image;
     63    VideoFrame     m_frame;
     64};
     65
     66#endif // VAAPICONTEXT_H
  • home/mark/trunk/mythtv/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("VAAPI acceleration");
    645646    }
    646647
    647648    QString ret = decoder;
     
    680681    if (decoder == "xvmc-vld")
    681682        msg += QObject::tr("VIA XvMC will use the VIA VLD XvMC extension.");
    682683
    683 
    684684    if (decoder == "macaccel")
    685685        msg += QObject::tr(
    686686            "Mac hardware will try to use the graphics "
     
    691691            "VDPAU will attempt to use the graphics hardware to "
    692692            "accelerate video decoding and playback.");
    693693
     694    if (decoder == "vaapi")
     695        msg += QObject::tr(
     696            "VAAPI will attempt to use the graphics hardware to "
     697            "accelerate video decoding.");
    694698    return msg;
    695699}
    696700
     
    748752        return QObject::tr("Advanced (1x, HW)");
    749753    else if ("vdpauadvanceddoublerate" == short_name)
    750754        return QObject::tr("Advanced (2x, HW)");
     755    else if ("vaapionefield" == short_name)
     756        return QObject::tr("One Field (1x, HW)");
     757    else if ("vaapibobdeint" == short_name)
     758        return QObject::tr("Bob (2x, HW)");
    751759
    752760    return "";
    753761}
     
    12371245            "This is the only video renderer for NVidia VDPAU decoding.");
    12381246    }
    12391247
     1248    if (renderer == "openglvaapi")
     1249    {
     1250        msg = QObject::tr(
     1251             "This video renderer uses VAAPI for video decoding and "
     1252             "OpenGL for scaling and color conversion.");
     1253    }
     1254
     1255    if (renderer == "openglvaapiglx")
     1256    {
     1257        msg = QObject::tr(
     1258             "This video renderer uses VAAPI for video decoding and "
     1259             "OpenGL for scaling and color conversion. Video frames are "
     1260             "transferred directly from VAAPI to OpenGL.");
     1261    }
     1262
    12401263    return msg;
    12411264}
    12421265
     
    13701393        msg = kBasicMsg + " " +  kDoubleRateMsg + " " + kUsingGPU;
    13711394    else if (deint == "vdpauadvanceddoublerate")
    13721395        msg = kAdvMsg + " " +  kDoubleRateMsg + " " + kUsingGPU;
     1396    else if (deint == "vaapionefield")
     1397        msg = kOneFieldMsg + " " + kUsingGPU;
     1398    else if (deint == "vaapibobdeint")
     1399        msg = kBobMsg + " " + kUsingGPU;
    13731400    else
    13741401        msg = QObject::tr("'%1' has not been documented yet.").arg(deint);
    13751402