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, 21 months 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