Ticket #13311: 20180829_working_vaapi2.patch

File 20180829_working_vaapi2.patch, 66.5 KB (added by Peter Bennett, 7 years ago)

VAAPI hardware deinterlace is now working. If you already had installed a prior patch, please delete the VAAPI2 Normal Profile, exit setup and go in again and reselect it. This will re-add it with the new defaults.

  • mythtv/configure

    diff --git a/mythtv/configure b/mythtv/configure
    index 07c67f7ebb5..2f1e147ddac 100755
    a b Advanced options (experts only):  
    134134  --disable-vdpau          disable NVidia VDPAU hardware acceleration.
    135135  --disable-crystalhd      disable Broadcom CrystalHD hardware decoder support
    136136  --disable-vaapi          disable VAAPI hardware accelerated video decoding
     137  --disable-vaapi2         disable VAAPI@ hardware accelerated video decoding
    137138  --disable-openmax        disable OpenMAX hardware accelerated video decoding
    138139  --disable-dxva2          disable hardware accelerated decoding on windows
    139140  --disable-mediacodec     disable hardware accelerated decoding on android
    HWACCEL_AUTODETECT_LIBRARY_LIST="  
    14011402    crystalhd
    14021403    dxva2
    14031404    vaapi
     1405    vaapi2
    14041406    vda
    14051407    vdpau
    14061408"
    USING_LIST='  
    20402042    opengl
    20412043    opengles
    20422044    vaapi
     2045    vaapi2
    20432046    vdpau
    20442047    openmax
    20452048    mediacodec
    if enabled x11 ; then  
    72737276  echo "xv support                ${xv-no}"
    72747277  echo "VDPAU support             ${vdpau-no}"
    72757278  echo "VAAPI support             ${vaapi-no}"
     7279  echo "VAAPI2 support            ${vaapi2-no}"
    72767280  echo "CrystalHD support         ${crystalhd-no}"
    72777281  echo "OpenMAX support           ${openmax-no}"
    72787282  if enabled openmax ; then
  • mythtv/libs/libmythtv/avformatdecoder.cpp

    diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
    index 6b9cca5663a..fb75343c8fa 100644
    a b extern "C" {  
    7070#include <QtAndroidExtras>
    7171#endif
    7272
     73#ifdef USING_VAAPI2
     74#include "vaapi2context.h"
     75#endif
     76
    7377extern "C" {
    7478#include "libavutil/avutil.h"
    7579#include "libavutil/error.h"
    int get_avf_buffer_dxva2(struct AVCodecContext *c, AVFrame *pic, int flags);  
    182186#ifdef USING_VAAPI
    183187int  get_avf_buffer_vaapi(struct AVCodecContext *c, AVFrame *pic, int flags);
    184188#endif
     189#ifdef USING_VAAPI2
     190int  get_avf_buffer_vaapi2(struct AVCodecContext *c, AVFrame *pic, int flags);
     191#endif
    185192
    186193static int determinable_frame_size(struct AVCodecContext *avctx)
    187194{
    static int has_codec_parameters(AVStream *st)  
    250257
    251258static bool force_sw_decode(AVCodecContext *avctx)
    252259{
    253     switch (avctx->codec_id)
    254     {
    255         case AV_CODEC_ID_H264:
    256             switch (avctx->profile)
    257             {
    258                 case FF_PROFILE_H264_HIGH_10:
    259                 case FF_PROFILE_H264_HIGH_10_INTRA:
    260                 case FF_PROFILE_H264_HIGH_422:
    261                 case FF_PROFILE_H264_HIGH_422_INTRA:
    262                 case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
    263                 case FF_PROFILE_H264_HIGH_444_INTRA:
    264                 case FF_PROFILE_H264_CAVLC_444:
    265                     return true;
    266                 default:
    267                     break;
    268             }
    269             break;
    270         default:
    271             break;
    272     }
     260    // This is nonsense...
     261    // switch (avctx->codec_id)
     262    // {
     263    //     case AV_CODEC_ID_H264:
     264    //         switch (avctx->profile)
     265    //         {
     266    //             case FF_PROFILE_H264_HIGH_10:
     267    //             case FF_PROFILE_H264_HIGH_10_INTRA:
     268    //             case FF_PROFILE_H264_HIGH_422:
     269    //             case FF_PROFILE_H264_HIGH_422_INTRA:
     270    //             case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
     271    //             case FF_PROFILE_H264_HIGH_444_INTRA:
     272    //             case FF_PROFILE_H264_CAVLC_444:
     273    //                 return true;
     274    //             default:
     275    //                 break;
     276    //         }
     277    //         break;
     278    //     default:
     279    //         break;
     280    // }
    273281    return false;
    274282}
    275283
    void AvFormatDecoder::GetDecoders(render_opts &opts)  
    385393    opts.decoders->append("vaapi");
    386394    (*opts.equiv_decoders)["vaapi"].append("dummy");
    387395#endif
     396#ifdef USING_VAAPI2
     397    opts.decoders->append("vaapi2");
     398    (*opts.equiv_decoders)["vaapi2"].append("dummy");
     399#endif
    388400#ifdef USING_MEDIACODEC
    389401    opts.decoders->append("mediacodec");
    390402    (*opts.equiv_decoders)["mediacodec"].append("dummy");
    enum AVPixelFormat get_format_dxva2(struct AVCodecContext *avctx,  
    15201532}
    15211533#endif
    15221534
    1523 #ifdef USING_VAAPI
     1535
    15241536static bool IS_VAAPI_PIX_FMT(enum AVPixelFormat fmt)
    15251537{
    15261538    return fmt == AV_PIX_FMT_VAAPI_MOCO ||
    static bool IS_VAAPI_PIX_FMT(enum AVPixelFormat fmt)  
    15281540           fmt == AV_PIX_FMT_VAAPI_VLD;
    15291541}
    15301542
     1543#ifdef USING_VAAPI
     1544
    15311545// Declared separately to allow attribute
    15321546static enum AVPixelFormat get_format_vaapi(struct AVCodecContext *,
    15331547                                         const enum AVPixelFormat *) MUNUSED;
    enum AVPixelFormat get_format_vaapi(struct AVCodecContext *avctx,  
    15541568}
    15551569#endif
    15561570
     1571#ifdef USING_VAAPI2
     1572static enum AVPixelFormat get_format_vaapi2(struct AVCodecContext *avctx,
     1573                                           const enum AVPixelFormat *valid_fmts)
     1574{
     1575    enum AVPixelFormat ret = AV_PIX_FMT_NONE;
     1576    while (*valid_fmts != AV_PIX_FMT_NONE) {
     1577        if (IS_VAAPI_PIX_FMT(*valid_fmts))
     1578        {
     1579            ret = *valid_fmts;
     1580            avctx->pix_fmt = ret;
     1581            // Vaapi2Context::SetHwframeCtx(avctx, 20);
     1582            break;
     1583        }
     1584        valid_fmts++;
     1585    }
     1586
     1587    // AVBufferRef* dev_ctx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI);
     1588    // AVBufferRef* frame_ctx = av_hwframe_ctx_alloc(dev_ctx);
     1589    // avctx->hw_frames_ctx = frame_ctx;
     1590    // avctx->hwaccel_context =
     1591    return ret;
     1592}
     1593#endif
     1594
    15571595#ifdef USING_MEDIACODEC
    15581596static enum AVPixelFormat get_format_mediacodec(struct AVCodecContext *avctx,
    15591597                                           const enum AVPixelFormat *valid_fmts)
    void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc,  
    16341672    else
    16351673#endif
    16361674#ifdef USING_VAAPI
    1637     if (CODEC_IS_VAAPI(codec, enc))
     1675    if (CODEC_IS_VAAPI(codec, enc) && codec_is_vaapi(video_codec_id))
    16381676    {
    16391677        enc->get_buffer2     = get_avf_buffer_vaapi;
    16401678        enc->get_format      = get_format_vaapi;
    void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc,  
    16491687        enc->slice_flags     = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
    16501688    }
    16511689    else
     1690#endif
     1691#ifdef USING_VAAPI2
     1692    if (codec_is_vaapi2(video_codec_id))
     1693    {
     1694        enc->get_buffer2     = get_avf_buffer_vaapi2;
     1695        enc->get_format      = get_format_vaapi2;
     1696    }
     1697    else
    16521698#endif
    16531699    if (codec && codec->capabilities & AV_CODEC_CAP_DR1)
    16541700    {
    void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc,  
    16641710                .arg(ff_codec_id_string(enc->codec_id)));
    16651711    }
    16661712
     1713    MythCodecContext *mctx = gCodecMap->getMythCodecContext(stream, video_codec_id);
     1714    if (mctx)
     1715    {
     1716        mctx->setPlayer(m_parent);
     1717        int ret = mctx->HwDecoderInit(enc);
     1718        if (ret < 0)
     1719        {
     1720            char error[AV_ERROR_MAX_STRING_SIZE];
     1721            if (ret < 0)
     1722            {
     1723                LOG(VB_GENERAL, LOG_ERR, LOC +
     1724                    QString("HwDecoderInit unable to initialize hardware decoder: %1 (%2)")
     1725                    .arg(av_make_error_string(error, sizeof(error), ret))
     1726                    .arg(ret));
     1727                // force it to switch to software decoding
     1728                averror_count = SEQ_PKT_ERR_MAX + 1;
     1729                m_streams_changed = true;
     1730            }
     1731        }
     1732    }
     1733
    16671734    if (FlagIsSet(kDecodeLowRes)    || FlagIsSet(kDecodeSingleThreaded) ||
    16681735        FlagIsSet(kDecodeFewBlocks) || FlagIsSet(kDecodeNoLoopFilter)   ||
    16691736        FlagIsSet(kDecodeNoDecode))
    int AvFormatDecoder::ScanStreams(bool novideo)  
    25422609                        foundgpudecoder = true;
    25432610                    }
    25442611                }
     2612#endif // USING_MEDIACODEC
     2613#ifdef USING_VAAPI2
     2614                if (!foundgpudecoder)
     2615                {
     2616                    MythCodecID vaapi2_mcid;
     2617                    AVPixelFormat pix_fmt = AV_PIX_FMT_YUV420P;
     2618                    vaapi2_mcid = Vaapi2Context::GetBestSupportedCodec(
     2619                        &codec, dec, mpeg_version(enc->codec_id),
     2620                        pix_fmt);
     2621
     2622                    if (codec_is_vaapi2(vaapi2_mcid))
     2623                    {
     2624                        gCodecMap->freeCodecContext(ic->streams[selTrack]);
     2625                        enc = gCodecMap->getCodecContext(ic->streams[selTrack], codec);
     2626                        video_codec_id = vaapi2_mcid;
     2627                        foundgpudecoder = true;
     2628                    }
     2629                }
    25452630#endif // USING_MEDIACODEC
    25462631            }
    25472632            // default to mpeg2
    int AvFormatDecoder::ScanStreams(bool novideo)  
    25632648
    25642649            use_frame_timing = false;
    25652650            if (! private_dec
    2566                 && (codec_is_std(video_codec_id) || codec_is_mediacodec(video_codec_id)))
     2651                && (codec_is_std(video_codec_id)
     2652                    || codec_is_mediacodec(video_codec_id))
     2653                    || codec_is_vaapi2(video_codec_id))
    25672654                use_frame_timing = true;
    25682655
    25692656            if (FlagIsSet(kDecodeSingleThreaded))
    int get_avf_buffer_vaapi(struct AVCodecContext *c, AVFrame *pic, int /*flags*/)  
    30633150}
    30643151#endif
    30653152
     3153#ifdef USING_VAAPI2
     3154int get_avf_buffer_vaapi2(struct AVCodecContext *c, AVFrame *pic, int flags)
     3155{
     3156    AvFormatDecoder *nd = (AvFormatDecoder *)(c->opaque);
     3157
     3158    nd->directrendering = false;
     3159    return avcodec_default_get_buffer2(c, pic, flags);
     3160}
     3161#endif
     3162
    30663163void AvFormatDecoder::DecodeDTVCC(const uint8_t *buf, uint len, bool scte)
    30673164{
    30683165    if (!len)
    bool AvFormatDecoder::ProcessVideoPacket(AVStream *curstream, AVPacket *pkt)  
    35993696    int ret = 0, gotpicture = 0;
    36003697    int64_t pts = 0;
    36013698    AVCodecContext *context = gCodecMap->getCodecContext(curstream);
     3699    MythCodecContext *mctx = gCodecMap->getMythCodecContext(curstream);
     3700    mctx->setPlayer(m_parent);
    36023701    MythAVFrame mpa_pic;
    36033702    if (!mpa_pic)
    36043703    {
    bool AvFormatDecoder::ProcessVideoPacket(AVStream *curstream, AVPacket *pkt)  
    36393738            //  Also now that it always consumes a whole buffer some code
    36403739            //  in the caller may be able to be optimized.
    36413740            ret = 0;
    3642             ret = avcodec_receive_frame(context, mpa_pic);
     3741            // ret = avcodec_receive_frame(context, mpa_pic);
     3742            // FilteredReceiveFrame will apply any codec-dependent filtering
     3743            ret = mctx->FilteredReceiveFrame(context, mpa_pic);
    36433744
    36443745            if (ret == 0)
    36453746                gotpicture = 1;
    bool AvFormatDecoder::ProcessVideoPacket(AVStream *curstream, AVPacket *pkt)  
    36803781                    QString("video avcodec_send_packet error: %1 (%2) gotpicture:%3")
    36813782                    .arg(av_make_error_string(error, sizeof(error), ret2))
    36823783                    .arg(ret2).arg(gotpicture));
    3683             if (ret == AVERROR_INVALIDDATA || ret2 == AVERROR_INVALIDDATA)
     3784            if (++averror_count > SEQ_PKT_ERR_MAX)
    36843785            {
    3685                 if (++averror_count > SEQ_PKT_ERR_MAX)
    3686                 {
    3687                     // If erroring on GPU assist, try switching to software decode
    3688                     if (codec_is_std(video_codec_id))
    3689                         m_parent->SetErrored(QObject::tr("Video Decode Error"));
    3690                     else
    3691                         m_streams_changed = true;
    3692                 }
     3786                // If erroring on GPU assist, try switching to software decode
     3787                if (codec_is_std(video_codec_id))
     3788                    m_parent->SetErrored(QObject::tr("Video Decode Error"));
     3789                else
     3790                    m_streams_changed = true;
    36933791            }
    36943792            if (ret == AVERROR_EXTERNAL || ret2 == AVERROR_EXTERNAL)
    36953793                m_streams_changed = true;
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic)  
    38393937
    38403938    VideoFrame *picframe = (VideoFrame *)(mpa_pic->opaque);
    38413939
     3940    // if (IS_VAAPI_PIX_FMT((AVPixelFormat)mpa_pic->format))
     3941    //     directrendering=false;
     3942
    38423943    if (FlagIsSet(kDecodeNoDecode))
    38433944    {
    38443945        // Do nothing, we just want the pts, captions, subtites, etc.
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic)  
    38473948    }
    38483949    else if (!directrendering)
    38493950    {
     3951        AVFrame *tmp_frame = NULL;
     3952        AVFrame *use_frame = NULL;
     3953
     3954        if (IS_VAAPI_PIX_FMT((AVPixelFormat)mpa_pic->format))
     3955        {
     3956            int ret = 0;
     3957            tmp_frame = av_frame_alloc();
     3958            use_frame = tmp_frame;
     3959            /* retrieve data from GPU to CPU */
     3960            if ((ret = av_hwframe_transfer_data(use_frame, mpa_pic, 0)) < 0) {
     3961                LOG(VB_GENERAL, LOG_ERR, LOC
     3962                    + QString("Error %1 transferring the data to system memory")
     3963                        .arg(ret));
     3964                av_frame_free(&use_frame);
     3965                return false;
     3966            }
     3967        }
     3968        else
     3969            use_frame = mpa_pic;
     3970
    38503971        AVFrame tmppicture;
    38513972
    38523973        VideoFrame *xf = picframe;
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic)  
    38543975
    38553976        unsigned char *buf = picframe->buf;
    38563977        av_image_fill_arrays(tmppicture.data, tmppicture.linesize,
    3857             buf, AV_PIX_FMT_YUV420P, context->width,
    3858                        context->height, IMAGE_ALIGN);
     3978            buf, AV_PIX_FMT_YUV420P, use_frame->width,
     3979                       use_frame->height, IMAGE_ALIGN);
    38593980        tmppicture.data[0] = buf + picframe->offsets[0];
    38603981        tmppicture.data[1] = buf + picframe->offsets[1];
    38613982        tmppicture.data[2] = buf + picframe->offsets[2];
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic)  
    38643985        tmppicture.linesize[2] = picframe->pitches[2];
    38653986
    38663987        QSize dim = get_video_dim(*context);
    3867         sws_ctx = sws_getCachedContext(sws_ctx, context->width,
    3868                                        context->height, context->pix_fmt,
    3869                                        context->width, context->height,
     3988        sws_ctx = sws_getCachedContext(sws_ctx, use_frame->width,
     3989                                       use_frame->height, (AVPixelFormat)use_frame->format,
     3990                                       use_frame->width, use_frame->height,
    38703991                                       AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR,
    38713992                                       NULL, NULL, NULL);
    38723993        if (!sws_ctx)
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic)  
    38743995            LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate sws context");
    38753996            return false;
    38763997        }
    3877         sws_scale(sws_ctx, mpa_pic->data, mpa_pic->linesize, 0, dim.height(),
     3998        sws_scale(sws_ctx, use_frame->data, use_frame->linesize, 0, dim.height(),
    38783999                  tmppicture.data, tmppicture.linesize);
    38794000
    38804001        if (xf)
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic)  
    38874008            xf->aspect = current_aspect;
    38884009            m_parent->DiscardVideoFrame(xf);
    38894010        }
     4011        if (tmp_frame)
     4012            av_frame_free(&tmp_frame);
    38904013    }
    38914014    else if (!picframe)
    38924015    {
  • mythtv/libs/libmythtv/avformatdecoder.h

    diff --git a/mythtv/libs/libmythtv/avformatdecoder.h b/mythtv/libs/libmythtv/avformatdecoder.h
    index e4dded21576..1ea3785b7db 100644
    a b class AvFormatDecoder : public DecoderBase  
    206206
    207207    friend int get_avf_buffer(struct AVCodecContext *c, AVFrame *pic,
    208208                              int flags);
     209    friend int get_avf_buffer_vaapi2(struct AVCodecContext *c, AVFrame *pic,
     210                              int flags);
    209211    friend void release_avf_buffer(void *opaque, uint8_t *data);
    210212
    211213    friend int open_avf(URLContext *h, const char *filename, int flags);
  • mythtv/libs/libmythtv/libmythtv.pro

    diff --git a/mythtv/libs/libmythtv/libmythtv.pro b/mythtv/libs/libmythtv/libmythtv.pro
    index 939ca20984b..8ffe3b82665 100644
    a b using_frontend {  
    366366    HEADERS += decoderbase.h
    367367    HEADERS += nuppeldecoder.h          avformatdecoder.h
    368368    HEADERS += privatedecoder.h
     369    HEADERS += mythcodeccontext.h
    369370    SOURCES += decoderbase.cpp
    370371    SOURCES += nuppeldecoder.cpp        avformatdecoder.cpp
    371372    SOURCES += privatedecoder.cpp
     373    SOURCES += mythcodeccontext.cpp
    372374
    373375    using_crystalhd {
    374376        DEFINES += USING_CRYSTALHD
    using_frontend {  
    505507        using_opengl_video:DEFINES += USING_GLVAAPI
    506508    }
    507509
     510    using_vaapi2 {
     511        DEFINES += USING_VAAPI2
     512        HEADERS += vaapi2context.h
     513        SOURCES += vaapi2context.cpp
     514    }
     515
    508516    using_mediacodec {
    509517        DEFINES += USING_MEDIACODEC
    510518        HEADERS += mediacodeccontext.h
  • mythtv/libs/libmythtv/mythavutil.cpp

    diff --git a/mythtv/libs/libmythtv/mythavutil.cpp b/mythtv/libs/libmythtv/mythavutil.cpp
    index aabf0200e90..ceda07ed261 100644
    a b  
    1010#include "mythavutil.h"
    1111#include "mythcorecontext.h"
    1212#include "mythconfig.h"
     13#include "vaapi2context.h"
    1314extern "C" {
    1415#include "libswscale/swscale.h"
    1516#include "libavfilter/avfilter.h"
    AVCodecContext *MythCodecMap::getCodecContext(const AVStream *stream,  
    393394    const AVCodec *pCodec, bool nullCodec)
    394395{
    395396    QMutexLocker lock(&mapLock);
    396     AVCodecContext *avctx = streamMap.value(stream, NULL);
     397    AVCodecContext *avctx = streamAvMap.value(stream, NULL);
    397398    if (!avctx)
    398399    {
    399400        if (stream == NULL || stream->codecpar == NULL)
    AVCodecContext *MythCodecMap::getCodecContext(const AVStream *stream,  
    417418        if (avctx)
    418419        {
    419420            av_codec_set_pkt_timebase(avctx, stream->time_base);
    420             streamMap.insert(stream, avctx);
     421            streamAvMap.insert(stream, avctx);
    421422        }
    422423    }
    423424    return avctx;
    424425}
    425426
     427MythCodecContext *MythCodecMap::getMythCodecContext(AVStream* stream, MythCodecID codec)
     428{
     429    QMutexLocker lock(&mapLock);
     430    MythCodecContext *mctx = streamMythMap.value(stream, NULL);
     431    if (!mctx && codec)
     432    {
     433        if (codec_is_vaapi2(codec))
     434            mctx = new Vaapi2Context(stream);
     435        if (!mctx)
     436            mctx = new MythCodecContext(stream);
     437        streamMythMap.insert(stream, mctx);
     438    }
     439    return mctx;
     440}
     441
    426442AVCodecContext *MythCodecMap::hasCodecContext(const AVStream *stream)
    427443{
    428     return streamMap.value(stream, NULL);
     444    return streamAvMap.value(stream, NULL);
    429445}
    430446
    431447void MythCodecMap::freeCodecContext(const AVStream *stream)
    432448{
    433449    QMutexLocker lock(&mapLock);
    434     AVCodecContext *avctx = streamMap.take(stream);
     450    AVCodecContext *avctx = streamAvMap.take(stream);
    435451    if (avctx)
    436452        avcodec_free_context(&avctx);
     453    MythCodecContext *mctx = streamMythMap.take(stream);
     454    if (mctx)
     455        delete mctx;
    437456}
    438457
    439458void MythCodecMap::freeAllCodecContexts()
    440459{
    441460    QMutexLocker lock(&mapLock);
    442     QMap<const AVStream*, AVCodecContext*>::iterator i = streamMap.begin();
    443     while (i != streamMap.end()) {
     461    QMap<const AVStream*, AVCodecContext*>::iterator i = streamAvMap.begin();
     462    while (i != streamAvMap.end()) {
    444463        const AVStream *stream = i.key();
    445464        ++i;
    446465        freeCodecContext(stream);
  • mythtv/libs/libmythtv/mythavutil.h

    diff --git a/mythtv/libs/libmythtv/mythavutil.h b/mythtv/libs/libmythtv/mythavutil.h
    index 1357fe2c54c..b14ad3ddd2e 100644
    a b  
    1111
    1212#include "mythtvexp.h" // for MUNUSED
    1313#include "mythframe.h"
     14#include "mythcodecid.h"
     15
    1416extern "C" {
    1517#include "libavcodec/avcodec.h"
    1618}
    private:  
    8688 * This is a singeton class - only 1 instance gets created.
    8789 */
    8890
     91class MythCodecContext;
     92
    8993class MTV_PUBLIC MythCodecMap
    9094{
    9195  public:
    class MTV_PUBLIC MythCodecMap  
    9599    AVCodecContext *getCodecContext(const AVStream*,
    96100        const AVCodec *pCodec = NULL, bool nullCodec = false);
    97101    AVCodecContext *hasCodecContext(const AVStream*);
     102    MythCodecContext *getMythCodecContext(AVStream*,
     103        const MythCodecID codec = kCodec_NONE);
    98104    void freeCodecContext(const AVStream*);
    99105    void freeAllCodecContexts();
    100106  protected:
    101     QMap<const AVStream*, AVCodecContext*> streamMap;
     107    QMap<const AVStream*, AVCodecContext*> streamAvMap;
     108    QMap<const AVStream*, MythCodecContext*> streamMythMap;
    102109    QMutex mapLock;
    103110};
    104111
  • new file mythtv/libs/libmythtv/mythcodeccontext.cpp

    diff --git a/mythtv/libs/libmythtv/mythcodeccontext.cpp b/mythtv/libs/libmythtv/mythcodeccontext.cpp
    new file mode 100644
    index 00000000000..1038c81f08a
    - +  
     1//////////////////////////////////////////////////////////////////////////////
     2// Copyright (c) 2017 MythTV Developers <mythtv-dev@mythtv.org>
     3//
     4// This is part of MythTV (https://www.mythtv.org)
     5//
     6// This program is free software; you can redistribute it and/or modify
     7// it under the terms of the GNU General Public License as published by
     8// the Free Software Foundation; either version 2 of the License, or
     9// (at your option) any later version.
     10//
     11// This program is distributed in the hope that it will be useful,
     12// but WITHOUT ANY WARRANTY; without even the implied warranty of
     13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14// GNU General Public License for more details.
     15//
     16// You should have received a copy of the GNU General Public License
     17// along with this program; if not, write to the Free Software
     18// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
     19//
     20// You should have received a copy of the GNU General Public License
     21// along with this program.  If not, see <http://www.gnu.org/licenses/>.
     22//
     23//////////////////////////////////////////////////////////////////////////////
     24
     25#include "mythcorecontext.h"
     26#include "mythlogging.h"
     27#include "mythcodeccontext.h"
     28#include "videooutbase.h"
     29#include "mythplayer.h"
     30
     31extern "C" {
     32    #include "libavutil/pixfmt.h"
     33    #include "libavutil/hwcontext.h"
     34    #include "libavcodec/avcodec.h"
     35    #include "libavfilter/avfilter.h"
     36    #include "libavfilter/buffersink.h"
     37    #include "libavfilter/buffersrc.h"
     38    #include "libavformat/avformat.h"
     39    #include "libavutil/opt.h"
     40    #include "libavutil/buffer.h"
     41}
     42
     43#define LOC QString("MythCodecContext: ")
     44
     45MythCodecContext::MythCodecContext(AVStream* initStream) :
     46    stream(initStream),
     47    buffersink_ctx(NULL),
     48    buffersrc_ctx(NULL),
     49    filter_graph(NULL),
     50    filtersInitialized(false),
     51    hw_frames_ctx(0),
     52    player(NULL),
     53    ptsUsed(0)
     54{
     55    priorPts[0] = 0;
     56    priorPts[1] = 0;
     57}
     58
     59MythCodecContext::~MythCodecContext()
     60{
     61    CloseFilters();
     62}
     63
     64QStringList MythCodecContext::MythCodecContext::GetDeinterlacers(QString decodername)
     65{
     66    QStringList ret;
     67#ifdef USING_VAAPI2
     68    if (decodername == "vaapi2")
     69    {
     70        ret.append("vaapi2default");
     71        ret.append("vaapi2bob");
     72        ret.append("vaapi2weave");
     73        ret.append("vaapi2motion_adaptive");
     74        ret.append("vaapi2motion_compensated");
     75        ret.append("vaapi2doubleratedefault");
     76        ret.append("vaapi2doubleratebob");
     77        ret.append("vaapi2doublerateweave");
     78        ret.append("vaapi2doubleratemotion_adaptive");
     79        ret.append("vaapi2doubleratemotion_compensated");
     80
     81/*
     82    "mode", "Deinterlacing mode",
     83        "default", "Use the highest-numbered (and therefore possibly most advanced) deinterlacing algorithm",
     84        "bob", "Use the bob deinterlacing algorithm",
     85        "weave", "Use the weave deinterlacing algorithm",
     86        "motion_adaptive", "Use the motion adaptive deinterlacing algorithm",
     87        "motion_compensated", "Use the motion compensated deinterlacing algorithm",
     88
     89    "rate", "Generate output at frame rate or field rate",
     90        "frame", "Output at frame rate (one frame of output for each field-pair)",
     91        "field", "Output at field rate (one frame of output for each field)",
     92
     93    "auto", "Only deinterlace fields, passing frames through unchanged",
     94        1 = enabled
     95        0 = disabled
     96*/
     97
     98    }
     99#endif
     100    return ret;
     101}
     102
     103
     104// Currently this will only set up the filter after an interlaced frame.
     105// If we need other filters apart from deinterlace filters we will
     106// need to make a change here.
     107
     108int MythCodecContext::FilteredReceiveFrame(AVCodecContext *ctx, AVFrame *frame)
     109{
     110    int ret = 0;
     111
     112    while (1)
     113    {
     114        if (filter_graph)
     115        {
     116            ret = av_buffersink_get_frame(buffersink_ctx, frame);
     117            if  (ret >= 0)
     118            {
     119                if (priorPts[0] && ptsUsed == priorPts[1])
     120                {
     121                    frame->pts = priorPts[1] + (priorPts[1] - priorPts[0])/2;
     122                    frame->scte_cc_len = 0;
     123                    frame->atsc_cc_len = 0;
     124                    av_frame_remove_side_data(frame, AV_FRAME_DATA_A53_CC);
     125                }
     126                else
     127                {
     128                    frame->pts = priorPts[1];
     129                    ptsUsed = priorPts[1];
     130                }
     131// {const char *msg = QString("filter pts=%1 interlaced=%2")
     132//     .arg(frame->pts).arg(frame->interlaced_frame).toLocal8Bit();
     133// fprintf(stderr,"%s\n", msg);}
     134            }
     135            if  (ret != AVERROR(EAGAIN))
     136                break;
     137        }
     138
     139        // EAGAIN or no filter graph
     140        ret = avcodec_receive_frame(ctx, frame);
     141        if (ret < 0)
     142            break;
     143// {const char *msg = QString("codec pts=%1 interlaced=%2")
     144//     .arg(frame->pts).arg(frame->interlaced_frame).toLocal8Bit();
     145// fprintf(stderr,"%s\n", msg);}
     146        priorPts[0]=priorPts[1];
     147        priorPts[1]=frame->pts;
     148        if (frame->interlaced_frame || filter_graph)
     149        {
     150            if (!filtersInitialized
     151              || width != frame->width
     152              || height != frame->height)
     153            {
     154                // bypass any frame of unknown format
     155                if (frame->format < 0)
     156                    break;
     157                ret = InitFilters(ctx, frame);
     158                filtersInitialized = true;
     159                if (ret < 0)
     160                {
     161                    LOG(VB_GENERAL, LOG_ERR, LOC + "InitFilters failed - continue without filters");
     162                    break;
     163                }
     164            }
     165            if (filter_graph)
     166            {
     167                ret = av_buffersrc_add_frame(buffersrc_ctx, frame);
     168                if (ret < 0)
     169                    break;
     170            }
     171            else
     172                break;
     173        }
     174        else
     175            break;
     176    }
     177
     178    return ret;
     179}
     180
     181
     182int MythCodecContext::InitFilters(AVCodecContext *ctx, AVFrame *frame)
     183{
     184    char args[512];
     185    int ret = 0;
     186    CloseFilters();
     187    width = frame->width;
     188    height = frame->height;
     189    if (!player)
     190        return -1;
     191    VideoOutput *vo = player->GetVideoOutput();
     192    VideoDisplayProfile *vdisp_profile = vo->GetProfile();
     193    QString filtername = vdisp_profile->GetFilteredDeint(QString());
     194    QString filters = GetDeinterlaceFilter(filtername);
     195
     196    if (filters.isEmpty())
     197        return ret;
     198
     199    const AVFilter *buffersrc  = avfilter_get_by_name("buffer");
     200    const AVFilter *buffersink = avfilter_get_by_name("buffersink");
     201    AVFilterInOut *outputs = avfilter_inout_alloc();
     202    AVFilterInOut *inputs  = avfilter_inout_alloc();
     203    AVRational time_base = stream->time_base;
     204    // enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE };
     205    // enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_VAAPI_VLD, AV_PIX_FMT_NONE };
     206    AVBufferSrcParameters* params = NULL;
     207
     208    filter_graph = avfilter_graph_alloc();
     209    if (!outputs || !inputs || !filter_graph)
     210    {
     211        ret = AVERROR(ENOMEM);
     212        goto end;
     213    }
     214
     215    /* buffer video source: the decoded frames from the decoder will be inserted here. */
     216    snprintf(args, sizeof(args),
     217            "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
     218            frame->width, frame->height, frame->format, // ctx->pix_fmt,
     219            time_base.num, time_base.den,
     220            ctx->sample_aspect_ratio.num, ctx->sample_aspect_ratio.den);
     221
     222    // isInterlaced = frame->interlaced_frame;
     223
     224    ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
     225                                       args, NULL, filter_graph);
     226    if (ret < 0)
     227    {
     228        LOG(VB_GENERAL, LOG_ERR, LOC + "avfilter_graph_create_filter failed for buffer source");
     229        goto end;
     230    }
     231
     232    params = av_buffersrc_parameters_alloc();
     233    // params->format = frame->format;
     234    // params->time_base.num = stream->time_base.num;
     235    // params->time_base.den = stream->time_base.den;
     236    // params->width = frame->width;
     237    // params->height = frame->height;
     238    // params->sample_aspect_ratio.num = ctx->sample_aspect_ratio.num;
     239    // params->sample_aspect_ratio.den = ctx->sample_aspect_ratio.den;
     240    if (hw_frames_ctx)
     241        av_buffer_unref(&hw_frames_ctx);
     242    hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx);
     243    params->hw_frames_ctx = hw_frames_ctx;
     244
     245    ret = av_buffersrc_parameters_set(buffersrc_ctx, params);
     246
     247    if (ret < 0)
     248    {
     249        LOG(VB_GENERAL, LOG_ERR, LOC + "av_buffersrc_parameters_set failed");
     250        goto end;
     251    }
     252
     253    av_freep(&params);
     254
     255    /* buffer video sink: to terminate the filter chain. */
     256    ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
     257                                       NULL, NULL, filter_graph);
     258    if (ret < 0)
     259    {
     260        LOG(VB_GENERAL, LOG_ERR, LOC + "avfilter_graph_create_filter failed for buffer sink");
     261        goto end;
     262    }
     263
     264    // ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts,
     265    //                           AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
     266    // if (ret < 0)
     267    // {
     268    //     LOG(VB_GENERAL, LOG_ERR, LOC + "av_opt_set_int_list pix_fmts failed");
     269    //     goto end;
     270    // }
     271
     272    /*
     273     * Set the endpoints for the filter graph. The filter_graph will
     274     * be linked to the graph described by filters_descr.
     275     */
     276
     277    /*
     278     * The buffer source output must be connected to the input pad of
     279     * the first filter described by filters_descr; since the first
     280     * filter input label is not specified, it is set to "in" by
     281     * default.
     282     */
     283    outputs->name       = av_strdup("in");
     284    outputs->filter_ctx = buffersrc_ctx;
     285    outputs->pad_idx    = 0;
     286    outputs->next       = NULL;
     287
     288    /*
     289     * The buffer sink input must be connected to the output pad of
     290     * the last filter described by filters_descr; since the last
     291     * filter output label is not specified, it is set to "out" by
     292     * default.
     293     */
     294    inputs->name       = av_strdup("out");
     295    inputs->filter_ctx = buffersink_ctx;
     296    inputs->pad_idx    = 0;
     297    inputs->next       = NULL;
     298
     299    if ((ret = avfilter_graph_parse_ptr(filter_graph, filters.toLocal8Bit(),
     300                                    &inputs, &outputs,0)) < 0)
     301    {
     302        LOG(VB_GENERAL, LOG_ERR, LOC
     303            + QString("avfilter_graph_parse_ptr failed for %1").arg(filters));
     304        goto end;
     305    }
     306
     307    if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
     308    {
     309        LOG(VB_GENERAL, LOG_ERR, LOC
     310            + QString("avfilter_graph_config failed"));
     311        goto end;
     312    }
     313
     314    // send the first packet to the filters
     315    // frame->pts = frame->best_effort_timestamp;
     316    // ret = av_buffersrc_add_frame(buffersrc_ctx, frame);
     317    // av_frame_unref(frame);
     318
     319    // if (ret < 0)
     320    // {
     321    //     LOG(VB_GENERAL, LOG_ERR, LOC
     322    //         + QString("av_buffersrc_add_frame first time failed"));
     323    //     goto end;
     324    // }
     325    LOG(VB_PLAYBACK, LOG_INFO, LOC +
     326        QString("Using hardware decoder based deinterlace filter <%1>.")
     327            .arg(filters));
     328end:
     329    if (ret < 0)
     330    {
     331        avfilter_graph_free(&filter_graph);
     332        filter_graph = NULL;
     333    }
     334    avfilter_inout_free(&inputs);
     335    avfilter_inout_free(&outputs);
     336
     337    return ret;
     338}
     339
     340void MythCodecContext::CloseFilters()
     341{
     342    avfilter_graph_free(&filter_graph);
     343    filter_graph = NULL;
     344    buffersink_ctx = NULL;
     345    buffersrc_ctx = NULL;
     346    filtersInitialized = false;
     347    ptsUsed = 0;
     348    priorPts[0] = 0;
     349    priorPts[1] = 0;
     350    // isInterlaced = 0;
     351    width = 0;
     352    height = 0;
     353
     354    if (hw_frames_ctx)
     355        av_buffer_unref(&hw_frames_ctx);
     356}
     357 No newline at end of file
  • new file mythtv/libs/libmythtv/mythcodeccontext.h

    diff --git a/mythtv/libs/libmythtv/mythcodeccontext.h b/mythtv/libs/libmythtv/mythcodeccontext.h
    new file mode 100644
    index 00000000000..95cb1858d6d
    - +  
     1//////////////////////////////////////////////////////////////////////////////
     2// Copyright (c) 2017 MythTV Developers <mythtv-dev@mythtv.org>
     3//
     4// This is part of MythTV (https://www.mythtv.org)
     5//
     6// This program is free software; you can redistribute it and/or modify
     7// it under the terms of the GNU General Public License as published by
     8// the Free Software Foundation; either version 2 of the License, or
     9// (at your option) any later version.
     10//
     11// This program is distributed in the hope that it will be useful,
     12// but WITHOUT ANY WARRANTY; without even the implied warranty of
     13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14// GNU General Public License for more details.
     15//
     16// You should have received a copy of the GNU General Public License
     17// along with this program; if not, write to the Free Software
     18// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
     19//
     20// You should have received a copy of the GNU General Public License
     21// along with this program.  If not, see <http://www.gnu.org/licenses/>.
     22//
     23//////////////////////////////////////////////////////////////////////////////
     24
     25
     26#ifndef MYTHCODECONTEXT_H
     27#define MYTHCODECCONTEXT_H
     28
     29struct AVCodecContext;
     30struct AVFrame;
     31struct AVStream;
     32struct AVFilterContext;
     33struct AVFilterGraph;
     34struct AVBufferRef;
     35class MythPlayer;
     36
     37#include "mythtvexp.h"
     38
     39class MTV_PUBLIC MythCodecContext
     40{
     41  public:
     42    MythCodecContext(AVStream* initStream);
     43    virtual ~MythCodecContext();
     44    virtual int HwDecoderInit(AVCodecContext * /*ctx*/) { return 0; }
     45    virtual int FilteredReceiveFrame(AVCodecContext *ctx, AVFrame *frame);
     46    int InitFilters(AVCodecContext *ctx, AVFrame *frame);
     47    void CloseFilters();
     48    static QStringList GetDeinterlacers(QString decodername);
     49    virtual QString GetDeinterlaceFilter(QString /*filtername*/) { return QString(); }
     50    void setPlayer(MythPlayer *tPlayer) { player = tPlayer; }
     51  protected:
     52    AVStream* stream;
     53    AVFilterContext *buffersink_ctx;
     54    AVFilterContext *buffersrc_ctx;
     55    AVFilterGraph *filter_graph;
     56    bool filtersInitialized;
     57    AVBufferRef *hw_frames_ctx;
     58    MythPlayer *player;
     59    int64_t priorPts[2];
     60    int64_t ptsUsed;
     61    // bool isInterlaced;
     62    int width;
     63    int height;
     64};
     65
     66#endif // MYTHCODECCONTEXT_H
     67 No newline at end of file
  • mythtv/libs/libmythtv/mythcodecid.cpp

    diff --git a/mythtv/libs/libmythtv/mythcodecid.cpp b/mythtv/libs/libmythtv/mythcodecid.cpp
    index b2023512b5f..cff4ba03585 100644
    a b QString toString(MythCodecID codecid)  
    123123        case kCodec_HEVC_MEDIACODEC:
    124124            return "HEVC MEDIACODEC";
    125125
     126        case kCodec_MPEG1_VAAPI2:
     127            return "MPEG1 VAAPI2";
     128        case kCodec_MPEG2_VAAPI2:
     129            return "MPEG2 VAAPI2";
     130        case kCodec_H263_VAAPI2:
     131            return "H.263 VAAPI2";
     132        case kCodec_MPEG4_VAAPI2:
     133            return "MPEG4 VAAPI2";
     134        case kCodec_H264_VAAPI2:
     135            return "H.264 VAAPI2";
     136        case kCodec_VC1_VAAPI2:
     137            return "VC1 VAAPI2";
     138        case kCodec_WMV3_VAAPI2:
     139            return "WMV3 VAAPI2";
     140        case kCodec_VP8_VAAPI2:
     141            return "VP8 VAAPI2";
     142        case kCodec_VP9_VAAPI2:
     143            return "VP9 VAAPI2";
     144        case kCodec_HEVC_VAAPI2:
     145            return "HEVC VAAPI2";
     146
    126147        default:
    127148            break;
    128149    }
    int myth2av_codecid(MythCodecID codec_id, bool &vdpau)  
    305326            ret = AV_CODEC_ID_HEVC;
    306327            break;
    307328
     329        case kCodec_MPEG1_VAAPI2:
     330            ret = AV_CODEC_ID_MPEG1VIDEO;
     331            break;
     332        case kCodec_MPEG2_VAAPI2:
     333            ret = AV_CODEC_ID_MPEG2VIDEO;
     334            break;
     335        case kCodec_H263_VAAPI2:
     336            ret = AV_CODEC_ID_H263;
     337            break;
     338        case kCodec_MPEG4_VAAPI2:
     339            ret = AV_CODEC_ID_MPEG4;
     340            break;
     341        case kCodec_H264_VAAPI2:
     342            ret = AV_CODEC_ID_H264;
     343            break;
     344        case kCodec_VC1_VAAPI2:
     345            ret = AV_CODEC_ID_VC1;
     346            break;
     347        case kCodec_WMV3_VAAPI2:
     348            ret = AV_CODEC_ID_WMV3;
     349            break;
     350        case kCodec_VP8_VAAPI2:
     351            ret = AV_CODEC_ID_VP8;
     352            break;
     353        case kCodec_VP9_VAAPI2:
     354            ret = AV_CODEC_ID_VP9;
     355            break;
     356        case kCodec_HEVC_VAAPI2:
     357            ret = AV_CODEC_ID_HEVC;
     358            break;
     359
    308360        default:
    309361            LOG(VB_GENERAL, LOG_ERR,
    310362                QString("Error: MythCodecID %1 has not been "
    QString get_encoding_type(MythCodecID codecid)  
    356408        case kCodec_MPEG1_VAAPI:
    357409        case kCodec_MPEG1_DXVA2:
    358410        case kCodec_MPEG1_MEDIACODEC:
     411        case kCodec_MPEG1_VAAPI2:
    359412        case kCodec_MPEG2:
    360413        case kCodec_MPEG2_VDPAU:
    361414        case kCodec_MPEG2_VAAPI:
    362415        case kCodec_MPEG2_DXVA2:
    363416        case kCodec_MPEG2_MEDIACODEC:
     417        case kCodec_MPEG2_VAAPI2:
    364418            return "MPEG-2";
    365419
    366420        case kCodec_H263:
    QString get_encoding_type(MythCodecID codecid)  
    368422        case kCodec_H263_VAAPI:
    369423        case kCodec_H263_DXVA2:
    370424        case kCodec_H263_MEDIACODEC:
     425        case kCodec_H263_VAAPI2:
    371426            return "H.263";
    372427
    373428        case kCodec_NUV_MPEG4:
    QString get_encoding_type(MythCodecID codecid)  
    376431        case kCodec_MPEG4_VAAPI:
    377432        case kCodec_MPEG4_DXVA2:
    378433        case kCodec_MPEG4_MEDIACODEC:
     434        case kCodec_MPEG4_VAAPI2:
    379435            return "MPEG-4";
    380436
    381437        case kCodec_H264:
    QString get_encoding_type(MythCodecID codecid)  
    383439        case kCodec_H264_VAAPI:
    384440        case kCodec_H264_DXVA2:
    385441        case kCodec_H264_MEDIACODEC:
     442        case kCodec_H264_VAAPI2:
    386443            return "H.264";
    387444
    388445        case kCodec_VC1:
    QString get_encoding_type(MythCodecID codecid)  
    390447        case kCodec_VC1_VAAPI:
    391448        case kCodec_VC1_DXVA2:
    392449        case kCodec_VC1_MEDIACODEC:
     450        case kCodec_VC1_VAAPI2:
    393451            return "VC-1";
    394452
    395453        case kCodec_WMV3:
    QString get_encoding_type(MythCodecID codecid)  
    397455        case kCodec_WMV3_VAAPI:
    398456        case kCodec_WMV3_DXVA2:
    399457        case kCodec_WMV3_MEDIACODEC:
     458        case kCodec_WMV3_VAAPI2:
    400459            return "WMV3";
    401460
    402461        case kCodec_VP8:
    QString get_encoding_type(MythCodecID codecid)  
    404463        case kCodec_VP8_VAAPI:
    405464        case kCodec_VP8_DXVA2:
    406465        case kCodec_VP8_MEDIACODEC:
     466        case kCodec_VP8_VAAPI2:
    407467            return "VP8";
    408468
    409469        case kCodec_VP9:
    QString get_encoding_type(MythCodecID codecid)  
    411471        case kCodec_VP9_VAAPI:
    412472        case kCodec_VP9_DXVA2:
    413473        case kCodec_VP9_MEDIACODEC:
     474        case kCodec_VP9_VAAPI2:
    414475            return "VP8";
    415476
    416477        case kCodec_HEVC:
    QString get_encoding_type(MythCodecID codecid)  
    418479        case kCodec_HEVC_VAAPI:
    419480        case kCodec_HEVC_DXVA2:
    420481        case kCodec_HEVC_MEDIACODEC:
     482        case kCodec_HEVC_VAAPI2:
    421483            return "HEVC";
    422484
    423485        case kCodec_NONE:
    QString get_encoding_type(MythCodecID codecid)  
    426488        case kCodec_VAAPI_END:
    427489        case kCodec_DXVA2_END:
    428490        case kCodec_MEDIACODEC_END:
     491        case kCodec_VAAPI2_END:
    429492            return QString();
    430493    }
    431494
    QString get_decoder_name(MythCodecID codec_id)  
    446509    if (codec_is_mediacodec(codec_id))
    447510        return "mediacodec";
    448511
     512    if (codec_is_vaapi2(codec_id))
     513        return "vaapi2";
     514
    449515    return "ffmpeg";
    450516}
  • mythtv/libs/libmythtv/mythcodecid.h

    diff --git a/mythtv/libs/libmythtv/mythcodecid.h b/mythtv/libs/libmythtv/mythcodecid.h
    index ce3620467d9..f1d225d4beb 100644
    a b typedef enum  
    9191
    9292    kCodec_MEDIACODEC_END,
    9393
     94    kCodec_VAAPI2_BEGIN = kCodec_MEDIACODEC_END,
     95
     96    kCodec_MPEG1_VAAPI2,
     97    kCodec_MPEG2_VAAPI2,
     98    kCodec_H263_VAAPI2,
     99    kCodec_MPEG4_VAAPI2,
     100    kCodec_H264_VAAPI2,
     101    kCodec_VC1_VAAPI2,
     102    kCodec_WMV3_VAAPI2,
     103    kCodec_VP8_VAAPI2,
     104    kCodec_VP9_VAAPI2,
     105    kCodec_HEVC_VAAPI2,
     106
     107    kCodec_VAAPI2_END,
     108
    94109} MythCodecID;
    95110
    96111// MythCodecID convenience functions
    typedef enum  
    113128                                (id == kCodec_VC1_DXVA2)))
    114129#define codec_is_mediacodec(id) ((id > kCodec_MEDIACODEC_BEGIN) &&     \
    115130                               (id < kCodec_MEDIACODEC_END))
     131#define codec_is_vaapi2(id)    ((id > kCodec_VAAPI2_BEGIN) &&     \
     132                               (id < kCodec_VAAPI2_END))
    116133
    117 #define codec_sw_copy(id) (codec_is_std(id) || codec_is_mediacodec(id))
     134#define codec_sw_copy(id) (codec_is_std(id) || codec_is_mediacodec(id) || codec_is_vaapi2(id))
    118135
    119136QString get_encoding_type(MythCodecID codecid);
    120137QString get_decoder_name(MythCodecID codec_id);
    int mpeg_version(int codec_id);  
    156173#define CODEC_IS_MEDIACODEC(codec) (0)
    157174#endif
    158175
    159 #define CODEC_IS_HWACCEL(codec, enc) (CODEC_IS_VDPAU(codec)      ||     \
    160                                       CODEC_IS_VAAPI(codec, enc) ||     \
    161                                       CODEC_IS_DXVA2(codec, enc) ||    \
    162                                       CODEC_IS_MEDIACODEC(codec))
    163 
    164176#endif // _MYTH_CODEC_ID_H_
  • mythtv/libs/libmythtv/mythplayer.cpp

    diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
    index e4e0bd83ead..369ab5d48f4 100644
    a b bool MythPlayer::PrebufferEnoughFrames(int min_buffers)  
    22472247                audio.Pause(false);
    22482248            }
    22492249        }
    2250         if ((waited_for > 500) && !videoOutput->EnoughFreeFrames())
     2250        if ((waited_for > 1800000 /*500*/) && !videoOutput->EnoughFreeFrames())
    22512251        {
    22522252            LOG(VB_GENERAL, LOG_NOTICE, LOC +
    22532253                "Timed out waiting for frames, and"
    bool MythPlayer::PrebufferEnoughFrames(int min_buffers)  
    22572257            // to recover from serious problems if frames get leaked.
    22582258            DiscardVideoFrames(true);
    22592259        }
    2260         if (waited_for > 30000) // 30 seconds for internet streamed media
     2260        if (waited_for > 1800000 /*30000*/) // 30 seconds for internet streamed media
    22612261        {
    22622262            LOG(VB_GENERAL, LOG_ERR, LOC +
    22632263                "Waited too long for decoder to fill video buffers. Exiting..");
  • new file mythtv/libs/libmythtv/vaapi2context.cpp

    diff --git a/mythtv/libs/libmythtv/vaapi2context.cpp b/mythtv/libs/libmythtv/vaapi2context.cpp
    new file mode 100644
    index 00000000000..21e9dec4cfe
    - +  
     1//////////////////////////////////////////////////////////////////////////////
     2// Copyright (c) 2017 MythTV Developers <mythtv-dev@mythtv.org>
     3//
     4// This is part of MythTV (https://www.mythtv.org)
     5//
     6// This program is free software; you can redistribute it and/or modify
     7// it under the terms of the GNU General Public License as published by
     8// the Free Software Foundation; either version 2 of the License, or
     9// (at your option) any later version.
     10//
     11// This program is distributed in the hope that it will be useful,
     12// but WITHOUT ANY WARRANTY; without even the implied warranty of
     13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14// GNU General Public License for more details.
     15//
     16// You should have received a copy of the GNU General Public License
     17// along with this program; if not, write to the Free Software
     18// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
     19//
     20// You should have received a copy of the GNU General Public License
     21// along with this program.  If not, see <http://www.gnu.org/licenses/>.
     22//
     23//////////////////////////////////////////////////////////////////////////////
     24
     25#include "mythcorecontext.h"
     26#include "mythlogging.h"
     27#include "vaapi2context.h"
     28#include "videooutbase.h"
     29#include "mythplayer.h"
     30
     31extern "C" {
     32    #include "libavutil/pixfmt.h"
     33    #include "libavutil/hwcontext.h"
     34    #include "libavcodec/avcodec.h"
     35}
     36
     37#define LOC QString("VAAPI2: ")
     38
     39Vaapi2Context::Vaapi2Context(AVStream* initStream) :
     40    MythCodecContext(initStream)
     41{
     42
     43}
     44
     45MythCodecID Vaapi2Context::GetBestSupportedCodec(
     46    AVCodec **ppCodec,
     47    const QString &decoder,
     48    uint stream_type,
     49    AVPixelFormat &pix_fmt)
     50{
     51    enum AVHWDeviceType type = AV_HWDEVICE_TYPE_VAAPI;
     52
     53    AVPixelFormat fmt = AV_PIX_FMT_NONE;
     54    if (decoder == "vaapi2")
     55    {
     56        for (int i = 0;; i++) {
     57            const AVCodecHWConfig *config = avcodec_get_hw_config(*ppCodec, i);
     58            if (!config) {
     59                LOG(VB_PLAYBACK, LOG_INFO, LOC +
     60                    QString("Decoder %1 does not support device type %2.")
     61                        .arg((*ppCodec)->name).arg(av_hwdevice_get_type_name(type)));
     62                break;
     63            }
     64            if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
     65                config->device_type == type) {
     66                fmt = config->pix_fmt;
     67                break;
     68            }
     69        }
     70    }
     71    if (fmt == AV_PIX_FMT_NONE)
     72        return (MythCodecID)(kCodec_MPEG1 + (stream_type - 1));
     73    else
     74    {
     75        LOG(VB_PLAYBACK, LOG_INFO, LOC +
     76            QString("Decoder %1 supports device type %2.")
     77                .arg((*ppCodec)->name).arg(av_hwdevice_get_type_name(type)));
     78        pix_fmt = fmt;
     79        return (MythCodecID)(kCodec_MPEG1_VAAPI2 + (stream_type - 1));
     80    }
     81}
     82
     83// const char *filter_descr = "scale=78:24,transpose=cclock";
     84/* other way:
     85   scale=78:24 [scl]; [scl] transpose=cclock // assumes "[in]" and "[out]" to be input output pads respectively
     86 */
     87
     88int Vaapi2Context::HwDecoderInit(AVCodecContext *ctx)
     89{
     90    int ret = 0;
     91    AVBufferRef *hw_device_ctx = NULL;
     92
     93    const char *device = NULL;
     94    QString vaapiDevice = gCoreContext->GetSetting("VAAPIDevice");
     95    if (!vaapiDevice.isEmpty())
     96    {
     97        device = vaapiDevice.toLocal8Bit().constData();
     98    }
     99
     100    ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI,
     101                                      device, NULL, 0);
     102    if (ret < 0)
     103    {
     104        char error[AV_ERROR_MAX_STRING_SIZE];
     105        LOG(VB_GENERAL, LOG_ERR, LOC +
     106            QString("av_hwdevice_ctx_create  Device = <%3> error: %1 (%2)")
     107            .arg(av_make_error_string(error, sizeof(error), ret))
     108            .arg(ret).arg(vaapiDevice));
     109    }
     110    else
     111    {
     112        ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
     113        av_buffer_unref(&hw_device_ctx);
     114    }
     115
     116    return ret;
     117}
     118
     119
     120QString Vaapi2Context::GetDeinterlaceFilter(QString filtername)
     121{
     122    // example filter - deinterlace_vaapi=mode=default:rate=frame:auto=1
     123    // example filtername - vaapi2doubleratemotion_compensated
     124    QString ret;
     125    QString rate="frame";
     126    if (!filtername.startsWith("vaapi2"))
     127        return ret;
     128    filtername.remove(0,6); //remove "vaapi2"
     129    if (filtername.startsWith("doublerate"))
     130    {
     131        rate="field";
     132        filtername.remove(0,10);  // remove "doublerate"
     133    }
     134    ret=QString("deinterlace_vaapi=mode=%1:rate=%2:auto=1")
     135        .arg(filtername).arg(rate);
     136
     137    return ret;
     138}
     139
     140
     141
     142// If we find that it needs more buffers than the default
     143// we can uncomment this and call it from get_format_vaapi2
     144// int Vaapi2Context::SetHwframeCtx(AVCodecContext *ctx, int poolsize)
     145// {
     146//     AVBufferRef *hw_frames_ref;
     147//     AVHWFramesContext *frames_ctx = NULL;
     148//     int err = 0;
     149
     150//     if (!(hw_frames_ref = av_hwframe_ctx_alloc(ctx->hw_device_ctx))) {
     151//         fprintf(stderr, "Failed to create VAAPI frame context.\n");
     152//         return -1;
     153//     }
     154//     frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data);
     155//     frames_ctx->format    = AV_PIX_FMT_VAAPI;
     156//     frames_ctx->sw_format = AV_PIX_FMT_NV12;
     157//     frames_ctx->width     = ctx->width;
     158//     frames_ctx->height    = ctx->height;
     159//     frames_ctx->initial_pool_size = poolsize;
     160//     if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) {
     161//         fprintf(stderr, "Failed to initialize VAAPI frame context.");
     162//         av_buffer_unref(&hw_frames_ref);
     163//         return err;
     164//     }
     165//     ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
     166//     if (!ctx->hw_frames_ctx)
     167//         err = AVERROR(ENOMEM);
     168
     169//     av_buffer_unref(&hw_frames_ref);
     170//     return err;
     171// }
  • new file mythtv/libs/libmythtv/vaapi2context.h

    diff --git a/mythtv/libs/libmythtv/vaapi2context.h b/mythtv/libs/libmythtv/vaapi2context.h
    new file mode 100644
    index 00000000000..fcd84b5833d
    - +  
     1//////////////////////////////////////////////////////////////////////////////
     2// Copyright (c) 2017 MythTV Developers <mythtv-dev@mythtv.org>
     3//
     4// This is part of MythTV (https://www.mythtv.org)
     5//
     6// This program is free software; you can redistribute it and/or modify
     7// it under the terms of the GNU General Public License as published by
     8// the Free Software Foundation; either version 2 of the License, or
     9// (at your option) any later version.
     10//
     11// This program is distributed in the hope that it will be useful,
     12// but WITHOUT ANY WARRANTY; without even the implied warranty of
     13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14// GNU General Public License for more details.
     15//
     16// You should have received a copy of the GNU General Public License
     17// along with this program; if not, write to the Free Software
     18// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
     19//
     20// You should have received a copy of the GNU General Public License
     21// along with this program.  If not, see <http://www.gnu.org/licenses/>.
     22//
     23//////////////////////////////////////////////////////////////////////////////
     24
     25
     26#ifndef VAAPI2CONTEXT_H
     27#define VAAPI2CONTEXT_H
     28
     29#include "mythtvexp.h"
     30#include "mythcodecid.h"
     31#include "mythcodeccontext.h"
     32
     33extern "C" {
     34    #include "libavcodec/avcodec.h"
     35}
     36
     37class MTV_PUBLIC Vaapi2Context : public MythCodecContext
     38{
     39  public:
     40    Vaapi2Context(AVStream* initStream);
     41    static MythCodecID GetBestSupportedCodec(AVCodec **ppCodec,
     42                                             const QString &decoder,
     43                                             uint stream_type,
     44                                             AVPixelFormat &pix_fmt);
     45    int HwDecoderInit(AVCodecContext *ctx);
     46    virtual QString GetDeinterlaceFilter(QString filtername);
     47};
     48
     49#endif // VAAPI2CONTEXT_H
     50 No newline at end of file
  • mythtv/libs/libmythtv/videodisplayprofile.cpp

    diff --git a/mythtv/libs/libmythtv/videodisplayprofile.cpp b/mythtv/libs/libmythtv/videodisplayprofile.cpp
    index 700ee3bb990..990b1ae6f7b 100644
    a b using namespace std;  
    88#include "mythlogging.h"
    99#include "videooutbase.h"
    1010#include "avformatdecoder.h"
     11#include "mythcodeccontext.h"
    1112
    1213
    1314// options are NNN NNN-MMM 0-MMM NNN-99999 >NNN >=NNN <MMM <=MMM or blank
    bool ProfileItem::IsValid(QString *reason) const  
    258259    }
    259260
    260261    QStringList deints    = VideoDisplayProfile::GetDeinterlacers(renderer);
     262    QStringList decoderdeints  = MythCodecContext::GetDeinterlacers(decoder);
     263    deints.append(decoderdeints);
    261264    QString     deint0    = Get("pref_deint0");
    262265    QString     deint1    = Get("pref_deint1");
    263266    if (!deint0.isEmpty() && !deints.contains(deint0))
    QString VideoDisplayProfile::GetDecoderName(const QString &decoder)  
    852855        dec_name["dxva2"]    = QObject::tr("Windows hardware acceleration");
    853856        dec_name["vda"]      = QObject::tr("Mac VDA hardware acceleration");
    854857        dec_name["mediacodec"] = QObject::tr("Android MediaCodec decoder");
     858        dec_name["vaapi2"]   = QObject::tr("VAAPI2 acceleration");
    855859    }
    856860
    857861    QString ret = decoder;
    QString VideoDisplayProfile::GetDecoderHelp(QString decoder)  
    913917            "Mediacodec will use the graphics hardware to "
    914918            "accelerate video decoding on Android. ");
    915919
     920    if (decoder == "vaapi2")
     921        msg += QObject::tr(
     922            "VAAPI2 is a new implementation of VAAPI to will use the graphics hardware to "
     923            "accelerate video decoding on Intel CPUs. ");
     924
    916925    return msg;
    917926}
    918927
    QString VideoDisplayProfile::GetDeinterlacerName(const QString &short_name)  
    941950    else if ("fieldorderdoubleprocessdeint" == short_name)
    942951        return QObject::tr("Interlaced (2x)");
    943952    else if ("opengllinearblend" == short_name)
    944         return QObject::tr("Linear blend (HW)");
     953        return QObject::tr("Linear blend (HW-GL)");
    945954    else if ("openglkerneldeint" == short_name)
    946         return QObject::tr("Kernel (HW)");
     955        return QObject::tr("Kernel (HW-GL)");
    947956    else if ("openglbobdeint" == short_name)
    948         return QObject::tr("Bob (2x, HW)");
     957        return QObject::tr("Bob (2x, HW-GL)");
    949958    else if ("openglonefield" == short_name)
    950         return QObject::tr("One field (HW)");
     959        return QObject::tr("One field (HW-GL)");
    951960    else if ("opengldoubleratekerneldeint" == short_name)
    952         return QObject::tr("Kernel (2x, HW)");
     961        return QObject::tr("Kernel (2x, HW-GL)");
    953962    else if ("opengldoubleratelinearblend" == short_name)
    954         return QObject::tr("Linear blend (2x, HW)");
     963        return QObject::tr("Linear blend (2x, HW-GL)");
    955964    else if ("opengldoubleratefieldorder" == short_name)
    956         return QObject::tr("Interlaced (2x, HW)");
     965        return QObject::tr("Interlaced (2x, HW-GL)");
    957966    else if ("vdpauonefield" == short_name)
    958967        return QObject::tr("One Field (1x, HW)");
    959968    else if ("vdpaubobdeint" == short_name)
    QString VideoDisplayProfile::GetDeinterlacerName(const QString &short_name)  
    978987    else if ("openmaxlinedouble" == short_name)
    979988        return QObject::tr("Line double (HW)");
    980989#endif // def USING_OPENMAX
     990#ifdef USING_VAAPI2
     991    else if ("vaapi2default" == short_name)
     992        return QObject::tr("Advanced (HW-VA)");
     993    else if ("vaapi2bob" == short_name)
     994        return QObject::tr("Bob (HW-VA)");
     995    else if ("vaapi2weave" == short_name)
     996        return QObject::tr("Weave (HW-VA)");
     997    else if ("vaapi2motion_adaptive" == short_name)
     998        return QObject::tr("Motion Adaptive (HW-VA)");
     999    else if ("vaapi2motion_compensated" == short_name)
     1000        return QObject::tr("Motion Compensated (HW-VA)");
     1001    else if ("vaapi2doubleratedefault" == short_name)
     1002        return QObject::tr("Advanced (2x, HW-VA)");
     1003    else if ("vaapi2doubleratebob" == short_name)
     1004        return QObject::tr("Bob (2x, HW-VA)");
     1005    else if ("vaapi2doublerateweave" == short_name)
     1006        return QObject::tr("Weave (2x, HW-VA)");
     1007    else if ("vaapi2doubleratemotion_adaptive" == short_name)
     1008        return QObject::tr("Motion Adaptive (2x, HW-VA)");
     1009    else if ("vaapi2doubleratemotion_compensated" == short_name)
     1010        return QObject::tr("Motion Compensated (2x, HW-VA)");
     1011#endif
    9811012
    9821013    return "";
    9831014}
    void VideoDisplayProfile::CreateProfiles(const QString &hostname)  
    14681499        CreateProfile(groupid, 1, "", "", "",
    14691500                      "mediacodec", 4, true, "opengl",
    14701501                      "opengl2", true,
    1471                       "none", "none",
     1502                      "opengldoubleratelinearblend", "opengllinearblend",
     1503                      "");
     1504    }
     1505#endif
     1506
     1507#ifdef USING_VAAPI2
     1508    if (!profiles.contains("VAAPI2 Normal")) {
     1509        (void) QObject::tr("VAAPI2 Normal",
     1510                           "Sample: VAAPI2 Normal");
     1511        groupid = CreateProfileGroup("VAAPI2 Normal", hostname);
     1512        CreateProfile(groupid, 1, "", "", "",
     1513                      "vaapi2", 4, true, "opengl",
     1514                      "opengl2", true,
     1515                      "vaapi2doubleratedefault", "vaapi2default",
    14721516                      "");
    14731517    }
    14741518#endif
    QString VideoDisplayProfile::GetDeinterlacerHelp(const QString &deint)  
    16151659
    16161660    QString kUsingGPU = QObject::tr("(Hardware Accelerated)");
    16171661
     1662    QString kUsingVA = QObject::tr("(VAAPI Hardware Accelerated)");
     1663
     1664    QString kUsingGL = QObject::tr("(OpenGL Hardware Accelerated)");
     1665
    16181666    QString kGreedyHMsg = QObject::tr(
    16191667        "This deinterlacer uses several fields to reduce motion blur. "
    16201668        "It has increased CPU requirements.");
    QString VideoDisplayProfile::GetDeinterlacerHelp(const QString &deint)  
    16351683        "This deinterlacer uses multiple fields to reduce motion blur "
    16361684        "and smooth edges. ");
    16371685
     1686    QString kMostAdvMsg = QObject::tr(
     1687        "Use the most advanced hardware deinterlacing algorithm available. ");
     1688
     1689    QString kWeaveMsg = QObject::tr(
     1690        "Use the weave deinterlacing algorithm. ");
     1691
     1692    QString kMAMsg = QObject::tr(
     1693        "Use the motion adaptive deinterlacing algorithm. ");
     1694
     1695    QString kMCMsg = QObject::tr(
     1696        "Use the motion compensated deinterlacing algorithm. ");
     1697
    16381698    if (deint == "none")
    16391699        msg = kNoneMsg;
    16401700    else if (deint == "onefield")
    QString VideoDisplayProfile::GetDeinterlacerHelp(const QString &deint)  
    16481708    else if (deint == "kerneldoubleprocessdeint")
    16491709        msg = kKernelMsg + " " + kDoubleRateMsg;
    16501710    else if (deint == "openglonefield")
    1651         msg = kOneFieldMsg + " " + kUsingGPU;
     1711        msg = kOneFieldMsg + " " + kUsingGL;
    16521712    else if (deint == "openglbobdeint")
    1653         msg = kBobMsg + " " + kUsingGPU;
     1713        msg = kBobMsg + " " + kUsingGL;
    16541714    else if (deint == "opengllinearblend")
    1655         msg = kLinearBlendMsg + " " + kUsingGPU;
     1715        msg = kLinearBlendMsg + " " + kUsingGL;
    16561716    else if (deint == "openglkerneldeint")
    1657         msg = kKernelMsg + " " + kUsingGPU;
     1717        msg = kKernelMsg + " " + kUsingGL;
    16581718    else if (deint == "opengldoubleratelinearblend")
    1659         msg = kLinearBlendMsg + " " +  kDoubleRateMsg + " " + kUsingGPU;
     1719        msg = kLinearBlendMsg + " " +  kDoubleRateMsg + " " + kUsingGL;
    16601720    else if (deint == "opengldoubleratekerneldeint")
    1661         msg = kKernelMsg + " " +  kDoubleRateMsg + " " + kUsingGPU;
     1721        msg = kKernelMsg + " " +  kDoubleRateMsg + " " + kUsingGL;
    16621722    else if (deint == "opengldoubleratefieldorder")
    1663         msg = kFieldOrderMsg + " " +  kDoubleRateMsg  + " " + kUsingGPU;
     1723        msg = kFieldOrderMsg + " " +  kDoubleRateMsg  + " " + kUsingGL;
    16641724    else if (deint == "greedyhdeint")
    16651725        msg = kGreedyHMsg;
    16661726    else if (deint == "greedyhdoubleprocessdeint")
    QString VideoDisplayProfile::GetDeinterlacerHelp(const QString &deint)  
    16871747        msg = kOneFieldMsg + " " + kUsingGPU;
    16881748    else if (deint == "vaapibobdeint")
    16891749        msg = kBobMsg + " " + kUsingGPU;
     1750
     1751    else if (deint == "vaapi2default")
     1752        msg = kMostAdvMsg + " " +  kUsingVA;
     1753    else if (deint == "vaapi2bob")
     1754        msg = kBobMsg + " " +  kUsingVA;
     1755    else if (deint == "vaapi2weave")
     1756        msg = kWeaveMsg + " " +  kUsingVA;
     1757    else if (deint == "vaapi2motion_adaptive")
     1758        msg = kMAMsg + " " +  kUsingVA;
     1759    else if (deint == "vaapi2motion_compensated")
     1760        msg = kMCMsg + " " +  kUsingVA;
     1761    else if (deint == "vaapi2doubleratedefault")
     1762        msg = kMostAdvMsg + " " +  kDoubleRateMsg + " " + kUsingVA;
     1763    else if (deint == "vaapi2doubleratebob")
     1764        msg = kBobMsg + " " +  kDoubleRateMsg + " " + kUsingVA;
     1765    else if (deint == "vaapi2doublerateweave")
     1766        msg = kWeaveMsg + " " +  kDoubleRateMsg + " " + kUsingVA;
     1767    else if (deint == "vaapi2doubleratemotion_adaptive")
     1768        msg = kMAMsg + " " +  kDoubleRateMsg + " " + kUsingVA;
     1769    else if (deint == "vaapi2doubleratemotion_compensated")
     1770        msg = kMCMsg + " " +  kDoubleRateMsg + " " + kUsingVA;
    16901771    else
    16911772        msg = QObject::tr("'%1' has not been documented yet.").arg(deint);
    16921773
  • mythtv/libs/libmythtv/videoout_opengl.cpp

    diff --git a/mythtv/libs/libmythtv/videoout_opengl.cpp b/mythtv/libs/libmythtv/videoout_opengl.cpp
    index b689947d738..51b62527ecf 100644
    a b void VideoOutputOpenGL::GetRenderOptions(render_opts &opts,  
    4040        (*opts.safe_renderers)["openmax"].append("opengl");
    4141    if (opts.decoders->contains("mediacodec"))
    4242        (*opts.safe_renderers)["mediacodec"].append("opengl");
     43    if (opts.decoders->contains("vaapi2"))
     44        (*opts.safe_renderers)["vaapi2"].append("opengl");
    4345    opts.priorities->insert("opengl", 65);
    4446
    4547    // lite profile - no colourspace control, GPU deinterlacing
    bool VideoOutputOpenGL::InputChanged(const QSize &video_dim_buf,  
    270272        StopEmbedding();
    271273    }
    272274
    273     if (!codec_is_std(av_codec_id) && !codec_is_mediacodec(av_codec_id))
     275    if (!codec_is_std(av_codec_id)
     276        && !codec_is_mediacodec(av_codec_id)
     277        && !codec_is_vaapi2(av_codec_id))
    274278    {
    275279        LOG(VB_GENERAL, LOG_ERR, LOC + "New video codec is not supported.");
    276280        errorState = kError_Unknown;
    QStringList VideoOutputOpenGL::GetAllowedRenderers(  
    741745    {
    742746        list << "opengl" << "opengl-lite";
    743747    }
    744     else if (codec_is_mediacodec(myth_codec_id) && !getenv("NO_OPENGL"))
     748    else if ((codec_is_mediacodec(myth_codec_id) || codec_is_vaapi2(myth_codec_id))
     749            && !getenv("NO_OPENGL"))
    745750    {
    746751        list << "opengl";
    747752    }
    bool VideoOutputOpenGL::SetupDeinterlace(  
    812817    if (db_vdisp_profile)
    813818        m_deintfiltername = db_vdisp_profile->GetFilteredDeint(overridefilter);
    814819
     820    if (m_deintfiltername.startsWith("vaapi2"))
     821        return false;
     822
    815823    if (!m_deintfiltername.contains("opengl"))
    816824    {
    817825        gl_videochain->SetDeinterlacing(false);
  • mythtv/libs/libmythtv/videoout_xv.cpp

    diff --git a/mythtv/libs/libmythtv/videoout_xv.cpp b/mythtv/libs/libmythtv/videoout_xv.cpp
    index 2f9518bcdd2..d8ecadd3c1f 100644
    a b void VideoOutputXv::GetRenderOptions(render_opts &opts,  
    122122        (*opts.safe_renderers)["crystalhd"].append("xshm");
    123123        (*opts.safe_renderers)["crystalhd"].append("xv-blit");
    124124    }
     125
     126    // These could work but needs some debugging so disable for now
     127    // if (opts.decoders->contains("vaapi2"))
     128    // {
     129    //     (*opts.safe_renderers)["vaapi2"].append("xlib");
     130    //     (*opts.safe_renderers)["vaapi2"].append("xshm");
     131    //     (*opts.safe_renderers)["vaapi2"].append("xv-blit");
     132    // }
     133
    125134}
    126135
    127136/** \class  VideoOutputXv
    static QStringList allowed_video_renderers(  
    20922101
    20932102    QStringList list;
    20942103    if (codec_is_std(myth_codec_id))
     2104    // this needs some work
     2105    //  || codec_is_vaapi2(myth_codec_id))
    20952106    {
    20962107        if (xv)
    20972108            list += "xv-blit";
  • mythtv/libs/libmythtv/videooutbase.cpp

    diff --git a/mythtv/libs/libmythtv/videooutbase.cpp b/mythtv/libs/libmythtv/videooutbase.cpp
    index 4f3f575c4c1..69cb05c8e2c 100644
    a b bool VideoOutput::SetupDeinterlace(bool interlaced,  
    608608        else
    609609            m_deintfiltername = "";
    610610
    611         m_deintFiltMan = new FilterManager;
    612611        m_deintFilter = NULL;
     612        m_deintFiltMan = NULL;
     613
     614        if (m_deintfiltername.startsWith("vaapi2"))
     615        {
     616            m_deinterlacing = false;
     617            return false;
     618        }
     619
     620        m_deintFiltMan = new FilterManager;
    613621
    614622        if (!m_deintfiltername.isEmpty())
    615623        {
  • mythtv/libs/libmythtv/videooutbase.h

    diff --git a/mythtv/libs/libmythtv/videooutbase.h b/mythtv/libs/libmythtv/videooutbase.h
    index 0c11bd60ce2..35a5f2877a5 100644
    a b class VideoOutput  
    7676    virtual void PrepareFrame(VideoFrame *buffer, FrameScanType,
    7777                              OSD *osd) = 0;
    7878    virtual void Show(FrameScanType) = 0;
     79    VideoDisplayProfile *GetProfile() { return db_vdisp_profile; }
     80
    7981
    8082    virtual void WindowResized(const QSize &) {}
    8183
  • mythtv/programs/mythfrontend/globalsettings.cpp

    diff --git a/mythtv/programs/mythfrontend/globalsettings.cpp b/mythtv/programs/mythfrontend/globalsettings.cpp
    index 7f87ba55caa..c169aab6a50 100644
    a b  
    3838#include "mythuihelper.h"
    3939#include "mythuidefines.h"
    4040#include "langsettings.h"
     41#include "mythcodeccontext.h"
    4142
    4243#ifdef USING_AIRPLAY
    4344#include "AirPlay/mythraopconnection.h"
    static HostSpinBoxSetting *AudioReadAhead()  
    6667    return gc;
    6768}
    6869
     70#ifdef USING_VAAPI2
     71static HostTextEditSetting *VAAPIDevice()
     72{
     73    HostTextEditSetting *ge = new HostTextEditSetting("VAAPIDevice");
     74
     75    ge->setLabel(MainGeneralSettings::tr("Decoder Device for VAAPI2 hardware decoding"));
     76
     77    ge->setValue("");
     78
     79    QString help = MainGeneralSettings::tr(
     80        "Use this if your system does not detect the VAAPI device. "
     81        "Example: '/dev/dri/renderD128'.");
     82
     83    ge->setHelpText(help);
     84
     85    return ge;
     86}
     87#endif
     88
    6989#if CONFIG_DEBUGTYPE
    7090static HostCheckBoxSetting *FFmpegDemuxer()
    7191{
    void PlaybackProfileItemConfig::decoderChanged(const QString &dec)  
    937957
    938958    decoder->setHelpText(VideoDisplayProfile::GetDecoderHelp(dec));
    939959
     960    QString vrenderer2 = vidrend->getValue();
     961    vrenderChanged(vrenderer2);
     962
    940963    InitLabel();
    941964}
    942965
    void PlaybackProfileItemConfig::vrenderChanged(const QString &renderer)  
    944967{
    945968    QStringList osds    = VideoDisplayProfile::GetOSDs(renderer);
    946969    QStringList deints  = VideoDisplayProfile::GetDeinterlacers(renderer);
     970    QString decodername = decoder->getValue();
     971    QStringList decoderdeints  = MythCodecContext::GetDeinterlacers(decodername);
     972    deints.append(decoderdeints);
    947973    QString     losd    = osdrend->getValue();
    948974    QString     ldeint0 = deint0->getValue();
    949975    QString     ldeint1 = deint1->getValue();
    void PlaybackSettings::Load(void)  
    39583984    GroupSetting* general = new GroupSetting();
    39593985    general->setLabel(tr("General Playback"));
    39603986    general->addChild(RealtimePriority());
     3987#ifdef USING_VAAPI2
     3988    general->addChild(VAAPIDevice());
     3989#endif
    39613990    general->addChild(AudioReadAhead());
    39623991    general->addChild(JumpToProgramOSD());
    39633992    general->addChild(ClearSavedPosition());
  • mythtv/programs/mythfrontend/mythfrontend.pro

    diff --git a/mythtv/programs/mythfrontend/mythfrontend.pro b/mythtv/programs/mythfrontend/mythfrontend.pro
    index 580bc606af7..83517acfefc 100644
    a b using_opengl:DEFINES += USING_OPENGL  
    116116using_opengl_video:DEFINES += USING_OPENGL_VIDEO
    117117using_vdpau:DEFINES += USING_VDPAU
    118118using_vaapi:using_opengl_video:DEFINES += USING_GLVAAPI
     119using_vaapi2:DEFINES += USING_VAAPI2
    119120
    120121using_pulse:DEFINES += USING_PULSE
    121122using_pulseoutput: DEFINES += USING_PULSEOUTPUT