Ticket #7964: frame-skip-v3.patch

File frame-skip-v3.patch, 13.9 KB (added by jpoet, 14 years ago)

Use a table for show:skip values

  • libs/libmythtv/NuppelVideoPlayer.cpp

    old new NuppelVideoPlayer::NuppelVideoPlayer(boo 
    254254    for (int i = 0; i < MAXTBUFFER; i++)
    255255        txtbuffers[i].buffer = new unsigned char[text_size + 1];
    256256
     257    m_frame_skip = m_frame_show = 0;
     258    m_frame_skip_idx = m_frame_show_idx = 0;
     259
    257260    memset(&CC708DelayedDeletes, 0, sizeof(CC708DelayedDeletes));
    258261}
    259262
    void NuppelVideoPlayer::AutoDeint(VideoF 
    10141017    m_scan_locked  = false;
    10151018}
    10161019
     1020void NuppelVideoPlayer::PredictFrameSkip(FrameScanType scan)
     1021{
     1022    m_frame_skip = m_frame_show = 0;
     1023
     1024    if (play_speed <= 1 || play_speed > 2 || scan != kScan_Progressive)
     1025        return;
     1026
     1027    switch ((int)(play_speed * 100.0 + 0.5))
     1028    {
     1029      case 105:
     1030        m_frame_show = 20;
     1031        m_frame_skip = 1;
     1032        break;
     1033      case 110:
     1034        m_frame_show = 10;
     1035        m_frame_skip = 1;
     1036        break;
     1037      case 115:
     1038        m_frame_show = 5;
     1039        m_frame_skip = 1;
     1040        break;
     1041      case 120:
     1042        m_frame_show = 5;
     1043        m_frame_skip = 1;
     1044        break;
     1045      case 125:
     1046        m_frame_show = 4;
     1047        m_frame_skip = 1;
     1048        break;
     1049      case 130:
     1050        m_frame_show = 4;
     1051        m_frame_skip = 1;
     1052        break;
     1053      case 135:
     1054        m_frame_show = 3;
     1055        m_frame_skip = 1;
     1056        break;
     1057      case 140:
     1058        m_frame_show = 5;
     1059        m_frame_skip = 2;
     1060        break;
     1061      case 145:
     1062        m_frame_show = 5;
     1063        m_frame_skip = 2;
     1064        break;
     1065      case 150:
     1066        m_frame_show = 2;
     1067        m_frame_skip = 1;
     1068        break;
     1069      case 155:
     1070        m_frame_show = 2;
     1071        m_frame_skip = 1;
     1072        break;
     1073      case 160:
     1074        m_frame_show = 5;
     1075        m_frame_skip = 3;
     1076        break;
     1077      case 165:
     1078        m_frame_show = 5;
     1079        m_frame_skip = 3;
     1080        break;
     1081      case 170:
     1082        m_frame_show = 5;
     1083        m_frame_skip = 3;
     1084        break;
     1085      case 175:
     1086        m_frame_show = 5;
     1087        m_frame_skip = 3;
     1088        break;
     1089      case 180:
     1090        m_frame_show = 5;
     1091        m_frame_skip = 3;
     1092        break;
     1093      case 185:
     1094        m_frame_show = 5;
     1095        m_frame_skip = 3;
     1096        break;
     1097      case 190:
     1098        m_frame_show = 5;
     1099        m_frame_skip = 3;
     1100        break;
     1101      case 195:
     1102        m_frame_show = 5;
     1103        m_frame_skip = 3;
     1104        break;
     1105      case 200:
     1106        m_frame_show = 5;
     1107        m_frame_skip = 4;
     1108        break;
     1109      default:
     1110        m_frame_show = 0;
     1111        m_frame_skip = 0;
     1112        break;
     1113    }
     1114
     1115    VERBOSE(VB_PLAYBACK, QString("PredictFrameSkip: speed %1 show %2 skip %3")
     1116            .arg(play_speed).arg(m_frame_show).arg(m_frame_skip));
     1117
     1118    m_frame_skip_idx = m_frame_show_idx = 0;
     1119}
     1120
    10171121void NuppelVideoPlayer::SetScanType(FrameScanType scan)
    10181122{
    10191123    QMutexLocker locker(&videofiltersLock);
    void NuppelVideoPlayer::SetScanType(Fram 
    10371141    {
    10381142        m_scan = scan;
    10391143        videosync->SetFrameInterval(frame_interval, false);
     1144        PredictFrameSkip(scan);
    10401145        return;
    10411146    }
    10421147
    void NuppelVideoPlayer::SetScanType(Fram 
    10841189            (frame_interval>>1) : frame_interval);
    10851190    }
    10861191
     1192    if (m_scan != scan)
     1193        PredictFrameSkip(scan);
     1194
    10871195    m_scan = scan;
    10881196}
    10891197
    void NuppelVideoPlayer::AVSync(void) 
    23772485        ps = kScan_Progressive;
    23782486
    23792487    bool dropframe = false;
    2380     if (diverge < -MAXDIVERGE)
    2381     {
    2382         dropframe = true;
    2383         // If video is way behind of audio, adjust for it...
    2384         QString dbg = QString("Video is %1 frames behind audio (too slow), ")
    2385             .arg(-diverge);
    23862488
    2387         // Reset A/V Sync
    2388         lastsync = true;
    2389 
    2390         if (buffer && !using_null_videoout &&
    2391             videoOutput->hasHWAcceleration() &&
    2392            !videoOutput->IsSyncLocked())
    2393         {
    2394             // If we are using certain hardware decoders, so we've already done
    2395             // the decoding; display the frame, but don't wait for A/V Sync.
    2396             // Excludes HW decoder/render methods that are locked to
    2397             // the vertical sync (e.g. VDPAU)
    2398             videoOutput->PrepareFrame(buffer, kScan_Intr2ndField);
    2399             videoOutput->Show(kScan_Intr2ndField);
    2400             VERBOSE(VB_PLAYBACK, LOC + dbg + "skipping A/V wait.");
     2489    if (m_frame_show > 0)
     2490    {
     2491        if (m_frame_show_idx == m_frame_show)
     2492        {
     2493            if (m_frame_skip_idx++ == m_frame_skip)
     2494            {
     2495                m_frame_show_idx = 1;
     2496                m_frame_skip_idx = 0;
     2497//                VERBOSE(VB_PLAYBACK, QString("SHOW %1").arg(m_frame_show_idx));
     2498            }
     2499            else
     2500            {
     2501//                VERBOSE(VB_PLAYBACK, QString("SKIP %1").arg(m_frame_skip_idx));;
     2502                dropframe = true;
     2503                lastsync = true;
     2504            }
    24012505        }
    24022506        else
    24032507        {
    2404             // If we are using software decoding, skip this frame altogether.
    2405             VERBOSE(VB_PLAYBACK, LOC + dbg + "dropping frame to catch up.");
     2508            ++m_frame_show_idx;
     2509//            VERBOSE(VB_PLAYBACK, QString("SHOW %1").arg(m_frame_show_idx));
    24062510        }
    24072511    }
    2408     else if (!using_null_videoout)
    2409     {
    2410         // if we get here, we're actually going to do video output
    2411         if (buffer)
    2412             videoOutput->PrepareFrame(buffer, ps);
    24132512
    2414         VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2")
    2415                 .arg(avsync_adjustment).arg(m_double_framerate));
    2416         videosync->WaitForFrame(avsync_adjustment + repeat_delay);
    2417         VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show");
    2418         if (!resetvideo)
    2419             videoOutput->Show(ps);
    2420 
    2421         if (videoOutput->IsErrored())
     2513    if (!dropframe)
     2514    {
     2515        if (diverge < -MAXDIVERGE)
    24222516        {
    2423             VERBOSE(VB_IMPORTANT, "NVP: Error condition detected "
    2424                     "in videoOutput after Show(), aborting playback.");
    2425             SetErrored(QObject::tr("Serious error detected in Video Output"));
    2426             return;
     2517            dropframe = true;
     2518            // If video is way behind of audio, adjust for it...
     2519            QString dbg = QString("Video is %1 frames behind audio (too slow), ")
     2520                          .arg(-diverge);
     2521
     2522            // Reset A/V Sync
     2523            lastsync = true;
     2524
     2525            if (buffer && !using_null_videoout &&
     2526                videoOutput->hasHWAcceleration() &&
     2527                !videoOutput->IsSyncLocked())
     2528            {
     2529                // If we are using certain hardware decoders, so we've already done
     2530                // the decoding; display the frame, but don't wait for A/V Sync.
     2531                // Excludes HW decoder/render methods that are locked to
     2532                // the vertical sync (e.g. VDPAU)
     2533                videoOutput->PrepareFrame(buffer, kScan_Intr2ndField);
     2534                videoOutput->Show(kScan_Intr2ndField);
     2535                VERBOSE(VB_PLAYBACK, LOC + dbg + "skipping A/V wait.");
     2536            }
     2537            else
     2538            {
     2539                // If we are using software decoding, skip this frame altogether.
     2540                VERBOSE(VB_PLAYBACK, LOC + dbg + "dropping frame to catch up.");
     2541            }
    24272542        }
    2428 
    2429         if (m_double_framerate)
     2543        else if (!using_null_videoout)
    24302544        {
    2431             //second stage of deinterlacer processing
    2432             ps = (kScan_Intr2ndField == ps) ?
    2433                 kScan_Interlaced : kScan_Intr2ndField;
    2434 
    2435             if (m_double_process && ps != kScan_Progressive)
    2436             {
    2437                 videofiltersLock.lock();
    2438                 if (player_ctx->buffer->isDVD() &&
    2439                     player_ctx->buffer->DVD()->InStillFrame() &&
    2440                     videoOutput->ValidVideoFrames() < 3)
    2441                 {
    2442                     videoOutput->ProcessFrame(buffer, NULL, NULL,
    2443                                               pip_players, ps);
    2444                 }
    2445                 else
     2545            // if we get here, we're actually going to do video output
     2546            if (buffer)
     2547                videoOutput->PrepareFrame(buffer, ps);
     2548
     2549            VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2")
     2550                    .arg(avsync_adjustment).arg(m_double_framerate));
     2551            videosync->WaitForFrame(avsync_adjustment + repeat_delay);
     2552            VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show");
     2553            if (!resetvideo)
     2554                videoOutput->Show(ps);
     2555
     2556            if (videoOutput->IsErrored())
     2557            {
     2558                VERBOSE(VB_IMPORTANT, "NVP: Error condition detected "
     2559                        "in videoOutput after Show(), aborting playback.");
     2560                SetErrored(QObject::tr("Serious error detected in Video Output"));
     2561                return;
     2562            }
     2563
     2564            if (m_double_framerate)
     2565            {
     2566                //second stage of deinterlacer processing
     2567                ps = (kScan_Intr2ndField == ps) ?
     2568                     kScan_Interlaced : kScan_Intr2ndField;
     2569
     2570                if (m_double_process && ps != kScan_Progressive)
    24462571                {
    2447                     videoOutput->ProcessFrame(
    2448                         buffer, osd, videoFilters, pip_players, ps);
     2572                    videofiltersLock.lock();
     2573                    if (player_ctx->buffer->isDVD() &&
     2574                        player_ctx->buffer->DVD()->InStillFrame() &&
     2575                        videoOutput->ValidVideoFrames() < 3)
     2576                    {
     2577                        videoOutput->ProcessFrame(buffer, NULL, NULL,
     2578                                                  pip_players, ps);
     2579                    }
     2580                    else
     2581                    {
     2582                        videoOutput->ProcessFrame(
     2583                                                  buffer, osd, videoFilters, pip_players, ps);
     2584                    }
     2585                    videofiltersLock.unlock();
    24492586                }
    2450                 videofiltersLock.unlock();
    2451             }
    24522587
    2453             if (buffer)
    2454                 videoOutput->PrepareFrame(buffer, ps);
     2588                if (buffer)
     2589                    videoOutput->PrepareFrame(buffer, ps);
    24552590
    2456             // Display the second field
    2457             videosync->AdvanceTrigger();
     2591                // Display the second field
     2592                videosync->AdvanceTrigger();
    24582593#ifdef NEW_AVSYNC
    2459             videosync->WaitForFrame(avsync_adjustment);
     2594                videosync->WaitForFrame(avsync_adjustment);
    24602595#else
    2461             videosync->WaitForFrame(0);
     2596                videosync->WaitForFrame(0);
    24622597#endif
    2463             if (!resetvideo)
    2464             {
    2465                 videoOutput->Show(ps);
     2598                if (!resetvideo)
     2599                {
     2600                    videoOutput->Show(ps);
     2601                }
    24662602            }
    2467         }
    24682603
    2469         repeat_delay = frame_interval * buffer->repeat_pict * 0.5;
     2604            repeat_delay = frame_interval * buffer->repeat_pict * 0.5;
    24702605
    2471         if (repeat_delay)
    2472             VERBOSE(VB_TIMESTAMP, QString("A/V repeat_pict, adding %1 repeat "
    2473                     "delay").arg(repeat_delay));
    2474     }
    2475     else
    2476     {
    2477         videosync->WaitForFrame(0);
     2606            if (repeat_delay)
     2607                VERBOSE(VB_TIMESTAMP,
     2608                        QString("A/V repeat_pict, adding %1 repeat "
     2609                                "delay").arg(repeat_delay));
     2610        }
     2611        else
     2612        {
     2613            videosync->WaitForFrame(0);
     2614        }
    24782615    }
    24792616
    24802617    if (output_jmeter && output_jmeter->RecordCycleTime())
    24812618    {
    24822619        VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, QString("A/V avsync_delay: %1, "
    2483                 "avsync_avg: %2, warpfactor: %3, warpfactor_avg: %4")
     2620                                                  "avsync_avg: %2, warpfactor: %3, warpfactor_avg: %4")
    24842621                .arg(avsync_delay / 1000).arg(avsync_avg / 1000)
    24852622                .arg(warpfactor).arg(warpfactor_avg));
    24862623    }
    void NuppelVideoPlayer::AVSync(void) 
    25122649        audio_lock.unlock();
    25132650#if 0
    25142651        VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, QString(
    2515                     "A/V timecodes audio %1 video %2 frameinterval %3 "
    2516                     "avdel %4 avg %5 tcoffset %6")
     2652                                                  "A/V timecodes audio %1 video %2 frameinterval %3 "
     2653                                                  "avdel %4 avg %5 tcoffset %6")
    25172654                .arg(currentaudiotime)
    25182655                .arg(buffer->timecode)
    25192656                .arg(frame_interval)
    25202657                .arg(buffer->timecode - currentaudiotime)
    25212658                .arg(avsync_avg)
    25222659                .arg(tc_wrap[TC_AUDIO])
    2523                  );
     2660                );
    25242661#endif
    25252662        if (currentaudiotime != 0 && buffer->timecode != 0)
    25262663        { // currentaudiotime == 0 after a seek
    bool NuppelVideoPlayer::StartPlaying(boo 
    35503687
    35513688            play_speed = next_play_speed;
    35523689            normal_speed = next_normal_speed;
     3690
    35533691            VERBOSE(VB_PLAYBACK, LOC + "Changing speed to " << play_speed);
    35543692
     3693            PredictFrameSkip(m_scan);
     3694
    35553695            if (play_speed == 0.0)
    35563696            {
    35573697                DoPause();
  • libs/libmythtv/NuppelVideoPlayer.h

    old new class MPUBLIC NuppelVideoPlayer : public 
    431431    FrameScanType detectInterlace(FrameScanType newScan, FrameScanType scan,
    432432                                  float fps, int video_height);
    433433    void AutoDeint(VideoFrame*);
     434    void PredictFrameSkip(FrameScanType scan);
    434435
    435436    // Private Sets
    436437    void SetPlayingInfo(const ProgramInfo &pginfo);
    class MPUBLIC NuppelVideoPlayer : public 
    805806    bool       audio_paused;
    806807    int        repeat_delay;
    807808
     809    int        m_frame_skip;
     810    int        m_frame_show;
     811    int        m_frame_skip_idx;
     812    int        m_frame_show_idx;
     813
    808814    // Audio warping stuff
    809815    float      warpfactor;
    810816    float      warpfactor_avg;