Ticket #13311: 20180909_1639_fix_configure.patch

File 20180909_1639_fix_configure.patch, 77.9 KB (added by Peter Bennett, 6 years ago)

Cleaned up and ready for commit to master

  • mythtv/configure

    diff --git a/mythtv/configure b/mythtv/configure
    index f7cfc291b82..ec11749e0f5 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 VAAPI2 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
    EXTERNAL_LIBRARY_LIST=" 
    13951396    opengl
    13961397    sdl
    13971398    sdl2
     1399    vaapi
     1400    vaapi2
    13981401"
    13991402
    14001403HWACCEL_AUTODETECT_LIBRARY_LIST="
    14011404    crystalhd
    14021405    dxva2
    1403     vaapi
    14041406    vda
    14051407    vdpau
    14061408"
    USING_LIST=' 
    20402042    opengl
    20412043    opengles
    20422044    vaapi
     2045    vaapi2
    20432046    vdpau
    20442047    openmax
    20452048    mediacodec
    enable libdns_sd 
    27692772enable libxml2
    27702773enable lirc
    27712774enable mediacodec
     2775enable vaapi
     2776enable vaapi2
    27722777enable mheg
    27732778enable mythtranscode
    27742779enable opengl
    enabled vaapi && 
    62036208    check_cpp_condition "va/va.h" "VA_CHECK_VERSION(1, 0, 0)" &&
    62046209    enable vaapi_1
    62056210
     6211enabled vaapi2 &&
     6212    check_func_headers va/va.h vaInitialize -lva ||
     6213    disable vaapi2
     6214
    62066215enabled vdpau &&
    62076216    check_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" ||
    62086217    disable vdpau
    ffmpeg_optset extra_cxxflags extra_ldflags target_os 
    70577066ffmpeg_optset pkg_config prefix libdir as objcc dep_cc host_cc
    70587067ffmpeg_optset host_ld
    70597068ffmpeg_optenable cross_compile libmp3lame libx264 libx265 libvpx libxvid
    7060 ffmpeg_optenable vdpau vaapi libxml2 libass dxva2
     7069ffmpeg_optenable vdpau libxml2 libass dxva2
    70617070ffmpeg_optenable libbluray libfontconfig libfreetype libiec61883
    70627071ffmpeg_optenable crystalhd sdl2 ffplay
    70637072if test $target_os = "android"; then
    if test $target_os = "android"; then 
    70667075else
    70677076    disable mediacodec
    70687077fi
    7069 
     7078if enabled vaapi || enabled vaapi2 ; then
     7079    ffopts="$ffopts --enable-vaapi"
     7080fi
    70707081ffmpeg_extra_cflags="$extra_cflags -w"
    70717082
    70727083## Call FFmpeg configure here
    if enabled x11 ; then 
    72727283  echo "xv support                ${xv-no}"
    72737284  echo "VDPAU support             ${vdpau-no}"
    72747285  echo "VAAPI support             ${vaapi-no}"
     7286  echo "VAAPI2 support            ${vaapi2-no}"
    72757287  echo "CrystalHD support         ${crystalhd-no}"
    72767288  echo "OpenMAX support           ${openmax-no}"
    72777289  if enabled openmax ; then
  • mythtv/libs/libmythtv/avformatdecoder.cpp

    diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
    index 5b5fce95e88..835a53e23c7 100644
    a b using namespace std; 
    4343#include "lcddevice.h"
    4444
    4545#include "audiooutput.h"
     46#include "mythcodeccontext.h"
    4647
    4748#ifdef USING_VDPAU
    4849#include "videoout_vdpau.h"
    extern "C" { 
    7071#include <QtAndroidExtras>
    7172#endif
    7273
     74#ifdef USING_VAAPI2
     75#include "vaapi2context.h"
     76#endif
     77
    7378extern "C" {
    7479#include "libavutil/avutil.h"
    7580#include "libavutil/error.h"
    int get_avf_buffer_dxva2(struct AVCodecContext *c, AVFrame *pic, int flags); 
    182187#ifdef USING_VAAPI
    183188int  get_avf_buffer_vaapi(struct AVCodecContext *c, AVFrame *pic, int flags);
    184189#endif
     190#ifdef USING_VAAPI2
     191int  get_avf_buffer_vaapi2(struct AVCodecContext *c, AVFrame *pic, int flags);
     192#endif
    185193
    186194static int determinable_frame_size(struct AVCodecContext *avctx)
    187195{
    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");
    AvFormatDecoder::~AvFormatDecoder() 
    478490    delete ttd;
    479491    delete private_dec;
    480492    delete m_h264_parser;
     493    delete m_mythcodecctx;
    481494
    482495    sws_freeContext(sws_ctx);
    483496
    enum AVPixelFormat get_format_dxva2(struct AVCodecContext *avctx, 
    15151528}
    15161529#endif
    15171530
    1518 #ifdef USING_VAAPI
     1531#if defined(USING_VAAPI) || defined(USING_VAAPI2)
    15191532static bool IS_VAAPI_PIX_FMT(enum AVPixelFormat fmt)
    15201533{
    15211534    return fmt == AV_PIX_FMT_VAAPI_MOCO ||
    15221535           fmt == AV_PIX_FMT_VAAPI_IDCT ||
    15231536           fmt == AV_PIX_FMT_VAAPI_VLD;
    15241537}
     1538#endif
    15251539
     1540#ifdef USING_VAAPI
    15261541// Declared separately to allow attribute
    15271542static enum AVPixelFormat get_format_vaapi(struct AVCodecContext *,
    15281543                                         const enum AVPixelFormat *) MUNUSED;
    enum AVPixelFormat get_format_vaapi(struct AVCodecContext *avctx, 
    15491564}
    15501565#endif
    15511566
     1567#ifdef USING_VAAPI2
     1568static enum AVPixelFormat get_format_vaapi2(struct AVCodecContext *avctx,
     1569                                           const enum AVPixelFormat *valid_fmts)
     1570{
     1571    enum AVPixelFormat ret = AV_PIX_FMT_NONE;
     1572    while (*valid_fmts != AV_PIX_FMT_NONE) {
     1573        if (IS_VAAPI_PIX_FMT(*valid_fmts))
     1574        {
     1575            ret = *valid_fmts;
     1576            avctx->pix_fmt = ret;
     1577            // Vaapi2Context::SetHwframeCtx(avctx, 20);
     1578            break;
     1579        }
     1580        valid_fmts++;
     1581    }
     1582    return ret;
     1583}
     1584#endif
     1585
    15521586#ifdef USING_MEDIACODEC
    15531587static enum AVPixelFormat get_format_mediacodec(struct AVCodecContext *avctx,
    15541588                                           const enum AVPixelFormat *valid_fmts)
    void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc, 
    16291663    else
    16301664#endif
    16311665#ifdef USING_VAAPI
    1632     if (CODEC_IS_VAAPI(codec, enc))
     1666    if (CODEC_IS_VAAPI(codec, enc) && codec_is_vaapi(video_codec_id))
    16331667    {
    16341668        enc->get_buffer2     = get_avf_buffer_vaapi;
    16351669        enc->get_format      = get_format_vaapi;
    void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc, 
    16441678        enc->slice_flags     = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
    16451679    }
    16461680    else
     1681#endif
     1682#ifdef USING_VAAPI2
     1683    if (codec_is_vaapi2(video_codec_id))
     1684    {
     1685        enc->get_buffer2     = get_avf_buffer_vaapi2;
     1686        enc->get_format      = get_format_vaapi2;
     1687    }
     1688    else
    16471689#endif
    16481690    if (codec && codec->capabilities & AV_CODEC_CAP_DR1)
    16491691    {
    void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc, 
    16591701                .arg(ff_codec_id_string(enc->codec_id)));
    16601702    }
    16611703
     1704    QString deinterlacer;
     1705    if (m_mythcodecctx)
     1706        deinterlacer = m_mythcodecctx->getDeinterlacerName();
     1707    delete m_mythcodecctx;
     1708    m_mythcodecctx = MythCodecContext::createMythCodecContext(video_codec_id);
     1709    m_mythcodecctx->setPlayer(m_parent);
     1710    m_mythcodecctx->setStream(stream);
     1711    m_mythcodecctx->setDeinterlacer(true,deinterlacer);
     1712
     1713    int ret = m_mythcodecctx->HwDecoderInit(enc);
     1714    if (ret < 0)
     1715    {
     1716        char error[AV_ERROR_MAX_STRING_SIZE];
     1717        if (ret < 0)
     1718        {
     1719            LOG(VB_GENERAL, LOG_ERR, LOC +
     1720                QString("HwDecoderInit unable to initialize hardware decoder: %1 (%2)")
     1721                .arg(av_make_error_string(error, sizeof(error), ret))
     1722                .arg(ret));
     1723            // force it to switch to software decoding
     1724            averror_count = SEQ_PKT_ERR_MAX + 1;
     1725            m_streams_changed = true;
     1726        }
     1727    }
     1728
    16621729    if (FlagIsSet(kDecodeLowRes)    || FlagIsSet(kDecodeSingleThreaded) ||
    16631730        FlagIsSet(kDecodeFewBlocks) || FlagIsSet(kDecodeNoLoopFilter)   ||
    16641731        FlagIsSet(kDecodeNoDecode))
    int AvFormatDecoder::ScanStreams(bool novideo) 
    25362603                    }
    25372604                }
    25382605#endif // USING_MEDIACODEC
     2606#ifdef USING_VAAPI2
     2607                if (!foundgpudecoder)
     2608                {
     2609                    MythCodecID vaapi2_mcid;
     2610                    AVPixelFormat pix_fmt = AV_PIX_FMT_YUV420P;
     2611                    vaapi2_mcid = Vaapi2Context::GetBestSupportedCodec(
     2612                        &codec, dec, mpeg_version(enc->codec_id),
     2613                        pix_fmt);
     2614
     2615                    if (codec_is_vaapi2(vaapi2_mcid))
     2616                    {
     2617                        gCodecMap->freeCodecContext(ic->streams[selTrack]);
     2618                        enc = gCodecMap->getCodecContext(ic->streams[selTrack], codec);
     2619                        video_codec_id = vaapi2_mcid;
     2620                        foundgpudecoder = true;
     2621                    }
     2622                }
     2623#endif // USING_VAAPI2
    25392624            }
    25402625            // default to mpeg2
    25412626            if (video_codec_id == kCodec_NONE)
    int AvFormatDecoder::ScanStreams(bool novideo) 
    25562641
    25572642            use_frame_timing = false;
    25582643            if (! private_dec
    2559                 && (codec_is_std(video_codec_id) || codec_is_mediacodec(video_codec_id)))
     2644                && (codec_is_std(video_codec_id)
     2645                    || codec_is_mediacodec(video_codec_id)
     2646                    || codec_is_vaapi2(video_codec_id)))
    25602647                use_frame_timing = true;
    25612648
    25622649            if (FlagIsSet(kDecodeSingleThreaded))
    int get_avf_buffer_vaapi(struct AVCodecContext *c, AVFrame *pic, int /*flags*/) 
    30563143}
    30573144#endif
    30583145
     3146#ifdef USING_VAAPI2
     3147int get_avf_buffer_vaapi2(struct AVCodecContext *c, AVFrame *pic, int flags)
     3148{
     3149    AvFormatDecoder *nd = (AvFormatDecoder *)(c->opaque);
     3150    nd->directrendering = false;
     3151    return avcodec_default_get_buffer2(c, pic, flags);
     3152}
     3153#endif
     3154
    30593155void AvFormatDecoder::DecodeDTVCC(const uint8_t *buf, uint len, bool scte)
    30603156{
    30613157    if (!len)
    bool AvFormatDecoder::ProcessVideoPacket(AVStream *curstream, AVPacket *pkt) 
    36303726            //  into separate routines or separate threads.
    36313727            //  Also now that it always consumes a whole buffer some code
    36323728            //  in the caller may be able to be optimized.
    3633             ret = avcodec_receive_frame(context, mpa_pic);
     3729
     3730            // FilteredReceiveFrame will call avcodec_receive_frame and
     3731            // apply any codec-dependent filtering
     3732            ret = m_mythcodecctx->FilteredReceiveFrame(context, mpa_pic);
    36343733
    36353734            if (ret == 0)
    36363735                gotpicture = 1;
    bool AvFormatDecoder::ProcessVideoPacket(AVStream *curstream, AVPacket *pkt) 
    36713770                    QString("video avcodec_send_packet error: %1 (%2) gotpicture:%3")
    36723771                    .arg(av_make_error_string(error, sizeof(error), ret2))
    36733772                    .arg(ret2).arg(gotpicture));
    3674             if (ret == AVERROR_INVALIDDATA || ret2 == AVERROR_INVALIDDATA)
     3773            if (++averror_count > SEQ_PKT_ERR_MAX)
    36753774            {
    3676                 if (++averror_count > SEQ_PKT_ERR_MAX)
    3677                 {
    3678                     // If erroring on GPU assist, try switching to software decode
    3679                     if (codec_is_std(video_codec_id))
    3680                         m_parent->SetErrored(QObject::tr("Video Decode Error"));
    3681                     else
    3682                         m_streams_changed = true;
    3683                 }
     3775                // If erroring on GPU assist, try switching to software decode
     3776                if (codec_is_std(video_codec_id))
     3777                    m_parent->SetErrored(QObject::tr("Video Decode Error"));
     3778                else
     3779                    m_streams_changed = true;
    36843780            }
    36853781            if (ret == AVERROR_EXTERNAL || ret2 == AVERROR_EXTERNAL)
    36863782                m_streams_changed = true;
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic) 
    38403936    }
    38413937    else if (!directrendering)
    38423938    {
     3939        AVFrame *tmp_frame = NULL;
     3940        AVFrame *use_frame = NULL;
     3941#ifdef USING_VAAPI2
     3942        if (IS_VAAPI_PIX_FMT((AVPixelFormat)mpa_pic->format))
     3943        {
     3944            int ret = 0;
     3945            tmp_frame = av_frame_alloc();
     3946            use_frame = tmp_frame;
     3947            /* retrieve data from GPU to CPU */
     3948            if ((ret = av_hwframe_transfer_data(use_frame, mpa_pic, 0)) < 0) {
     3949                LOG(VB_GENERAL, LOG_ERR, LOC
     3950                    + QString("Error %1 transferring the data to system memory")
     3951                        .arg(ret));
     3952                av_frame_free(&use_frame);
     3953                return false;
     3954            }
     3955        }
     3956        else
     3957#endif // USING_VAAPI2
     3958            use_frame = mpa_pic;
     3959
    38433960        AVFrame tmppicture;
    38443961
    38453962        VideoFrame *xf = picframe;
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic) 
    38473964
    38483965        unsigned char *buf = picframe->buf;
    38493966        av_image_fill_arrays(tmppicture.data, tmppicture.linesize,
    3850             buf, AV_PIX_FMT_YUV420P, context->width,
    3851                        context->height, IMAGE_ALIGN);
     3967            buf, AV_PIX_FMT_YUV420P, use_frame->width,
     3968                       use_frame->height, IMAGE_ALIGN);
    38523969        tmppicture.data[0] = buf + picframe->offsets[0];
    38533970        tmppicture.data[1] = buf + picframe->offsets[1];
    38543971        tmppicture.data[2] = buf + picframe->offsets[2];
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic) 
    38573974        tmppicture.linesize[2] = picframe->pitches[2];
    38583975
    38593976        QSize dim = get_video_dim(*context);
    3860         sws_ctx = sws_getCachedContext(sws_ctx, context->width,
    3861                                        context->height, context->pix_fmt,
    3862                                        context->width, context->height,
     3977        sws_ctx = sws_getCachedContext(sws_ctx, use_frame->width,
     3978                                       use_frame->height, (AVPixelFormat)use_frame->format,
     3979                                       use_frame->width, use_frame->height,
    38633980                                       AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR,
    38643981                                       NULL, NULL, NULL);
    38653982        if (!sws_ctx)
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic) 
    38673984            LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate sws context");
    38683985            return false;
    38693986        }
    3870         sws_scale(sws_ctx, mpa_pic->data, mpa_pic->linesize, 0, dim.height(),
     3987        sws_scale(sws_ctx, use_frame->data, use_frame->linesize, 0, dim.height(),
    38713988                  tmppicture.data, tmppicture.linesize);
    38723989
    38733990        if (xf)
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic) 
    38803997            xf->aspect = current_aspect;
    38813998            m_parent->DiscardVideoFrame(xf);
    38823999        }
     4000        if (tmp_frame)
     4001            av_frame_free(&tmp_frame);
    38834002    }
    38844003    else if (!picframe)
    38854004    {
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic) 
    39284047        // If fps has doubled due to frame-doubling deinterlace
    39294048        // Set fps to double value.
    39304049        double fpschange = calcfps / fps;
     4050        int prior = fpsMultiplier;
    39314051        if (fpschange > 1.9 && fpschange < 2.1)
    39324052            fpsMultiplier = 2;
    39334053        if (fpschange > 0.5 && fpschange < 0.6)
    39344054            fpsMultiplier = 1;
     4055        if (fpsMultiplier != prior)
     4056            m_parent->SetFrameRate(fps);
    39354057    }
    39364058
    39374059    LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
  • 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/decoderbase.cpp

    diff --git a/mythtv/libs/libmythtv/decoderbase.cpp b/mythtv/libs/libmythtv/decoderbase.cpp
    index b8a2edef83b..788598f119a 100644
    a b using namespace std; 
    1111#include "iso639.h"
    1212#include "DVD/dvdringbuffer.h"
    1313#include "Bluray/bdringbuffer.h"
     14#include "mythcodeccontext.h"
    1415
    1516#define LOC QString("Dec: ")
    1617
    DecoderBase::DecoderBase(MythPlayer *parent, const ProgramInfo &pginfo) 
    4546      video_inverted(false),
    4647      decodeAllSubtitles(false),
    4748      // language preference
    48       languagePreference(iso639_get_language_key_list())
     49      languagePreference(iso639_get_language_key_list()),
     50      // this will be deleted and recreated once decoder is set up
     51      m_mythcodecctx(new MythCodecContext())
    4952{
    5053    ResetTracks();
    5154    tracks[kTrackTypeAudio].push_back(StreamInfo(0, 0, 0, 0, 0));
  • mythtv/libs/libmythtv/decoderbase.h

    diff --git a/mythtv/libs/libmythtv/decoderbase.h b/mythtv/libs/libmythtv/decoderbase.h
    index 608c1e6b336..91c8804c8de 100644
    a b class RingBuffer; 
    1818class TeletextViewer;
    1919class MythPlayer;
    2020class AudioPlayer;
     21class MythCodecContext;
    2122
    2223const int kDecoderProbeBufferSize = 256 * 1024;
    2324
    class DecoderBase 
    270271    bool GetVideoInverted(void) const { return video_inverted; }
    271272    void TrackTotalDuration(bool track) { trackTotalDuration = track; }
    272273    int GetfpsMultiplier(void) { return fpsMultiplier; }
     274    MythCodecContext *GetMythCodecContext(void) { return m_mythcodecctx; }
    273275
    274276  protected:
    275277    virtual int  AutoSelectTrack(uint type);
    class DecoderBase 
    359361    StreamInfo  selectedTrack[(uint)kTrackTypeCount];
    360362    /// language preferences for auto-selection of streams
    361363    vector<int> languagePreference;
     364    MythCodecContext *m_mythcodecctx;
    362365};
    363366
    364367inline int DecoderBase::IncrementTrack(uint type)
  • 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 c21aec44568..d3a17ccfe17 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, 
    411412            avcodec_free_context(&avctx);
    412413        if (avctx)
    413414        {
    414             av_codec_set_pkt_timebase(avctx, stream->time_base);
     415            avctx->pkt_timebase =  stream->time_base;
    415416            streamMap.insert(stream, avctx);
    416417        }
    417418    }
  • 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..ae1c84370a5
    - +  
     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#ifdef USING_VAAPI2
     31#include "vaapi2context.h"
     32#endif
     33
     34extern "C" {
     35    #include "libavutil/pixfmt.h"
     36    #include "libavutil/hwcontext.h"
     37    #include "libavcodec/avcodec.h"
     38    #include "libavfilter/avfilter.h"
     39    #include "libavfilter/buffersink.h"
     40    #include "libavfilter/buffersrc.h"
     41    #include "libavformat/avformat.h"
     42    #include "libavutil/opt.h"
     43    #include "libavutil/buffer.h"
     44}
     45
     46#define LOC QString("MythCodecContext: ")
     47
     48MythCodecContext::MythCodecContext() :
     49    stream(NULL),
     50    buffersink_ctx(NULL),
     51    buffersrc_ctx(NULL),
     52    filter_graph(NULL),
     53    filtersInitialized(false),
     54    hw_frames_ctx(NULL),
     55    player(NULL),
     56    ptsUsed(0),
     57    doublerate(false)
     58{
     59    priorPts[0] = 0;
     60    priorPts[1] = 0;
     61}
     62
     63MythCodecContext::~MythCodecContext()
     64{
     65    CloseFilters();
     66}
     67
     68// static
     69MythCodecContext *MythCodecContext::createMythCodecContext(MythCodecID codec)
     70{
     71    MythCodecContext *mctx = NULL;
     72#ifdef USING_VAAPI2
     73    if (codec_is_vaapi2(codec))
     74        mctx = new Vaapi2Context();
     75#endif
     76    if (!mctx)
     77        mctx = new MythCodecContext();
     78    return mctx;
     79}
     80
     81// static
     82QStringList MythCodecContext::GetDeinterlacers(QString decodername)
     83{
     84    QStringList ret;
     85#ifdef USING_VAAPI2
     86    if (decodername == "vaapi2")
     87    {
     88        ret.append("vaapi2default");
     89        ret.append("vaapi2bob");
     90        ret.append("vaapi2weave");
     91        ret.append("vaapi2motion_adaptive");
     92        ret.append("vaapi2motion_compensated");
     93        ret.append("vaapi2doubleratedefault");
     94        ret.append("vaapi2doubleratebob");
     95        ret.append("vaapi2doublerateweave");
     96        ret.append("vaapi2doubleratemotion_adaptive");
     97        ret.append("vaapi2doubleratemotion_compensated");
     98
     99/*
     100    Explanation of vaapi2 deinterlacing modes.
     101    "mode", "Deinterlacing mode",
     102        "default", "Use the highest-numbered (and therefore possibly most advanced) deinterlacing algorithm",
     103        "bob", "Use the bob deinterlacing algorithm",
     104        "weave", "Use the weave deinterlacing algorithm",
     105        "motion_adaptive", "Use the motion adaptive deinterlacing algorithm",
     106        "motion_compensated", "Use the motion compensated deinterlacing algorithm",
     107
     108    "rate", "Generate output at frame rate or field rate",
     109        "frame", "Output at frame rate (one frame of output for each field-pair)",
     110        "field", "Output at field rate (one frame of output for each field)",
     111
     112    "auto", "Only deinterlace fields, passing frames through unchanged",
     113        1 = enabled
     114        0 = disabled
     115*/
     116
     117    }
     118#endif
     119    return ret;
     120}
     121// static - Find if a deinterlacer is codec-provided
     122bool MythCodecContext::isCodecDeinterlacer(QString decodername)
     123{
     124    return (decodername.startsWith("vaapi2"));
     125}
     126
     127
     128// Currently this will only set up the filter after an interlaced frame.
     129// If we need other filters apart from deinterlace filters we will
     130// need to make a change here.
     131
     132int MythCodecContext::FilteredReceiveFrame(AVCodecContext *ctx, AVFrame *frame)
     133{
     134    int ret = 0;
     135
     136    while (1)
     137    {
     138        if (filter_graph)
     139        {
     140            ret = av_buffersink_get_frame(buffersink_ctx, frame);
     141            if  (ret >= 0)
     142            {
     143                if (priorPts[0] && ptsUsed == priorPts[1])
     144                {
     145                    frame->pts = priorPts[1] + (priorPts[1] - priorPts[0])/2;
     146                    frame->scte_cc_len = 0;
     147                    frame->atsc_cc_len = 0;
     148                    av_frame_remove_side_data(frame, AV_FRAME_DATA_A53_CC);
     149                }
     150                else
     151                {
     152                    frame->pts = priorPts[1];
     153                    ptsUsed = priorPts[1];
     154                }
     155            }
     156            if  (ret != AVERROR(EAGAIN))
     157                break;
     158        }
     159
     160        // EAGAIN or no filter graph
     161        ret = avcodec_receive_frame(ctx, frame);
     162        if (ret < 0)
     163            break;
     164        priorPts[0]=priorPts[1];
     165        priorPts[1]=frame->pts;
     166        if (frame->interlaced_frame || filter_graph)
     167        {
     168            if (!filtersInitialized
     169              || width != frame->width
     170              || height != frame->height)
     171            {
     172                // bypass any frame of unknown format
     173                if (frame->format < 0)
     174                    break;
     175                ret = InitDeinterlaceFilter(ctx, frame);
     176                if (ret < 0)
     177                {
     178                    LOG(VB_GENERAL, LOG_ERR, LOC + "InitDeinterlaceFilter failed - continue without filters");
     179                    break;
     180                }
     181            }
     182            if (filter_graph)
     183            {
     184                ret = av_buffersrc_add_frame(buffersrc_ctx, frame);
     185                if (ret < 0)
     186                    break;
     187            }
     188            else
     189                break;
     190        }
     191        else
     192            break;
     193    }
     194
     195    return ret;
     196}
     197
     198// Setup or change deinterlacer.
     199// Same usage as VideoOutBase::SetupDeinterlace
     200// enable - true to enable, false to disable
     201// name - empty to use video profile deinterlacers, otherwise
     202//        use the supplied name.
     203// return true if the deinterlacer was found as a hardware deinterlacer.
     204// return false if the deinterlacer is nnt a hardware deinterlacer,
     205//        and a videououtput deinterlacer should be tried instead.
     206
     207bool MythCodecContext::setDeinterlacer(bool enable, QString name)
     208{
     209    QMutexLocker lock(&contextLock);
     210    // Code to disable interlace
     211    if (!enable)
     212    {
     213        if (deinterlacername.isEmpty())
     214            return true;
     215        else
     216        {
     217            deinterlacername.clear();
     218            doublerate = false;
     219            filtersInitialized = false;
     220            return true;
     221        }
     222    }
     223
     224    // Code to enable or change interlace
     225    if (name.isEmpty())
     226    {
     227        if (deinterlacername.isEmpty())
     228        {
     229            VideoOutput *vo = NULL;
     230            VideoDisplayProfile *vdisp_profile = NULL;
     231            if (player)
     232                vo = player->GetVideoOutput();
     233            if (vo)
     234                vdisp_profile = vo->GetProfile();
     235            if (vdisp_profile)
     236                name = vdisp_profile->GetFilteredDeint(QString());
     237        }
     238        else
     239            name = deinterlacername;
     240    }
     241    bool ret = true;
     242    if (!isCodecDeinterlacer(name))
     243        name.clear();
     244
     245    if (name.isEmpty())
     246        ret = false;
     247
     248    if (deinterlacername == name)
     249        return ret;
     250
     251    deinterlacername = name;
     252    doublerate = deinterlacername.contains("doublerate");
     253    filtersInitialized = false;
     254    return ret;
     255}
     256
     257bool MythCodecContext::BestDeint(void)
     258{
     259    deinterlacername.clear();
     260    doublerate = false;
     261    return setDeinterlacer(true);
     262}
     263
     264bool MythCodecContext::FallbackDeint(void)
     265{
     266    return setDeinterlacer(true,GetFallbackDeint());
     267}
     268
     269QString MythCodecContext::GetFallbackDeint(void)
     270{
     271
     272    VideoOutput *vo = NULL;
     273    VideoDisplayProfile *vdisp_profile = NULL;
     274    if (player)
     275        vo = player->GetVideoOutput();
     276    if (vo)
     277        vdisp_profile = vo->GetProfile();
     278    if (vdisp_profile)
     279        return vdisp_profile->GetFallbackDeinterlacer();
     280    return QString();
     281}
     282
     283int MythCodecContext::InitDeinterlaceFilter(AVCodecContext *ctx, AVFrame *frame)
     284{
     285    QMutexLocker lock(&contextLock);
     286    char args[512];
     287    int ret = 0;
     288    CloseFilters();
     289    width = frame->width;
     290    height = frame->height;
     291    filtersInitialized = true;
     292    if (!player || !stream)
     293    {
     294        LOG(VB_GENERAL, LOG_ERR, LOC + "Player or stream is not set up in MythCodecContext");
     295        return -1;
     296    }
     297    if (doublerate && !player->CanSupportDoubleRate())
     298    {
     299        QString request = deinterlacername;
     300        deinterlacername = GetFallbackDeint();
     301        LOG(VB_PLAYBACK, LOG_INFO, LOC
     302          + QString("Deinterlacer %1 requires double rate, switching to %2 instead.")
     303          .arg(request).arg(deinterlacername));
     304        if (!isCodecDeinterlacer(deinterlacername))
     305            deinterlacername.clear();
     306        doublerate = deinterlacername.contains("doublerate");
     307
     308        // if the fallback is a non-vaapi - deinterlace will be turned off
     309        // and the videoout methods can take over.
     310    }
     311    QString filters;
     312    if (isValidDeinterlacer(deinterlacername))
     313        filters = GetDeinterlaceFilter();
     314
     315    if (filters.isEmpty())
     316    {
     317        LOG(VB_GENERAL, LOG_INFO, LOC +
     318            "Disabled hardware decoder based deinterlacer.");
     319        return ret;
     320    }
     321    const AVFilter *buffersrc  = avfilter_get_by_name("buffer");
     322    const AVFilter *buffersink = avfilter_get_by_name("buffersink");
     323    AVFilterInOut *outputs = avfilter_inout_alloc();
     324    AVFilterInOut *inputs  = avfilter_inout_alloc();
     325    AVRational time_base = stream->time_base;
     326    AVBufferSrcParameters* params = NULL;
     327
     328    filter_graph = avfilter_graph_alloc();
     329    if (!outputs || !inputs || !filter_graph)
     330    {
     331        ret = AVERROR(ENOMEM);
     332        goto end;
     333    }
     334
     335    /* buffer video source: the decoded frames from the decoder will be inserted here. */
     336    snprintf(args, sizeof(args),
     337            "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
     338            frame->width, frame->height, frame->format, // ctx->pix_fmt,
     339            time_base.num, time_base.den,
     340            ctx->sample_aspect_ratio.num, ctx->sample_aspect_ratio.den);
     341
     342    // isInterlaced = frame->interlaced_frame;
     343
     344    ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
     345                                       args, NULL, filter_graph);
     346    if (ret < 0)
     347    {
     348        LOG(VB_GENERAL, LOG_ERR, LOC + "avfilter_graph_create_filter failed for buffer source");
     349        goto end;
     350    }
     351
     352    params = av_buffersrc_parameters_alloc();
     353    if (hw_frames_ctx)
     354        av_buffer_unref(&hw_frames_ctx);
     355    hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx);
     356    params->hw_frames_ctx = hw_frames_ctx;
     357
     358    ret = av_buffersrc_parameters_set(buffersrc_ctx, params);
     359
     360    if (ret < 0)
     361    {
     362        LOG(VB_GENERAL, LOG_ERR, LOC + "av_buffersrc_parameters_set failed");
     363        goto end;
     364    }
     365
     366    av_freep(&params);
     367
     368    /* buffer video sink: to terminate the filter chain. */
     369    ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
     370                                       NULL, NULL, filter_graph);
     371    if (ret < 0)
     372    {
     373        LOG(VB_GENERAL, LOG_ERR, LOC + "avfilter_graph_create_filter failed for buffer sink");
     374        goto end;
     375    }
     376
     377    /*
     378     * Set the endpoints for the filter graph. The filter_graph will
     379     * be linked to the graph described by filters_descr.
     380     */
     381
     382    /*
     383     * The buffer source output must be connected to the input pad of
     384     * the first filter described by filters_descr; since the first
     385     * filter input label is not specified, it is set to "in" by
     386     * default.
     387     */
     388    outputs->name       = av_strdup("in");
     389    outputs->filter_ctx = buffersrc_ctx;
     390    outputs->pad_idx    = 0;
     391    outputs->next       = NULL;
     392
     393    /*
     394     * The buffer sink input must be connected to the output pad of
     395     * the last filter described by filters_descr; since the last
     396     * filter output label is not specified, it is set to "out" by
     397     * default.
     398     */
     399    inputs->name       = av_strdup("out");
     400    inputs->filter_ctx = buffersink_ctx;
     401    inputs->pad_idx    = 0;
     402    inputs->next       = NULL;
     403
     404    if ((ret = avfilter_graph_parse_ptr(filter_graph, filters.toLocal8Bit(),
     405                                    &inputs, &outputs,0)) < 0)
     406    {
     407        LOG(VB_GENERAL, LOG_ERR, LOC
     408            + QString("avfilter_graph_parse_ptr failed for %1").arg(filters));
     409        goto end;
     410    }
     411
     412    if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
     413    {
     414        LOG(VB_GENERAL, LOG_ERR, LOC
     415            + QString("avfilter_graph_config failed"));
     416        goto end;
     417    }
     418
     419    LOG(VB_GENERAL, LOG_INFO, LOC +
     420        QString("Enabled hardware decoder based deinterlace filter '%1': <%2>.")
     421            .arg(deinterlacername).arg(filters));
     422end:
     423    if (ret < 0)
     424    {
     425        avfilter_graph_free(&filter_graph);
     426        filter_graph = NULL;
     427        doublerate = false;
     428    }
     429    avfilter_inout_free(&inputs);
     430    avfilter_inout_free(&outputs);
     431
     432    return ret;
     433}
     434
     435void MythCodecContext::CloseFilters()
     436{
     437    avfilter_graph_free(&filter_graph);
     438    filter_graph = NULL;
     439    buffersink_ctx = NULL;
     440    buffersrc_ctx = NULL;
     441    filtersInitialized = false;
     442    ptsUsed = 0;
     443    priorPts[0] = 0;
     444    priorPts[1] = 0;
     445    // isInterlaced = 0;
     446    width = 0;
     447    height = 0;
     448
     449    if (hw_frames_ctx)
     450        av_buffer_unref(&hw_frames_ctx);
     451}
     452 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..234797aeac4
    - +  
     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 MYTHCODECONTEXT_H
     28
     29struct AVCodecContext;
     30struct AVFrame;
     31struct AVStream;
     32struct AVFilterContext;
     33struct AVFilterGraph;
     34struct AVBufferRef;
     35class MythPlayer;
     36
     37#include "mythtvexp.h"
     38#include "mythcodecid.h"
     39
     40class MTV_PUBLIC MythCodecContext
     41{
     42  public:
     43    MythCodecContext(void);
     44    virtual ~MythCodecContext();
     45    static MythCodecContext* createMythCodecContext(MythCodecID codec);
     46    virtual int HwDecoderInit(AVCodecContext * /*ctx*/) { return 0; }
     47    void setStream(AVStream *initStream) { stream = initStream; }
     48    virtual int FilteredReceiveFrame(AVCodecContext *ctx, AVFrame *frame);
     49    static QStringList GetDeinterlacers(QString decodername);
     50    static bool isCodecDeinterlacer(QString decodername);
     51    virtual QStringList GetDeinterlacers(void) { return QStringList(); }
     52    virtual QString GetDeinterlaceFilter() { return QString(); }
     53    void setPlayer(MythPlayer *tPlayer) { player = tPlayer; }
     54    bool setDeinterlacer(bool enable, QString name = QString());
     55    bool isDeinterlacing(void) { return filter_graph != NULL;}
     56    QString getDeinterlacerName(void) { return deinterlacername; }
     57    bool BestDeint(void);
     58    bool FallbackDeint(void);
     59    bool getDoubleRate(void) { return doublerate; }
     60    QString GetFallbackDeint(void);
     61
     62  protected:
     63    virtual bool isValidDeinterlacer(QString /*name*/) { return false; }
     64    int InitDeinterlaceFilter(AVCodecContext *ctx, AVFrame *frame);
     65    void CloseFilters();
     66    AVStream* stream;
     67    AVFilterContext *buffersink_ctx;
     68    AVFilterContext *buffersrc_ctx;
     69    AVFilterGraph *filter_graph;
     70    bool filtersInitialized;
     71    AVBufferRef *hw_frames_ctx;
     72    MythPlayer *player;
     73    int64_t priorPts[2];
     74    int64_t ptsUsed;
     75    int width;
     76    int height;
     77    QString deinterlacername;
     78    QMutex contextLock;
     79    bool doublerate;
     80};
     81
     82#endif // MYTHCODECCONTEXT_H
     83 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..f1b02571f31 100644
    a b using namespace std; 
    5353#include "mythuiactions.h"              // for ACTION_LEFT, ACTION_RIGHT, etc
    5454#include "ringbuffer.h"                 // for RingBuffer, etc
    5555#include "tv_actions.h"                 // for ACTION_BIGJUMPFWD, etc
     56#include "mythcodeccontext.h"
    5657
    5758extern "C" {
    5859#include "vsync.h"
    void MythPlayer::FallbackDeint(void) 
    676677     m_double_process   = false;
    677678
    678679     if (videoOutput)
    679          videoOutput->FallbackDeint();
     680     {
     681        videoOutput->SetupDeinterlace(false);
     682        bool hwset = decoder->GetMythCodecContext()->FallbackDeint();
     683        if (!hwset)
     684            videoOutput->FallbackDeint();
     685     }
    680686}
    681687
    682688void MythPlayer::AutoDeint(VideoFrame *frame, bool allow_lock)
    void MythPlayer::AutoDeint(VideoFrame *frame, bool allow_lock) 
    715721
    716722    if ((m_scan_tracker % 400) == 0)
    717723    {
    718         QString type = (m_scan_tracker < 0) ? "progressive" : "interlaced";
     724        QString type;
     725        //  = (m_scan_tracker < 0) ? "progressive" : "interlaced";
     726        if (m_scan_tracker < 0)
     727        {
     728            if (decoder->GetMythCodecContext()->isDeinterlacing())
     729                type = "codec-deinterlaced";
     730            else
     731                type = "progressive";
     732        }
     733        else
     734            type = "interlaced";
     735
    719736        LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("%1 %2 frames seen.")
    720737                .arg(abs(m_scan_tracker)).arg(type));
    721738    }
    void MythPlayer::SetScanType(FrameScanType scan) 
    763780
    764781    if (interlaced)
    765782    {
    766         m_deint_possible = videoOutput->SetDeinterlacingEnabled(true);
    767         if (!m_deint_possible)
    768         {
    769             LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to enable deinterlacing");
    770             m_scan = scan;
    771             return;
    772         }
     783            m_deint_possible = videoOutput->SetDeinterlacingEnabled(true);
     784            if (!m_deint_possible)
     785            {
     786                LOG(VB_GENERAL, LOG_INFO, LOC + "Unable to enable Video Output based deinterlacing");
     787                m_scan = scan;
     788                return;
     789            }
    773790        if (videoOutput->NeedsDoubleFramerate())
    774791        {
    775792            m_double_framerate = true;
    void MythPlayer::SetScanType(FrameScanType scan) 
    782799            }
    783800        }
    784801        m_double_process = videoOutput->IsExtraProcessingRequired();
    785         LOG(VB_PLAYBACK, LOG_INFO, LOC + "Enabled deinterlacing");
     802        LOG(VB_PLAYBACK, LOG_INFO, LOC + "Enabled Video Output based deinterlacing");
    786803    }
    787804    else
    788805    {
    void MythPlayer::SetScanType(FrameScanType scan) 
    791808            m_double_process = false;
    792809            m_double_framerate = false;
    793810            videoOutput->SetDeinterlacingEnabled(false);
    794             LOG(VB_PLAYBACK, LOG_INFO, LOC + "Disabled deinterlacing");
     811            LOG(VB_PLAYBACK, LOG_INFO, LOC + "Disabled Video Output based deinterlacing");
    795812        }
    796813    }
    797814
    void MythPlayer::SetVideoParams(int width, int height, double fps, 
    849866    m_scan_tracker = (m_scan == kScan_Interlaced) ? 2 : 0;
    850867}
    851868
     869
     870void MythPlayer::SetFrameRate(double fps)
     871{
     872    video_frame_rate = fps;
     873    float temp_speed = (play_speed == 0.0f) ?
     874        audio.GetStretchFactor() : play_speed;
     875    SetFrameInterval(kScan_Progressive,
     876                        1.0 / (video_frame_rate * temp_speed));
     877}
     878
    852879void MythPlayer::SetFileLength(int total, int frames)
    853880{
    854881    totalLength = total;
    void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) 
    18891916        else
    18901917        {
    18911918            dropframe = true;
    1892             dbg = "A/V predict drop frame, ";
     1919            dbg = QString("A/V predict drop frame, refreshrate %1, avsync_predictor %2, diverge %3, ")
     1920            .arg(refreshrate).arg(avsync_predictor).arg(diverge);
    18931921        }
    18941922    }
    18951923
    void MythPlayer::SetBuffering(bool new_buffering) 
    21822210    }
    21832211}
    21842212
     2213// For debugging playback set this to increase the timeout so that
     2214// playback does not fail if stepping through code.
     2215// Set PREBUFFERDEBUG to any value and you will get 30 minutes.
     2216static char *preBufferDebug = getenv("PREBUFFERDEBUG");
     2217
    21852218bool MythPlayer::PrebufferEnoughFrames(int min_buffers)
    21862219{
    21872220    if (!videoOutput)
    bool MythPlayer::PrebufferEnoughFrames(int min_buffers) 
    22472280                audio.Pause(false);
    22482281            }
    22492282        }
    2250         if ((waited_for > 500) && !videoOutput->EnoughFreeFrames())
     2283        int msecs = 500;
     2284        if (preBufferDebug)
     2285            msecs = 1800000;
     2286        if ((waited_for > msecs /*500*/) && !videoOutput->EnoughFreeFrames())
    22512287        {
    22522288            LOG(VB_GENERAL, LOG_NOTICE, LOC +
    22532289                "Timed out waiting for frames, and"
    bool MythPlayer::PrebufferEnoughFrames(int min_buffers) 
    22572293            // to recover from serious problems if frames get leaked.
    22582294            DiscardVideoFrames(true);
    22592295        }
    2260         if (waited_for > 30000) // 30 seconds for internet streamed media
     2296        msecs = 30000;
     2297        if (preBufferDebug)
     2298            msecs = 1800000;
     2299        if (waited_for > msecs /*30000*/) // 30 seconds for internet streamed media
    22612300        {
    22622301            LOG(VB_GENERAL, LOG_ERR, LOC +
    22632302                "Waited too long for decoder to fill video buffers. Exiting..");
    void MythPlayer::ForceDeinterlacer(const QString &overridefilter) 
    23822421    bool normal = play_speed > 0.99f && play_speed < 1.01f && normal_speed;
    23832422    videofiltersLock.lock();
    23842423
    2385     m_double_framerate =
    2386          videoOutput->SetupDeinterlace(true, overridefilter) &&
    2387          videoOutput->NeedsDoubleFramerate();
    2388     m_double_process = videoOutput->IsExtraProcessingRequired();
    2389 
    2390     if (m_double_framerate && (!CanSupportDoubleRate() || !normal))
     2424    bool hwset = decoder->GetMythCodecContext()->setDeinterlacer(true, overridefilter);
     2425    if (hwset)
     2426    {
     2427        m_double_framerate = false;
     2428        m_double_process = false;
     2429        videoOutput->SetupDeinterlace(false);
     2430    }
     2431    else
     2432    {
     2433        m_double_framerate =
     2434            videoOutput->SetupDeinterlace(true, overridefilter) &&
     2435            videoOutput->NeedsDoubleFramerate();
     2436        m_double_process = videoOutput->IsExtraProcessingRequired();
     2437    }
     2438    if ((decoder->GetMythCodecContext()->getDoubleRate() || m_double_framerate)
     2439      && (!CanSupportDoubleRate() || !normal))
    23912440        FallbackDeint();
    23922441
    23932442    videofiltersLock.unlock();
    void MythPlayer::VideoStart(void) 
    24802529    }
    24812530    else if (videoOutput)
    24822531    {
    2483         // Set up deinterlacing in the video output method
    2484         m_double_framerate =
    2485             (videoOutput->SetupDeinterlace(true) &&
    2486              videoOutput->NeedsDoubleFramerate());
    2487 
    2488         m_double_process = videoOutput->IsExtraProcessingRequired();
     2532        bool hwset = decoder->GetMythCodecContext()->setDeinterlacer(true);
     2533        if (hwset)
     2534            videoOutput->SetupDeinterlace(false);
     2535        else
     2536        {
     2537            // Set up deinterlacing in the video output method
     2538            m_double_framerate =
     2539                (videoOutput->SetupDeinterlace(true) &&
     2540                videoOutput->NeedsDoubleFramerate());
    24892541
     2542            m_double_process = videoOutput->IsExtraProcessingRequired();
     2543        }
    24902544        videosync = VideoSync::BestMethod(videoOutput, (uint)rf_int);
    24912545
    24922546        // Make sure video sync can do it
    void MythPlayer::ChangeSpeed(void) 
    38083862                       kScan_Intr2ndField == m_scan);
    38093863
    38103864        videofiltersLock.lock();
    3811         if (m_double_framerate && !play_1)
    3812             videoOutput->FallbackDeint();
    3813         else if (!m_double_framerate && CanSupportDoubleRate() && play_1 &&
    3814                  inter)
    3815             videoOutput->BestDeint();
     3865        bool doublerate = m_double_framerate || decoder->GetMythCodecContext()->getDoubleRate();
     3866        if (doublerate && !play_1)
     3867        {
     3868            bool hwdeint = decoder->GetMythCodecContext()->FallbackDeint();
     3869            if (!hwdeint)
     3870                videoOutput->FallbackDeint();
     3871        }
     3872        else if (!m_double_framerate && CanSupportDoubleRate() && play_1
     3873                && (inter || decoder->GetMythCodecContext()->isDeinterlacing()))
     3874        {
     3875            videoOutput->SetupDeinterlace(false);
     3876            bool hwdeint = decoder->GetMythCodecContext()->BestDeint();
     3877            if (!hwdeint)
     3878                videoOutput->BestDeint();
     3879        }
    38163880        videofiltersLock.unlock();
    3817 
    38183881        m_double_framerate = videoOutput->NeedsDoubleFramerate();
    38193882        m_double_process = videoOutput->IsExtraProcessingRequired();
    38203883    }
    void MythPlayer::SetDecoder(DecoderBase *dec) 
    55025565            decoder = dec;
    55035566        else
    55045567        {
     5568            // Copy the deinterlacer name to the new decoder.
    55055569            DecoderBase *d = decoder;
    55065570            decoder = dec;
     5571            if (d && decoder)
     5572            {
     5573                QString deinterlacer = d->GetMythCodecContext()->getDeinterlacerName();
     5574                decoder->GetMythCodecContext()->setDeinterlacer(true,deinterlacer);
     5575            }
    55075576            delete d;
    55085577        }
    55095578        decoder_change_lock.unlock();
  • mythtv/libs/libmythtv/mythplayer.h

    diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
    index a17364522be..fd4741e1db7 100644
    a b class MTV_PUBLIC MythPlayer 
    166166    void SetVideoResize(const QRect &videoRect);
    167167    void EnableFrameRateMonitor(bool enable = false);
    168168    void ForceDeinterlacer(const QString &override = QString());
     169    void SetFrameRate(double fps);
    169170
    170171    // Gets
    171172    QSize   GetVideoBufferSize(void) const    { return video_dim; }
    class MTV_PUBLIC MythPlayer 
    240241                                int &vw, int &vh, float &ar);
    241242    InteractiveTV *GetInteractiveTV(void);
    242243    VideoOutput *GetVideoOutput(void)       { return videoOutput; }
     244    MythCodecContext *GetMythCodecContext(void) { return decoder->GetMythCodecContext(); }
    243245
    244246    // Title stuff
    245247    virtual bool SwitchTitle(int /*title*/) { return false; }
  • mythtv/libs/libmythtv/tv_play.cpp

    diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp
    index 5ade8680bcc..b381bf6e9fc 100644
    a b using namespace std; 
    7878#include "programtypes.h"
    7979#include "ringbuffer.h"                 // for RingBuffer, etc
    8080#include "tv_actions.h"                 // for ACTION_TOGGLESLEEP, etc
     81#include "mythcodeccontext.h"
    8182
    8283#if ! HAVE_ROUND
    8384#define round(x) ((int) ((x) + 0.5))
    bool TV::MenuItemDisplayPlayback(const MenuItemContext &c) 
    1176711768    }
    1176811769    else if (matchesGroup(actionName, "DEINTERLACER_", category, prefix))
    1176911770    {
    11770         if (m_tvm_scan_type != kScan_Progressive)
     11771        if (m_tvm_scan_type != kScan_Progressive
     11772            || ctx->player->GetMythCodecContext()->isDeinterlacing())
    1177111773        {
    1177211774            foreach (QString deint, m_tvm_deinterlacers)
    1177311775            {
    void TV::PlaybackMenuInit(const MenuBase &menu) 
    1246312465        m_tvm_subs_havetext      = ctx->player->HasTextSubtitles();
    1246412466        m_tvm_subs_forcedon      = ctx->player->GetAllowForcedSubtitles();
    1246512467        ctx->player->GetVideoOutput()->GetDeinterlacers(m_tvm_deinterlacers);
    12466         m_tvm_currentdeinterlacer =
    12467             ctx->player->GetVideoOutput()->GetDeinterlacer();
     12468        QStringList decoderdeints
     12469            = ctx->player->GetMythCodecContext()->GetDeinterlacers();
     12470        m_tvm_deinterlacers.append(decoderdeints);
     12471        m_tvm_currentdeinterlacer
     12472            = ctx->player->GetMythCodecContext()->getDeinterlacerName();
     12473        if (m_tvm_currentdeinterlacer.isEmpty())
     12474            m_tvm_currentdeinterlacer =
     12475                ctx->player->GetVideoOutput()->GetDeinterlacer();
    1246812476        if (m_tvm_visual)
    1246912477            m_tvm_visualisers = ctx->player->GetVisualiserList();
    1247012478        VideoOutput *vo = ctx->player->GetVideoOutput();
  • 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..cf727b02be6
    - +  
     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() :
     40    MythCodecContext()
     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
     119QString Vaapi2Context::GetDeinterlaceFilter()
     120{
     121    // example filter - deinterlace_vaapi=mode=default:rate=frame:auto=1
     122    // example deinterlacername - vaapi2doubleratemotion_compensated
     123    QString ret;
     124    QString rate="frame";
     125    if (!isValidDeinterlacer(deinterlacername))
     126        return ret;
     127    QString filtername = deinterlacername;
     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
     140bool Vaapi2Context::isValidDeinterlacer(QString filtername)
     141{
     142    return filtername.startsWith("vaapi2");
     143}
     144
     145QStringList Vaapi2Context::GetDeinterlacers(void)
     146{
     147    return MythCodecContext::GetDeinterlacers("vaapi2");
     148}
  • 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..05562f0e238
    - +  
     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(void);
     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(void);
     47    virtual bool isValidDeinterlacer(QString /*name*/ );
     48    virtual QStringList GetDeinterlacers(void);
     49
     50};
     51
     52#endif // VAAPI2CONTEXT_H
     53 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..4105b3d2ca7 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#if defined(USING_VAAPI2) && defined(USING_OPENGL_VIDEO)
     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..b055c2a608e 100644
    a b  
    1010#include "openglvideo.h"
    1111#include "mythrender_opengl.h"
    1212#include "mythpainter_ogl.h"
     13#include "mythcodeccontext.h"
    1314
    1415#define LOC      QString("VidOutGL: ")
    1516
    void VideoOutputOpenGL::GetRenderOptions(render_opts &opts, 
    4041        (*opts.safe_renderers)["openmax"].append("opengl");
    4142    if (opts.decoders->contains("mediacodec"))
    4243        (*opts.safe_renderers)["mediacodec"].append("opengl");
     44    if (opts.decoders->contains("vaapi2"))
     45        (*opts.safe_renderers)["vaapi2"].append("opengl");
    4346    opts.priorities->insert("opengl", 65);
    4447
    4548    // lite profile - no colourspace control, GPU deinterlacing
    bool VideoOutputOpenGL::InputChanged(const QSize &video_dim_buf, 
    270273        StopEmbedding();
    271274    }
    272275
    273     if (!codec_is_std(av_codec_id) && !codec_is_mediacodec(av_codec_id))
     276    if (!codec_is_std(av_codec_id)
     277        && !codec_is_mediacodec(av_codec_id)
     278        && !codec_is_vaapi2(av_codec_id))
    274279    {
    275280        LOG(VB_GENERAL, LOG_ERR, LOC + "New video codec is not supported.");
    276281        errorState = kError_Unknown;
    QStringList VideoOutputOpenGL::GetAllowedRenderers( 
    741746    {
    742747        list << "opengl" << "opengl-lite";
    743748    }
    744     else if (codec_is_mediacodec(myth_codec_id) && !getenv("NO_OPENGL"))
     749    else if ((codec_is_mediacodec(myth_codec_id) || codec_is_vaapi2(myth_codec_id))
     750            && !getenv("NO_OPENGL"))
    745751    {
    746752        list << "opengl";
    747753    }
    bool VideoOutputOpenGL::SetupDeinterlace( 
    812818    if (db_vdisp_profile)
    813819        m_deintfiltername = db_vdisp_profile->GetFilteredDeint(overridefilter);
    814820
     821    if (MythCodecContext::isCodecDeinterlacer(m_deintfiltername))
     822        return false;
     823
    815824    if (!m_deintfiltername.contains("opengl"))
    816825    {
    817826        gl_videochain->SetDeinterlacing(false);
  • mythtv/libs/libmythtv/videooutbase.cpp

    diff --git a/mythtv/libs/libmythtv/videooutbase.cpp b/mythtv/libs/libmythtv/videooutbase.cpp
    index 60b2d4fa249..608eeb703b6 100644
    a b  
    1818#include "mythxdisplay.h"
    1919#include "mythavutil.h"
    2020#include "mthreadpool.h"
     21#include "mythcodeccontext.h"
    2122
    2223#ifdef USING_XV
    2324#include "videoout_xv.h"
    bool VideoOutput::SetupDeinterlace(bool interlaced, 
    607608        else
    608609            m_deintfiltername = "";
    609610
    610         m_deintFiltMan = new FilterManager;
    611611        m_deintFilter = NULL;
     612        m_deintFiltMan = NULL;
     613
     614        if (MythCodecContext::isCodecDeinterlacer(m_deintfiltername))
     615        {
     616            m_deinterlacing = false;
     617            return false;
     618        }
     619
     620        m_deintFiltMan = new FilterManager;
    612621
    613622        if (!m_deintfiltername.isEmpty())
    614623        {
  • 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