Ticket #13233: 20180717_1042_partial_livetv_fix.patch

File 20180717_1042_partial_livetv_fix.patch, 51.2 KB (added by Peter Bennett, 3 years ago)

Fix LiveTV crash

  • mythtv/configure

    diff --git a/mythtv/configure b/mythtv/configure
    index 32e0098b9f3..4d9c025e3b4 100755
    a b Advanced options (experts only): 
    135135  --disable-vaapi          disable VAAPI hardware accelerated video decoding
    136136  --disable-openmax        disable OpenMAX hardware accelerated video decoding
    137137  --disable-dxva2          disable hardware accelerated decoding on windows
     138  --disable-mediacodec     disable hardware accelerated decoding on android
    138139  --disable-opengl-video   disable OpenGL based video display
    139140  --disable-opengl-themepainter disable OpenGL based theme painting
    140141  --disable-libass         disable libass SSA/ASS subtitle support
    USING_LIST=' 
    20382039    vaapi
    20392040    vdpau
    20402041    openmax
     2042    mediacodec
    20412043'
    20422044
    20432045CMDLINE_SELECT="
    enable libcrypto 
    27632765enable libdns_sd
    27642766enable libxml2
    27652767enable lirc
     2768enable mediacodec
    27662769enable mheg
    27672770enable mythtranscode
    27682771enable opengl
    ffmpeg_optset extra_cxxflags extra_ldflags target_os 
    69716974ffmpeg_optset pkg_config prefix libdir as objcc dep_cc host_cc
    69726975ffmpeg_optset host_ld
    69736976ffmpeg_optenable cross_compile libmp3lame libx264 libx265 libvpx libxvid
    6974 ffmpeg_optenable vdpau vaapi libxml2 libass dxva2 mediacodec
    6975 ffmpeg_optenable jni libbluray libfontconfig libfreetype libiec61883
     6977ffmpeg_optenable vdpau vaapi libxml2 libass dxva2
     6978ffmpeg_optenable libbluray libfontconfig libfreetype libiec61883
    69766979ffmpeg_optenable crystalhd sdl2 ffplay
     6980if test $target_os = "android"; then
     6981    enabled mediacodec && enable jni
     6982    ffmpeg_optenable mediacodec jni
     6983else
     6984    disable mediacodec
     6985fi
     6986
    69776987ffmpeg_extra_cflags="$extra_cflags -w"
    69786988
    69796989## Call FFmpeg configure here
  • mythtv/external/FFmpeg/libavcodec/mediacodec_sw_buffer.c

    diff --git a/mythtv/external/FFmpeg/libavcodec/mediacodec_sw_buffer.c b/mythtv/external/FFmpeg/libavcodec/mediacodec_sw_buffer.c
    index 92428e85f02..30a53f05b36 100644
    a b void ff_mediacodec_sw_buffer_copy_yuv420_semi_planar(AVCodecContext *avctx, 
    150150        } else if (i == 1) {
    151151            height = avctx->height / 2;
    152152
    153             src += s->slice_height * s->stride;
     153            src += s->height * s->stride;
    154154            src += s->crop_top * s->stride;
    155155            src += s->crop_left;
    156156        }
  • mythtv/libs/libmythtv/avformatdecoder.cpp

    diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
    index 2c3a1985a05..a592bafdb4e 100644
    a b extern "C" { 
    6262#include "vaapicontext.h"
    6363#endif
    6464
     65#ifdef USING_MEDIACODEC
     66#include "mediacodeccontext.h"
     67extern "C" {
     68#include "libavcodec/jni.h"
     69}
     70#include <QtAndroidExtras>
     71#endif
     72
    6573extern "C" {
    6674#include "libavutil/avutil.h"
    6775#include "libavutil/error.h"
    static void myth_av_log(void *ptr, int level, const char* fmt, va_list vl) 
    276284    static QString full_line("");
    277285    static const int msg_len = 255;
    278286    static QMutex string_lock;
    279     uint64_t   verbose_mask  = VB_GENERAL;
    280     LogLevel_t verbose_level = LOG_DEBUG;
     287    uint64_t   verbose_mask  = VB_LIBAV;
     288    LogLevel_t verbose_level = LOG_EMERG;
    281289
    282290    // determine mythtv debug level from av log level
    283291    switch (level)
    284292    {
    285293        case AV_LOG_PANIC:
    286294            verbose_level = LOG_EMERG;
     295            verbose_mask |= VB_GENERAL;
    287296            break;
    288297        case AV_LOG_FATAL:
    289298            verbose_level = LOG_CRIT;
     299            verbose_mask |= VB_GENERAL;
    290300            break;
    291301        case AV_LOG_ERROR:
    292302            verbose_level = LOG_ERR;
    293             verbose_mask |= VB_LIBAV;
    294303            break;
    295         case AV_LOG_DEBUG:
    296         case AV_LOG_VERBOSE:
     304        case AV_LOG_WARNING:
     305            verbose_level = LOG_WARNING;
     306            break;
    297307        case AV_LOG_INFO:
    298             verbose_level = LOG_DEBUG;
    299             verbose_mask |= VB_LIBAV;
     308            verbose_level = LOG_INFO;
    300309            break;
    301         case AV_LOG_WARNING:
    302             verbose_mask |= VB_LIBAV;
     310        case AV_LOG_VERBOSE:
     311        case AV_LOG_DEBUG:
     312        case AV_LOG_TRACE:
     313            verbose_level = LOG_DEBUG;
    303314            break;
    304315        default:
    305316            return;
    void AvFormatDecoder::GetDecoders(render_opts &opts) 
    374385    opts.decoders->append("vaapi");
    375386    (*opts.equiv_decoders)["vaapi"].append("dummy");
    376387#endif
     388#ifdef USING_MEDIACODEC
     389    opts.decoders->append("mediacodec");
     390    (*opts.equiv_decoders)["mediacodec"].append("dummy");
     391#endif
    377392
    378393    PrivateDecoder::GetDecoders(opts);
    379394}
    AvFormatDecoder::AvFormatDecoder(MythPlayer *parent, 
    405420      pts_detected(false),
    406421      reordered_pts_detected(false),
    407422      pts_selected(true),
     423      use_frame_timing(false),
     424      flush_discard(0),
    408425      force_dts_timestamps(false),
    409426      playerFlags(flags),
    410427      video_codec_id(kCodec_NONE),
    AvFormatDecoder::AvFormatDecoder(MythPlayer *parent, 
    433450    audioSamples = (uint8_t *)av_mallocz(AudioOutput::MAX_SIZE_BUFFER);
    434451    ccd608->SetIgnoreTimecode(true);
    435452
    436     bool debug = VERBOSE_LEVEL_CHECK(VB_LIBAV, LOG_ANY);
    437     av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR);
    438453    av_log_set_callback(myth_av_log);
    439454
    440455    audioIn.sample_size = -32; // force SetupAudioStream to run once
    bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool discardFrames) 
    742757
    743758        lastKey = (long long)((newts*(long double)fps)/AV_TIME_BASE);
    744759        framesPlayed = lastKey;
     760        fpsSkip = 0;
    745761        framesRead = lastKey;
    746762
    747763        normalframes = (exactseeks) ? desiredFrame - framesPlayed : 0;
    bool AvFormatDecoder::DoFastForward(long long desiredFrame, bool discardFrames) 
    753769        LOG(VB_GENERAL, LOG_INFO, LOC + "No DTS Seeking Hack!");
    754770        no_dts_hack = true;
    755771        framesPlayed = desiredFrame;
     772        fpsSkip = 0;
    756773        framesRead = desiredFrame;
    757774        normalframes = 0;
    758775    }
    void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames, 
    817834            // enc->internal = NULL and cause a segfault in
    818835            // avcodec_flush_buffers
    819836            if (enc && enc->internal)
     837            {
    820838                avcodec_flush_buffers(enc);
     839                if (fpsMultiplier > 1)
     840                    flush_discard = 4;
     841            }
    821842        }
    822843        if (private_dec)
    823844            private_dec->Reset();
    void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames, 
    844865            if (!no_dts_hack)
    845866            {
    846867                framesPlayed = lastKey;
     868                fpsSkip = 0;
    847869                framesRead = lastKey;
    848870            }
    849871
    extern "C" void HandleStreamChange(void *data) 
    10041026int AvFormatDecoder::FindStreamInfo(void)
    10051027{
    10061028    QMutexLocker lock(avcodeclock);
    1007     // Suppress ffmpeg logging unless "-v libav --loglevel debug"
    1008     if (!VERBOSE_LEVEL_CHECK(VB_LIBAV, LOG_DEBUG))
    1009         silence_ffmpeg_logging = true;
    10101029    int retval = avformat_find_stream_info(ic, NULL);
    10111030    silence_ffmpeg_logging = false;
    10121031    // ffmpeg 3.0 is returning -1 code when there is a channel
    enum AVPixelFormat get_format_vaapi(struct AVCodecContext *avctx, 
    15401559}
    15411560#endif
    15421561
     1562#ifdef USING_MEDIACODEC
     1563static enum AVPixelFormat get_format_mediacodec(struct AVCodecContext *avctx,
     1564                                           const enum AVPixelFormat *valid_fmts)
     1565{
     1566    enum AVPixelFormat ret = *valid_fmts; // default to first
     1567    while (*valid_fmts != AV_PIX_FMT_NONE) {
     1568        if (*valid_fmts == AV_PIX_FMT_YUV420P)
     1569            ret = AV_PIX_FMT_YUV420P;
     1570        valid_fmts++;
     1571    }
     1572    return ret;
     1573}
     1574#endif
     1575
     1576
    15431577static bool IS_DR1_PIX_FMT(const enum AVPixelFormat fmt)
    15441578{
    15451579    switch (fmt)
    void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc, 
    15751609    enc->debug = 0;
    15761610    // enc->error_rate = 0;
    15771611
    1578     AVCodec *codec = avcodec_find_decoder(enc->codec_id);
     1612    const AVCodec *codec = enc->codec;
    15791613
    15801614    if (selectedStream)
    15811615    {
    void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc, 
    16121646        enc->slice_flags     = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
    16131647    }
    16141648    else
     1649#endif
     1650#ifdef USING_MEDIACODEC
     1651    if (CODEC_IS_MEDIACODEC(codec))
     1652    {
     1653        enc->get_format      = get_format_mediacodec;
     1654        enc->slice_flags     = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
     1655    }
     1656    else
    16151657#endif
    16161658    if (codec && codec->capabilities & AV_CODEC_CAP_DR1)
    16171659    {
    void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc, 
    16791721        }
    16801722
    16811723        m_parent->SetKeyframeDistance(keyframedist);
    1682         AVCodec *codec = avcodec_find_decoder(enc->codec_id);
     1724        const AVCodec *codec = enc->codec;
    16831725        QString codecName;
    16841726        if (codec)
    16851727            codecName = codec->name;
    int AvFormatDecoder::ScanStreams(bool novideo) 
    23682410
    23692411            if (averror_count > SEQ_PKT_ERR_MAX)
    23702412                gCodecMap->freeCodecContext(ic->streams[selTrack]);
    2371             AVCodecContext *enc = gCodecMap->getCodecContext(ic->streams[selTrack]);
     2413            AVCodecContext *enc = gCodecMap->getCodecContext(ic->streams[selTrack], codec);
    23722414            StreamInfo si(selTrack, 0, 0, 0, 0);
    23732415
    23742416            tracks[kTrackTypeVideo].push_back(si);
    int AvFormatDecoder::ScanStreams(bool novideo) 
    23932435            uint height = max(dim.height(), 16);
    23942436            QString dec = "ffmpeg";
    23952437            uint thread_count = 1;
    2396             AVCodec *codec1 = avcodec_find_decoder(enc->codec_id);
    23972438            QString codecName;
    2398             if (codec1)
    2399                 codecName = codec1->name;
     2439            if (enc->codec)
     2440                codecName = enc->codec->name;
    24002441            if (enc->framerate.den && enc->framerate.num)
    24012442                fps = float(enc->framerate.num) / float(enc->framerate.den);
    24022443            else
    int AvFormatDecoder::ScanStreams(bool novideo) 
    24732514                }
    24742515#endif // USING_GLVAAPI
    24752516#ifdef USING_DXVA2
    2476                 if (!foundgpudecode)
     2517                if (!foundgpudecoder)
    24772518                {
    24782519                    MythCodecID dxva2_mcid;
    24792520                    AVPixelFormat pix_fmt = AV_PIX_FMT_YUV420P;
    int AvFormatDecoder::ScanStreams(bool novideo) 
    24892530                    }
    24902531                }
    24912532#endif // USING_DXVA2
    2492                 if (foundgpudecoder)
     2533#ifdef USING_MEDIACODEC
     2534                if (!foundgpudecoder)
    24932535                {
    2494                     enc->codec_id = (AVCodecID) myth2av_codecid(video_codec_id);
     2536                    MythCodecID mediacodec_mcid;
     2537                    AVPixelFormat pix_fmt = AV_PIX_FMT_YUV420P;
     2538                    mediacodec_mcid = MediaCodecContext::GetBestSupportedCodec(
     2539                        &codec, dec, mpeg_version(enc->codec_id),
     2540                        pix_fmt);
     2541
     2542                    if (codec_is_mediacodec(mediacodec_mcid))
     2543                    {
     2544                        gCodecMap->freeCodecContext(ic->streams[selTrack]);
     2545                        enc = gCodecMap->getCodecContext(ic->streams[selTrack], codec);
     2546                        video_codec_id = mediacodec_mcid;
     2547                        foundgpudecoder = true;
     2548                    }
    24952549                }
     2550#endif // USING_MEDIACODEC
    24962551            }
    2497 
    24982552            // default to mpeg2
    24992553            if (video_codec_id == kCodec_NONE)
    25002554            {
    int AvFormatDecoder::ScanStreams(bool novideo) 
    25022556                    "Unknown video codec - defaulting to MPEG2");
    25032557                video_codec_id = kCodec_MPEG2;
    25042558            }
    2505             else
    2506             {
    2507                 codec = avcodec_find_decoder(enc->codec_id);
    2508             }
    25092559
    25102560            // Use a PrivateDecoder if allowed in playerFlags AND matched
    25112561            // via the decoder name
    int AvFormatDecoder::ScanStreams(bool novideo) 
    25162566            if (!codec_is_std(video_codec_id))
    25172567                thread_count = 1;
    25182568
     2569            use_frame_timing = false;
     2570            if (! private_dec
     2571                && (codec_is_std(video_codec_id) || codec_is_mediacodec(video_codec_id)))
     2572                use_frame_timing = true;
     2573
    25192574            if (FlagIsSet(kDecodeSingleThreaded))
    25202575                thread_count = 1;
    25212576
    int AvFormatDecoder::ScanStreams(bool novideo) 
    25312586            ScanATSCCaptionStreams(selTrack);
    25322587            UpdateATSCCaptionTracks();
    25332588
    2534             LOG(VB_PLAYBACK, LOG_INFO, LOC +
     2589            LOG(VB_GENERAL, LOG_INFO, LOC +
    25352590                QString("Using %1 for video decoding")
    25362591                .arg(GetCodecDecoderName()));
    25372592
    bool AvFormatDecoder::OpenAVCodec(AVCodecContext *avctx, const AVCodec *codec) 
    26112666{
    26122667    QMutexLocker locker(avcodeclock);
    26132668
     2669#ifdef USING_MEDIACODEC
     2670    if (QString("mediacodec") == codec->wrapper_name)
     2671        av_jni_set_java_vm(QAndroidJniEnvironment::javaVM(), NULL);
     2672#endif
    26142673    int ret = avcodec_open2(avctx, codec, NULL);
    26152674    if (ret < 0)
    26162675    {
    bool AvFormatDecoder::PreProcessVideoPacket(AVStream *curstream, AVPacket *pkt) 
    35363595    return true;
    35373596}
    35383597
     3598// Maximum retries - 500 = 5 seconds
     3599#define PACKET_MAX_RETRIES 5000
     3600#define RETRY_WAIT_TIME 10000   // microseconds
    35393601bool AvFormatDecoder::ProcessVideoPacket(AVStream *curstream, AVPacket *pkt)
    35403602{
     3603    int retryCount = 0;
    35413604    int ret = 0, gotpicture = 0;
    35423605    int64_t pts = 0;
    35433606    AVCodecContext *context = gCodecMap->getCodecContext(curstream);
    bool AvFormatDecoder::ProcessVideoPacket(AVStream *curstream, AVPacket *pkt) 
    35513614    if (pkt->pts != (int64_t)AV_NOPTS_VALUE)
    35523615        pts_detected = true;
    35533616
    3554     avcodeclock->lock();
    3555     if (private_dec)
     3617    bool tryAgain = true;
     3618    bool sentPacket = false;
     3619    int ret2 = 0;
     3620    while (tryAgain)
    35563621    {
    3557         if (QString(ic->iformat->name).contains("avi") || !pts_detected)
    3558             pkt->pts = pkt->dts;
    3559         // TODO disallow private decoders for dvd playback
    3560         // N.B. we do not reparse the frame as it breaks playback for
    3561         // everything but libmpeg2
    3562         ret = private_dec->GetFrame(curstream, mpa_pic, &gotpicture, pkt);
    3563     }
    3564     else
    3565     {
    3566         context->reordered_opaque = pkt->pts;
    3567         //  SUGGESTION
    3568         //  Now that avcodec_decode_video2 is deprecated and replaced
    3569         //  by 2 calls (receive frame and send packet), this could be optimized
    3570         //  into separate routines or separate threads.
    3571         //  Also now that it always consumes a whole buffer some code
    3572         //  in the caller may be able to be optimized.
    3573         ret = avcodec_receive_frame(context, mpa_pic);
    3574         if (ret == 0)
    3575             gotpicture = 1;
    3576         if (ret == AVERROR(EAGAIN))
     3622        tryAgain = false;
     3623        gotpicture = 0;
     3624        avcodeclock->lock();
     3625        if (private_dec)
     3626        {
     3627            if (QString(ic->iformat->name).contains("avi") || !pts_detected)
     3628                pkt->pts = pkt->dts;
     3629            // TODO disallow private decoders for dvd playback
     3630            // N.B. we do not reparse the frame as it breaks playback for
     3631            // everything but libmpeg2
     3632            ret = private_dec->GetFrame(curstream, mpa_pic, &gotpicture, pkt);
     3633            sentPacket = true;
     3634        }
     3635        else
     3636        {
     3637            if (!use_frame_timing)
     3638                context->reordered_opaque = pkt->pts;
     3639
     3640            //  SUGGESTION
     3641            //  Now that avcodec_decode_video2 is deprecated and replaced
     3642            //  by 2 calls (receive frame and send packet), this could be optimized
     3643            //  into separate routines or separate threads.
     3644            //  Also now that it always consumes a whole buffer some code
     3645            //  in the caller may be able to be optimized.
    35773646            ret = 0;
    3578         if (ret == 0)
    3579             ret = avcodec_send_packet(context, pkt);
    3580         // The code assumes that there is always space to add a new
    3581         // packet. This seems risky but has always worked.
    3582         // It should actually check if (ret == AVERROR(EAGAIN)) and then keep
    3583         // the packet around and try it again after processing the frame
    3584         // received here.
    3585     }
    3586     avcodeclock->unlock();
     3647            ret = avcodec_receive_frame(context, mpa_pic);
    35873648
    3588     if (ret < 0)
    3589     {
    3590         char error[AV_ERROR_MAX_STRING_SIZE];
    3591         LOG(VB_GENERAL, LOG_ERR, LOC +
    3592             QString("video decode error: %1 (%2)")
    3593             .arg(av_make_error_string(error, sizeof(error), ret))
    3594             .arg(gotpicture));
    3595         if (ret == AVERROR_INVALIDDATA)
    3596         {
    3597             if (++averror_count > SEQ_PKT_ERR_MAX)
     3649            if (ret == 0)
     3650                gotpicture = 1;
     3651            else
     3652                gotpicture = 0;
     3653            if (ret == AVERROR(EAGAIN))
     3654                ret = 0;
     3655            // If we got a picture do not send the packet until we have
     3656            // all available pictures
     3657            // if (ret == 0 && !gotpicture)
     3658            if (ret==0 && !gotpicture)
    35983659            {
    3599                 // If erroring on GPU assist, try switching to software decode
    3600                 if (codec_is_std(video_codec_id))
    3601                     m_parent->SetErrored(QObject::tr("Video Decode Error"));
     3660                ret2 = avcodec_send_packet(context, pkt);
     3661                if (ret2 == AVERROR(EAGAIN))
     3662                {
     3663                    tryAgain = true;
     3664                    ret2 = 0;
     3665                }
    36023666                else
    3603                     m_streams_changed = true;
     3667                {
     3668                    sentPacket = true;
     3669                }
    36043670            }
    36053671        }
    3606         return false;
     3672        avcodeclock->unlock();
     3673
     3674        if (ret < 0 || ret2 < 0)
     3675        {
     3676            char error[AV_ERROR_MAX_STRING_SIZE];
     3677            if (ret < 0)
     3678            {
     3679                LOG(VB_GENERAL, LOG_ERR, LOC +
     3680                    QString("video avcodec_receive_frame error: %1 (%2) gotpicture:%3")
     3681                    .arg(av_make_error_string(error, sizeof(error), ret))
     3682                    .arg(ret).arg(gotpicture));
     3683            }
     3684            if (ret2 < 0)
     3685                LOG(VB_GENERAL, LOG_ERR, LOC +
     3686                    QString("video avcodec_send_packet error: %1 (%2) gotpicture:%3")
     3687                    .arg(av_make_error_string(error, sizeof(error), ret2))
     3688                    .arg(ret2).arg(gotpicture));
     3689            if (ret == AVERROR_INVALIDDATA || ret2 == AVERROR_INVALIDDATA)
     3690            {
     3691                if (++averror_count > SEQ_PKT_ERR_MAX)
     3692                {
     3693                    // If erroring on GPU assist, try switching to software decode
     3694                    if (codec_is_std(video_codec_id))
     3695                        m_parent->SetErrored(QObject::tr("Video Decode Error"));
     3696                    else
     3697                        m_streams_changed = true;
     3698                }
     3699            }
     3700            if (ret == AVERROR_EXTERNAL || ret2 == AVERROR_EXTERNAL)
     3701                m_streams_changed = true;
     3702            return false;
     3703        }
     3704
     3705        if (tryAgain)
     3706        {
     3707            if (++retryCount > PACKET_MAX_RETRIES)
     3708            {
     3709                LOG(VB_GENERAL, LOG_ERR, LOC +
     3710                    QString("ERROR: Video decode buffering retries exceeded maximum"));
     3711                return false;
     3712            }
     3713            LOG(VB_PLAYBACK, LOG_INFO, LOC +
     3714                QString("Video decode buffering retry"));
     3715            usleep(RETRY_WAIT_TIME);
     3716        }
    36073717    }
    36083718    // averror_count counts sequential errors, so if you have a successful
    36093719    // packet then reset it
    36103720    averror_count = 0;
    3611 
    3612     if (!gotpicture)
     3721    if (gotpicture)
    36133722    {
    3614         return true;
    3615     }
     3723        LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
     3724            QString("video timecodes packet-pts:%1 frame-pts:%2 packet-dts: %3 frame-dts:%4")
     3725                .arg(pkt->pts).arg(mpa_pic->pts).arg(pkt->pts)
     3726                .arg(mpa_pic->pkt_dts));
    36163727
    3617     // Detect faulty video timestamps using logic from ffplay.
    3618     if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
    3619     {
    3620         faulty_dts += (pkt->dts <= last_dts_for_fault_detection);
    3621         last_dts_for_fault_detection = pkt->dts;
    3622     }
    3623     if (mpa_pic->reordered_opaque != (int64_t)AV_NOPTS_VALUE)
    3624     {
    3625         faulty_pts += (mpa_pic->reordered_opaque <= last_pts_for_fault_detection);
    3626         last_pts_for_fault_detection = mpa_pic->reordered_opaque;
    3627         reordered_pts_detected = true;
    3628     }
     3728        if (!use_frame_timing)
     3729        {
     3730            // Detect faulty video timestamps using logic from ffplay.
     3731            if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
     3732            {
     3733                faulty_dts += (pkt->dts <= last_dts_for_fault_detection);
     3734                last_dts_for_fault_detection = pkt->dts;
     3735            }
     3736            if (mpa_pic->reordered_opaque != (int64_t)AV_NOPTS_VALUE)
     3737            {
     3738                faulty_pts += (mpa_pic->reordered_opaque <= last_pts_for_fault_detection);
     3739                last_pts_for_fault_detection = mpa_pic->reordered_opaque;
     3740                reordered_pts_detected = true;
     3741            }
    36293742
    3630     // Explicity use DTS for DVD since they should always be valid for every
    3631     // frame and fixups aren't enabled for DVD.
    3632     // Select reordered_opaque (PTS) timestamps if they are less faulty or the
    3633     // the DTS timestamp is missing. Also use fixups for missing PTS instead of
    3634     // DTS to avoid oscillating between PTS and DTS. Only select DTS if PTS is
    3635     // more faulty or never detected.
    3636     if (force_dts_timestamps)
    3637     {
    3638         if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
    3639             pts = pkt->dts;
    3640         pts_selected = false;
    3641     }
    3642     else if (ringBuffer->IsDVD())
    3643     {
    3644         if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
    3645             pts = pkt->dts;
    3646         pts_selected = false;
    3647     }
    3648     else if (private_dec && private_dec->NeedsReorderedPTS() &&
    3649              mpa_pic->reordered_opaque != (int64_t)AV_NOPTS_VALUE)
    3650     {
    3651         pts = mpa_pic->reordered_opaque;
    3652         pts_selected = true;
    3653     }
    3654     else if (faulty_pts <= faulty_dts && reordered_pts_detected)
    3655     {
    3656         if (mpa_pic->reordered_opaque != (int64_t)AV_NOPTS_VALUE)
    3657             pts = mpa_pic->reordered_opaque;
    3658         pts_selected = true;
     3743            // Explicity use DTS for DVD since they should always be valid for every
     3744            // frame and fixups aren't enabled for DVD.
     3745            // Select reordered_opaque (PTS) timestamps if they are less faulty or the
     3746            // the DTS timestamp is missing. Also use fixups for missing PTS instead of
     3747            // DTS to avoid oscillating between PTS and DTS. Only select DTS if PTS is
     3748            // more faulty or never detected.
     3749            if (force_dts_timestamps)
     3750            {
     3751                if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
     3752                    pts = pkt->dts;
     3753                pts_selected = false;
     3754            }
     3755            else if (ringBuffer->IsDVD())
     3756            {
     3757                if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
     3758                    pts = pkt->dts;
     3759                pts_selected = false;
     3760            }
     3761            else if (private_dec && private_dec->NeedsReorderedPTS() &&
     3762                    mpa_pic->reordered_opaque != (int64_t)AV_NOPTS_VALUE)
     3763            {
     3764                pts = mpa_pic->reordered_opaque;
     3765                pts_selected = true;
     3766            }
     3767            else if (faulty_pts <= faulty_dts && reordered_pts_detected)
     3768            {
     3769                if (mpa_pic->reordered_opaque != (int64_t)AV_NOPTS_VALUE)
     3770                    pts = mpa_pic->reordered_opaque;
     3771                pts_selected = true;
     3772            }
     3773            else if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
     3774            {
     3775                pts = pkt->dts;
     3776                pts_selected = false;
     3777            }
     3778
     3779            LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_DEBUG, LOC +
     3780                QString("video packet timestamps reordered %1 pts %2 dts %3 (%4)")
     3781                    .arg(mpa_pic->reordered_opaque).arg(pkt->pts).arg(pkt->dts)
     3782                    .arg((force_dts_timestamps) ? "dts forced" :
     3783                        (pts_selected) ? "reordered" : "dts"));
     3784
     3785            mpa_pic->reordered_opaque = pts;
     3786        }
     3787        ProcessVideoFrame(curstream, mpa_pic);
    36593788    }
    3660     else if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
     3789    if (!sentPacket)
    36613790    {
    3662         pts = pkt->dts;
    3663         pts_selected = false;
     3791        // MythTV logic expects that only one frame is processed
     3792        // Save the packet for later and return.
     3793        AVPacket *newPkt = new AVPacket;
     3794        memset(newPkt, 0, sizeof(AVPacket));
     3795        av_init_packet(newPkt);
     3796        av_packet_ref(newPkt, pkt);
     3797        storedPackets.prepend(newPkt);
    36643798    }
    3665 
    3666     LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_DEBUG, LOC +
    3667         QString("video packet timestamps reordered %1 pts %2 dts %3 (%4)")
    3668             .arg(mpa_pic->reordered_opaque).arg(pkt->pts).arg(pkt->dts)
    3669             .arg((force_dts_timestamps) ? "dts forced" :
    3670                  (pts_selected) ? "reordered" : "dts"));
    3671 
    3672     mpa_pic->reordered_opaque = pts;
    3673 
    3674     ProcessVideoFrame(curstream, mpa_pic);
    3675 
    36763799    return true;
    36773800}
    36783801
    36793802bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic)
    36803803{
     3804
     3805    if (flush_discard > 0)
     3806    {
     3807        flush_discard--;
     3808        return true;
     3809    }
     3810
    36813811    AVCodecContext *context = gCodecMap->getCodecContext(stream);
    36823812
    36833813    // We need to mediate between ATSC and SCTE data when both are present.  If
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic) 
    37773907        return false;
    37783908    }
    37793909
    3780     long long pts = (long long)(av_q2d(stream->time_base) *
     3910    long long pts;
     3911    if (use_frame_timing)
     3912    {
     3913        pts = mpa_pic->pts;
     3914        if (pts == AV_NOPTS_VALUE)
     3915            pts = mpa_pic->pkt_dts;
     3916        if (pts == AV_NOPTS_VALUE)
     3917        {
     3918            LOG(VB_GENERAL, LOG_ERR, LOC + "No PTS found - unable to process video.");
     3919            return false;
     3920        }
     3921        pts = (long long)(av_q2d(stream->time_base) *
     3922                                pts * 1000);
     3923    }
     3924    else
     3925        pts = (long long)(av_q2d(stream->time_base) *
    37813926                                mpa_pic->reordered_opaque * 1000);
    37823927
    37833928    long long temppts = pts;
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic) 
    37943939        temppts += (long long)(mpa_pic->repeat_pict * 500 / fps);
    37953940    }
    37963941
     3942    // Calculate actual fps from the pts values.
     3943    long long ptsdiff = temppts - lastvpts;
     3944    double calcfps = 1000.0 / ptsdiff;
     3945    if (calcfps < 121.0 && calcfps > 3.0)
     3946    {
     3947        // If fps has doubled due to frame-doubling deinterlace
     3948        // Set fps to double value.
     3949        double fpschange = calcfps / fps;
     3950        if (fpschange > 1.9 && fpschange < 2.1)
     3951            fpsMultiplier = 2;
     3952        if (fpschange > 0.5 && fpschange < 0.6)
     3953            fpsMultiplier = 1;
     3954    }
     3955
    37973956    LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
    37983957        QString("video timecode %1 %2 %3 %4%5")
    3799             .arg(mpa_pic->reordered_opaque).arg(pts).arg(temppts).arg(lastvpts)
     3958            .arg(use_frame_timing ? mpa_pic->pts : mpa_pic->reordered_opaque).arg(pts)
     3959            .arg(temppts).arg(lastvpts)
    38003960            .arg((pts != temppts) ? " fixup" : ""));
    38013961
    38023962    if (picframe)
    bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic) 
    38153975
    38163976    decoded_video_frame = picframe;
    38173977    gotVideoFrame = 1;
    3818     ++framesPlayed;
     3978    if (++fpsSkip >= fpsMultiplier)
     3979    {
     3980        ++framesPlayed;
     3981        fpsSkip = 0;
     3982    }
    38193983
    38203984    lastvpts = temppts;
    38213985    if (!firstvpts && firstvptsinuse)
  • mythtv/libs/libmythtv/avformatdecoder.h

    diff --git a/mythtv/libs/libmythtv/avformatdecoder.h b/mythtv/libs/libmythtv/avformatdecoder.h
    index 486e0bb1bed..c3da8a6cedf 100644
    a b class AvFormatDecoder : public DecoderBase 
    322322    bool pts_detected;
    323323    bool reordered_pts_detected;
    324324    bool pts_selected;
     325    // set use_frame_timing true to utilize the pts values in returned
     326    // frames. Set fale to use deprecated method.
     327    bool use_frame_timing;
     328    int flush_discard;
    325329
    326330    bool force_dts_timestamps;
    327331
  • mythtv/libs/libmythtv/decoderbase.cpp

    diff --git a/mythtv/libs/libmythtv/decoderbase.cpp b/mythtv/libs/libmythtv/decoderbase.cpp
    index 33b1676c60b..b8a2edef83b 100644
    a b DecoderBase::DecoderBase(MythPlayer *parent, const ProgramInfo &pginfo) 
    2020
    2121      current_width(640), current_height(480),
    2222      current_aspect(1.33333), fps(29.97),
     23      fpsMultiplier(1), fpsSkip(0),
    2324      bitrate(4000),
    2425
    2526      framesPlayed(0), framesRead(0),
    void DecoderBase::Reset(bool reset_video_data, bool seek_reset, bool reset_file) 
    8081    {
    8182        ResetPosMap();
    8283        framesPlayed = 0;
     84        fpsSkip = 0;
    8385        framesRead = 0;
    8486        totalDuration = AVRationalInit(0);
    8587        dontSyncPositionMap = false;
    bool DecoderBase::DoRewind(long long desiredFrame, bool discardFrames) 
    581583        return false;
    582584
    583585    framesPlayed = lastKey;
     586    fpsSkip = 0;
    584587    framesRead = lastKey;
    585588
    586589    // Do any Extra frame-by-frame seeking for exactseeks mode
    void DecoderBase::DoFastForwardSeek(long long desiredFrame, bool &needflush) 
    880883        ringBuffer->Seek(e.pos, SEEK_SET);
    881884        needflush    = true;
    882885        framesPlayed = lastKey;
     886        fpsSkip = 0;
    883887        framesRead = lastKey;
    884888    }
    885889}
  • mythtv/libs/libmythtv/decoderbase.h

    diff --git a/mythtv/libs/libmythtv/decoderbase.h b/mythtv/libs/libmythtv/decoderbase.h
    index 3f7eddb8ca5..608c1e6b336 100644
    a b class DecoderBase 
    269269    void SaveTotalFrames(void);
    270270    bool GetVideoInverted(void) const { return video_inverted; }
    271271    void TrackTotalDuration(bool track) { trackTotalDuration = track; }
     272    int GetfpsMultiplier(void) { return fpsMultiplier; }
    272273
    273274  protected:
    274275    virtual int  AutoSelectTrack(uint type);
    class DecoderBase 
    301302    int current_height;
    302303    float current_aspect;
    303304    double fps;
     305    int fpsMultiplier;
     306    int fpsSkip;
    304307    uint bitrate;
    305308
    306309    long long framesPlayed;
  • mythtv/libs/libmythtv/libmythtv.pro

    diff --git a/mythtv/libs/libmythtv/libmythtv.pro b/mythtv/libs/libmythtv/libmythtv.pro
    index 39356bf774f..953fcb4a8b3 100644
    a b  
    11include ( ../../settings.pro )
    22
    33QT += network xml sql widgets
     4android: QT += androidextras
    45
    56TEMPLATE = lib
    67TARGET = mythtv-$$LIBVERSION
    using_frontend { 
    503504        using_opengl_video:DEFINES += USING_GLVAAPI
    504505    }
    505506
     507    using_mediacodec {
     508        DEFINES += USING_MEDIACODEC
     509        HEADERS += mediacodeccontext.h
     510        SOURCES += mediacodeccontext.cpp
     511    }
     512
    506513    # Misc. frontend
    507514    HEADERS += DetectLetterbox.h
    508515    SOURCES += DetectLetterbox.cpp
  • new file mythtv/libs/libmythtv/mediacodeccontext.cpp

    diff --git a/mythtv/libs/libmythtv/mediacodeccontext.cpp b/mythtv/libs/libmythtv/mediacodeccontext.cpp
    new file mode 100644
    index 00000000000..d95de6a01a1
    - +  
     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 "mediacodeccontext.h"
     26
     27#include "mythlogging.h"
     28
     29extern "C" {
     30    #include "libavutil/pixfmt.h"
     31    #include "libavutil/hwcontext.h"
     32    #include "libavcodec/avcodec.h"
     33}
     34
     35#define LOC QString("MEDIACODEC: ")
     36
     37MythCodecID MediaCodecContext::GetBestSupportedCodec(
     38    AVCodec **ppCodec,
     39    const QString &decoder,
     40    uint stream_type,
     41    AVPixelFormat &pix_fmt)
     42{
     43    enum AVHWDeviceType type = AV_HWDEVICE_TYPE_MEDIACODEC;
     44
     45    AVPixelFormat fmt = AV_PIX_FMT_NONE;
     46    if (decoder == "mediacodec")
     47    {
     48        QString decodername = QString((*ppCodec)->name) + "_mediacodec";
     49        if (decodername == "mpeg2video_mediacodec")
     50            decodername = "mpeg2_mediacodec";
     51        AVCodec *newCodec = avcodec_find_decoder_by_name (decodername.toLocal8Bit());
     52        if (newCodec)
     53        {
     54            *ppCodec = newCodec;
     55            fmt = AV_PIX_FMT_MEDIACODEC;
     56        }
     57        else
     58            LOG(VB_PLAYBACK, LOG_INFO, LOC +
     59                QString("Decoder %1 does not support device type %2.")
     60                    .arg((*ppCodec)->name).arg(av_hwdevice_get_type_name(type)));
     61    }
     62
     63    if (fmt == AV_PIX_FMT_NONE)
     64        return (MythCodecID)(kCodec_MPEG1 + (stream_type - 1));
     65    else
     66    {
     67        LOG(VB_PLAYBACK, LOG_INFO, LOC +
     68            QString("Decoder %1 supports device type %2.")
     69                .arg((*ppCodec)->name).arg(av_hwdevice_get_type_name(type)));
     70        pix_fmt = fmt;
     71        return (MythCodecID)(kCodec_MPEG1_MEDIACODEC + (stream_type - 1));
     72    }
     73}
  • new file mythtv/libs/libmythtv/mediacodeccontext.h

    diff --git a/mythtv/libs/libmythtv/mediacodeccontext.h b/mythtv/libs/libmythtv/mediacodeccontext.h
    new file mode 100644
    index 00000000000..7f116487e0b
    - +  
     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 VIDEOOUTOPENGLMEDIACODEC_H
     27#define VIDEOOUTOPENGLMEDIACODEC_H
     28
     29#include "videoout_opengl.h"
     30
     31
     32class MediaCodecContext
     33{
     34  public:
     35    static MythCodecID GetBestSupportedCodec(AVCodec **ppCodec,
     36                                             const QString &decoder,
     37                                             uint stream_type,
     38                                             AVPixelFormat &pix_fmt);
     39};
     40
     41#endif // VIDEOOUTOPENGLMEDIACODEC_H
     42 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 cd9170a648d..b2023512b5f 100644
    a b QString toString(MythCodecID codecid) 
    102102        case kCodec_HEVC_DXVA2:
    103103            return "HEVC DXVA2";
    104104
     105        case kCodec_MPEG1_MEDIACODEC:
     106            return "MPEG1 MEDIACODEC";
     107        case kCodec_MPEG2_MEDIACODEC:
     108            return "MPEG2 MEDIACODEC";
     109        case kCodec_H263_MEDIACODEC:
     110            return "H.263 MEDIACODEC";
     111        case kCodec_MPEG4_MEDIACODEC:
     112            return "MPEG4 MEDIACODEC";
     113        case kCodec_H264_MEDIACODEC:
     114            return "H.264 MEDIACODEC";
     115        case kCodec_VC1_MEDIACODEC:
     116            return "VC1 MEDIACODEC";
     117        case kCodec_WMV3_MEDIACODEC:
     118            return "WMV3 MEDIACODEC";
     119        case kCodec_VP8_MEDIACODEC:
     120            return "VP8 MEDIACODEC";
     121        case kCodec_VP9_MEDIACODEC:
     122            return "VP9 MEDIACODEC";
     123        case kCodec_HEVC_MEDIACODEC:
     124            return "HEVC MEDIACODEC";
     125
    105126        default:
    106127            break;
    107128    }
    int myth2av_codecid(MythCodecID codec_id, bool &vdpau) 
    253274            ret = AV_CODEC_ID_HEVC;
    254275            break;
    255276
     277        case kCodec_MPEG1_MEDIACODEC:
     278            ret = AV_CODEC_ID_MPEG1VIDEO;
     279            break;
     280        case kCodec_MPEG2_MEDIACODEC:
     281            ret = AV_CODEC_ID_MPEG2VIDEO;
     282            break;
     283        case kCodec_H263_MEDIACODEC:
     284            ret = AV_CODEC_ID_H263;
     285            break;
     286        case kCodec_MPEG4_MEDIACODEC:
     287            ret = AV_CODEC_ID_MPEG4;
     288            break;
     289        case kCodec_H264_MEDIACODEC:
     290            ret = AV_CODEC_ID_H264;
     291            break;
     292        case kCodec_VC1_MEDIACODEC:
     293            ret = AV_CODEC_ID_VC1;
     294            break;
     295        case kCodec_WMV3_MEDIACODEC:
     296            ret = AV_CODEC_ID_WMV3;
     297            break;
     298        case kCodec_VP8_MEDIACODEC:
     299            ret = AV_CODEC_ID_VP8;
     300            break;
     301        case kCodec_VP9_MEDIACODEC:
     302            ret = AV_CODEC_ID_VP9;
     303            break;
     304        case kCodec_HEVC_MEDIACODEC:
     305            ret = AV_CODEC_ID_HEVC;
     306            break;
     307
    256308        default:
    257309            LOG(VB_GENERAL, LOG_ERR,
    258310                QString("Error: MythCodecID %1 has not been "
    QString get_encoding_type(MythCodecID codecid) 
    303355        case kCodec_MPEG1_VDPAU:
    304356        case kCodec_MPEG1_VAAPI:
    305357        case kCodec_MPEG1_DXVA2:
     358        case kCodec_MPEG1_MEDIACODEC:
    306359        case kCodec_MPEG2:
    307360        case kCodec_MPEG2_VDPAU:
    308361        case kCodec_MPEG2_VAAPI:
    309362        case kCodec_MPEG2_DXVA2:
     363        case kCodec_MPEG2_MEDIACODEC:
    310364            return "MPEG-2";
    311365
    312366        case kCodec_H263:
    313367        case kCodec_H263_VDPAU:
    314368        case kCodec_H263_VAAPI:
    315369        case kCodec_H263_DXVA2:
     370        case kCodec_H263_MEDIACODEC:
    316371            return "H.263";
    317372
    318373        case kCodec_NUV_MPEG4:
    QString get_encoding_type(MythCodecID codecid) 
    320375        case kCodec_MPEG4_VDPAU:
    321376        case kCodec_MPEG4_VAAPI:
    322377        case kCodec_MPEG4_DXVA2:
     378        case kCodec_MPEG4_MEDIACODEC:
    323379            return "MPEG-4";
    324380
    325381        case kCodec_H264:
    326382        case kCodec_H264_VDPAU:
    327383        case kCodec_H264_VAAPI:
    328384        case kCodec_H264_DXVA2:
     385        case kCodec_H264_MEDIACODEC:
    329386            return "H.264";
    330387
    331388        case kCodec_VC1:
    332389        case kCodec_VC1_VDPAU:
    333390        case kCodec_VC1_VAAPI:
    334391        case kCodec_VC1_DXVA2:
     392        case kCodec_VC1_MEDIACODEC:
    335393            return "VC-1";
    336394
    337395        case kCodec_WMV3:
    338396        case kCodec_WMV3_VDPAU:
    339397        case kCodec_WMV3_VAAPI:
    340398        case kCodec_WMV3_DXVA2:
     399        case kCodec_WMV3_MEDIACODEC:
    341400            return "WMV3";
    342401
    343402        case kCodec_VP8:
    344403        case kCodec_VP8_VDPAU:
    345404        case kCodec_VP8_VAAPI:
    346405        case kCodec_VP8_DXVA2:
     406        case kCodec_VP8_MEDIACODEC:
    347407            return "VP8";
    348408
    349409        case kCodec_VP9:
    350410        case kCodec_VP9_VDPAU:
    351411        case kCodec_VP9_VAAPI:
    352412        case kCodec_VP9_DXVA2:
     413        case kCodec_VP9_MEDIACODEC:
    353414            return "VP8";
    354415
    355416        case kCodec_HEVC:
    356417        case kCodec_HEVC_VDPAU:
    357418        case kCodec_HEVC_VAAPI:
    358419        case kCodec_HEVC_DXVA2:
     420        case kCodec_HEVC_MEDIACODEC:
    359421            return "HEVC";
    360422
    361423        case kCodec_NONE:
    QString get_encoding_type(MythCodecID codecid) 
    363425        case kCodec_VDPAU_END:
    364426        case kCodec_VAAPI_END:
    365427        case kCodec_DXVA2_END:
     428        case kCodec_MEDIACODEC_END:
    366429            return QString();
    367430    }
    368431
    QString get_decoder_name(MythCodecID codec_id) 
    380443    if (codec_is_dxva2(codec_id))
    381444        return "dxva2";
    382445
     446    if (codec_is_mediacodec(codec_id))
     447        return "mediacodec";
     448
    383449    return "ffmpeg";
    384450}
  • mythtv/libs/libmythtv/mythcodecid.h

    diff --git a/mythtv/libs/libmythtv/mythcodecid.h b/mythtv/libs/libmythtv/mythcodecid.h
    index 92466df9b8c..ce3620467d9 100644
    a b typedef enum 
    7575    kCodec_HEVC_DXVA2,
    7676
    7777    kCodec_DXVA2_END,
     78
     79    kCodec_MEDIACODEC_BEGIN = kCodec_DXVA2_END,
     80
     81    kCodec_MPEG1_MEDIACODEC,
     82    kCodec_MPEG2_MEDIACODEC,
     83    kCodec_H263_MEDIACODEC,
     84    kCodec_MPEG4_MEDIACODEC,
     85    kCodec_H264_MEDIACODEC,
     86    kCodec_VC1_MEDIACODEC,
     87    kCodec_WMV3_MEDIACODEC,
     88    kCodec_VP8_MEDIACODEC,
     89    kCodec_VP9_MEDIACODEC,
     90    kCodec_HEVC_MEDIACODEC,
     91
     92    kCodec_MEDIACODEC_END,
     93
    7894} MythCodecID;
    7995
    8096// MythCodecID convenience functions
    typedef enum 
    95111                               ((id == kCodec_H264_DXVA2)  ||   \
    96112                                (id == kCodec_MPEG2_DXVA2) ||   \
    97113                                (id == kCodec_VC1_DXVA2)))
     114#define codec_is_mediacodec(id) ((id > kCodec_MEDIACODEC_BEGIN) &&     \
     115                               (id < kCodec_MEDIACODEC_END))
     116
     117#define codec_sw_copy(id) (codec_is_std(id) || codec_is_mediacodec(id))
    98118
    99119QString get_encoding_type(MythCodecID codecid);
    100120QString get_decoder_name(MythCodecID codec_id);
    int mpeg_version(int codec_id); 
    130150#define CODEC_IS_DXVA2(codec, enc) (0)
    131151#endif
    132152
     153#ifdef USING_MEDIACODEC
     154#define CODEC_IS_MEDIACODEC(codec) (codec && (QString("mediacodec") == codec->wrapper_name))
     155#else
     156#define CODEC_IS_MEDIACODEC(codec) (0)
     157#endif
     158
    133159#define CODEC_IS_HWACCEL(codec, enc) (CODEC_IS_VDPAU(codec)      ||     \
    134160                                      CODEC_IS_VAAPI(codec, enc) ||     \
    135                                       CODEC_IS_DXVA2(codec, enc))
     161                                      CODEC_IS_DXVA2(codec, enc) ||    \
     162                                      CODEC_IS_MEDIACODEC(codec))
    136163
    137164#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 1fa28968898..885701d0ac9 100644
    a b MythPlayer::MythPlayer(PlayerFlags flags) 
    204204      next_play_speed(1.0f),        next_normal_speed(true),
    205205      play_speed(1.0f),             normal_speed(true),
    206206      frame_interval((int)(1000000.0f / 30)), m_frame_interval(0),
     207      m_fpsMultiplier(1),
    207208      ffrew_skip(1),ffrew_adjust(0),
    208209      // Audio and video synchronization stuff
    209210      videosync(NULL),              avsync_delay(0),
    int MythPlayer::NextCaptionTrack(int mode) 
    17471748
    17481749void MythPlayer::SetFrameInterval(FrameScanType scan, double frame_period)
    17491750{
    1750     frame_interval = (int)(1000000.0f * frame_period + 0.5f);
     1751    if (decoder)
     1752        m_fpsMultiplier = decoder->GetfpsMultiplier();
     1753    frame_interval = (int)(1000000.0f * frame_period + 0.5f)
     1754      / m_fpsMultiplier;
    17511755    if (!avsync_predictor_enabled)
    17521756        avsync_predictor = 0;
    17531757    avsync_predictor_enabled = false;
    void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) 
    19401944        if (!player_ctx->IsPBP() || player_ctx->IsPrimaryPBP())
    19411945        {
    19421946            LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
    1943                 LOC + QString("AVSync waitforframe %1 %2")
    1944                     .arg(avsync_adjustment).arg(m_double_framerate));
     1947                LOC + QString("AVSync waitforframe %1 %2 %3")
     1948                    .arg(frameDelay).arg(avsync_adjustment).arg(m_double_framerate));
    19451949            vsync_delay_clock = videosync->WaitForFrame(frameDelay, avsync_adjustment + repeat_delay);
    19461950        }
    19471951        else
    void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay) 
    19791983            osdLock.unlock();
    19801984            // Display the second field
    19811985            if (!player_ctx->IsPBP() || player_ctx->IsPrimaryPBP())
     1986            {
     1987                LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
     1988                    LOC + QString("AVSync waitforframe %1 %2 %3")
     1989                        .arg(frameDelay).arg(avsync_adjustment).arg(m_double_framerate));
    19821990                vsync_delay_clock = videosync->WaitForFrame(frameDelay, avsync_adjustment);
     1991            }
    19831992            videoOutput->Show(ps);
    19841993        }
    19851994
    void MythPlayer::DisplayNormalFrame(bool check_prebuffer) 
    23042313    // Check aspect ratio
    23052314    CheckAspectRatio(frame);
    23062315
     2316    if (decoder && m_fpsMultiplier != decoder->GetfpsMultiplier())
     2317        UpdateFFRewSkip();
     2318
    23072319    // Player specific processing (dvd, bd, mheg etc)
    23082320    PreProcessNormalFrame();
    23092321
    bool MythPlayer::UpdateFFRewSkip(void) 
    37373749    if (play_speed >= 0.0f && play_speed <= 3.0f)
    37383750    {
    37393751        skip_changed = (ffrew_skip != 1);
    3740         frame_interval = (int) (1000000.0f / video_frame_rate / temp_speed);
     3752        if (decoder)
     3753            m_fpsMultiplier = decoder->GetfpsMultiplier();
     3754        frame_interval = (int) (1000000.0f / video_frame_rate / temp_speed)
     3755          / m_fpsMultiplier;
    37413756        ffrew_skip = (play_speed != 0.0f);
    37423757    }
    37433758    else
  • mythtv/libs/libmythtv/mythplayer.h

    diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
    index 7fe3bb3cec4..a17364522be 100644
    a b class MTV_PUBLIC MythPlayer 
    810810    bool       normal_speed;
    811811    int        frame_interval;///< always adjusted for play_speed
    812812    int        m_frame_interval;///< used to detect changes to frame_interval
     813    int        m_fpsMultiplier;///< used to detect changes
    813814
    814815    int        ffrew_skip;
    815816    int        ffrew_adjust;
  • mythtv/libs/libmythtv/videobuffers.cpp

    diff --git a/mythtv/libs/libmythtv/videobuffers.cpp b/mythtv/libs/libmythtv/videobuffers.cpp
    index e20c13d2772..92620924ca9 100644
    a b extern "C" { 
    1515#include "compat.h"
    1616#include "mythlogging.h"
    1717
    18 #define TRY_LOCK_SPINS                 100
    19 #define TRY_LOCK_SPINS_BEFORE_WARNING   10
    20 #define TRY_LOCK_SPIN_WAIT             100 /* usec */
     18#define TRY_LOCK_SPINS                 2000
     19#define TRY_LOCK_SPINS_BEFORE_WARNING  9999
     20#define TRY_LOCK_SPIN_WAIT             1000 /* usec */
    2121
    2222int next_dbg_str = 0;
    2323
    VideoFrame *VideoBuffers::GetNextFreeFrame(BufferType enqueue_to) 
    289289
    290290        if (tries >= TRY_LOCK_SPINS)
    291291        {
     292            LOG(VB_GENERAL, LOG_ERR, QString("GetNextFreeFrame: "
     293            "available:%1 used:%2 limbo:%3 pause:%4 displayed:%5 decode:%6 finished:%7")
     294            .arg(available.size()).arg(used.size()).arg(limbo.size()).arg(pause.size()).arg(displayed.size()).arg(decode.size()).arg(finished.size()));
    292295            LOG(VB_GENERAL, LOG_ERR,
    293296                QString("GetNextFreeFrame() unable to "
    294297                        "lock frame %1 times. Discarding Frames.")
  • mythtv/libs/libmythtv/videodisplayprofile.cpp

    diff --git a/mythtv/libs/libmythtv/videodisplayprofile.cpp b/mythtv/libs/libmythtv/videodisplayprofile.cpp
    index 4aec35f421d..700ee3bb990 100644
    a b QString VideoDisplayProfile::GetDecoderName(const QString &decoder) 
    851851        dec_name["vaapi"]    = QObject::tr("VAAPI acceleration");
    852852        dec_name["dxva2"]    = QObject::tr("Windows hardware acceleration");
    853853        dec_name["vda"]      = QObject::tr("Mac VDA hardware acceleration");
     854        dec_name["mediacodec"] = QObject::tr("Android MediaCodec decoder");
    854855    }
    855856
    856857    QString ret = decoder;
    QString VideoDisplayProfile::GetDecoderHelp(QString decoder) 
    907908            "Openmax will use the graphics hardware to "
    908909            "accelerate video decoding on Raspberry Pi. ");
    909910
     911    if (decoder == "mediacodec")
     912        msg += QObject::tr(
     913            "Mediacodec will use the graphics hardware to "
     914            "accelerate video decoding on Android. ");
     915
    910916    return msg;
    911917}
    912918
    void VideoDisplayProfile::CreateProfiles(const QString &hostname) 
    14531459                      "");
    14541460    }
    14551461#endif
     1462
     1463#ifdef USING_MEDIACODEC
     1464    if (!profiles.contains("MediaCodec Normal")) {
     1465        (void) QObject::tr("MediaCodec Normal",
     1466                           "Sample: MediaCodec Normal");
     1467        groupid = CreateProfileGroup("MediaCodec Normal", hostname);
     1468        CreateProfile(groupid, 1, "", "", "",
     1469                      "mediacodec", 4, true, "opengl",
     1470                      "opengl2", true,
     1471                      "none", "none",
     1472                      "");
     1473    }
     1474#endif
     1475
    14561476}
    14571477
    14581478QStringList VideoDisplayProfile::GetVideoRenderers(const QString &decoder)
  • mythtv/libs/libmythtv/videoout_opengl.cpp

    diff --git a/mythtv/libs/libmythtv/videoout_opengl.cpp b/mythtv/libs/libmythtv/videoout_opengl.cpp
    index af80727f7ef..b689947d738 100644
    a b void VideoOutputOpenGL::GetRenderOptions(render_opts &opts, 
    3838        (*opts.safe_renderers)["crystalhd"].append("opengl");
    3939    if (opts.decoders->contains("openmax"))
    4040        (*opts.safe_renderers)["openmax"].append("opengl");
     41    if (opts.decoders->contains("mediacodec"))
     42        (*opts.safe_renderers)["mediacodec"].append("opengl");
    4143    opts.priorities->insert("opengl", 65);
    4244
    4345    // lite profile - no colourspace control, GPU deinterlacing
    bool VideoOutputOpenGL::InputChanged(const QSize &video_dim_buf, 
    268270        StopEmbedding();
    269271    }
    270272
    271     if (!codec_is_std(av_codec_id))
     273    if (!codec_is_std(av_codec_id) && !codec_is_mediacodec(av_codec_id))
    272274    {
    273275        LOG(VB_GENERAL, LOG_ERR, LOC + "New video codec is not supported.");
    274276        errorState = kError_Unknown;
    bool VideoOutputOpenGL::SetupOpenGL(void) 
    417419                                  window.GetVideoDispDim(), dvr,
    418420                                  window.GetDisplayVideoRect(),
    419421                                  window.GetVideoRect(), true,
    420                                   options, !codec_is_std(video_codec_id));
     422                                  options, !codec_sw_copy(video_codec_id));
    421423    if (success)
    422424    {
    423425        bool temp_deinterlacing = m_deinterlacing;
    void VideoOutputOpenGL::CreatePainter(void) 
    473475bool VideoOutputOpenGL::CreateBuffers(void)
    474476{
    475477    QMutexLocker locker(&gl_context_lock);
    476     vbuffers.Init(31, true, 1, 12, 4, 2);
     478    if (codec_is_mediacodec(video_codec_id))
     479        // vbuffers.Init(4, true, 1, 2, 2, 1);
     480        vbuffers.Init(8, true, 1, 4, 2, 1);
     481    else
     482        vbuffers.Init(31, true, 1, 12, 4, 2);
    477483    return vbuffers.CreateBuffers(FMT_YV12,
    478484                                  window.GetVideoDim().width(),
    479485                                  window.GetVideoDim().height());
    void VideoOutputOpenGL::ProcessFrame(VideoFrame *frame, OSD */*osd*/, 
    525531        gl_valid = true;
    526532    }
    527533
    528     bool sw_frame = codec_is_std(video_codec_id) &&
     534    bool sw_frame = codec_sw_copy(video_codec_id) &&
    529535                    video_codec_id != kCodec_NONE;
    530536    bool deint_proc = m_deinterlacing && (m_deintFilter != NULL);
    531537    OpenGLLocker ctx_lock(gl_context);
    QStringList VideoOutputOpenGL::GetAllowedRenderers( 
    735741    {
    736742        list << "opengl" << "opengl-lite";
    737743    }
     744    else if (codec_is_mediacodec(myth_codec_id) && !getenv("NO_OPENGL"))
     745    {
     746        list << "opengl";
     747    }
    738748
    739749    return list;
    740750}