Ticket #7964: frame-skip-v3.patch
File frame-skip-v3.patch, 13.9 KB (added by , 14 years ago) |
---|
-
libs/libmythtv/NuppelVideoPlayer.cpp
old new NuppelVideoPlayer::NuppelVideoPlayer(boo 254 254 for (int i = 0; i < MAXTBUFFER; i++) 255 255 txtbuffers[i].buffer = new unsigned char[text_size + 1]; 256 256 257 m_frame_skip = m_frame_show = 0; 258 m_frame_skip_idx = m_frame_show_idx = 0; 259 257 260 memset(&CC708DelayedDeletes, 0, sizeof(CC708DelayedDeletes)); 258 261 } 259 262 … … void NuppelVideoPlayer::AutoDeint(VideoF 1014 1017 m_scan_locked = false; 1015 1018 } 1016 1019 1020 void 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 1017 1121 void NuppelVideoPlayer::SetScanType(FrameScanType scan) 1018 1122 { 1019 1123 QMutexLocker locker(&videofiltersLock); … … void NuppelVideoPlayer::SetScanType(Fram 1037 1141 { 1038 1142 m_scan = scan; 1039 1143 videosync->SetFrameInterval(frame_interval, false); 1144 PredictFrameSkip(scan); 1040 1145 return; 1041 1146 } 1042 1147 … … void NuppelVideoPlayer::SetScanType(Fram 1084 1189 (frame_interval>>1) : frame_interval); 1085 1190 } 1086 1191 1192 if (m_scan != scan) 1193 PredictFrameSkip(scan); 1194 1087 1195 m_scan = scan; 1088 1196 } 1089 1197 … … void NuppelVideoPlayer::AVSync(void) 2377 2485 ps = kScan_Progressive; 2378 2486 2379 2487 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);2386 2488 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 } 2401 2505 } 2402 2506 else 2403 2507 { 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)); 2406 2510 } 2407 2511 } 2408 else if (!using_null_videoout)2409 {2410 // if we get here, we're actually going to do video output2411 if (buffer)2412 videoOutput->PrepareFrame(buffer, ps);2413 2512 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) 2422 2516 { 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 } 2427 2542 } 2428 2429 if (m_double_framerate) 2543 else if (!using_null_videoout) 2430 2544 { 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) 2446 2571 { 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(); 2449 2586 } 2450 videofiltersLock.unlock();2451 }2452 2587 2453 if (buffer)2454 videoOutput->PrepareFrame(buffer, ps);2588 if (buffer) 2589 videoOutput->PrepareFrame(buffer, ps); 2455 2590 2456 // Display the second field2457 videosync->AdvanceTrigger();2591 // Display the second field 2592 videosync->AdvanceTrigger(); 2458 2593 #ifdef NEW_AVSYNC 2459 videosync->WaitForFrame(avsync_adjustment);2594 videosync->WaitForFrame(avsync_adjustment); 2460 2595 #else 2461 videosync->WaitForFrame(0);2596 videosync->WaitForFrame(0); 2462 2597 #endif 2463 if (!resetvideo) 2464 { 2465 videoOutput->Show(ps); 2598 if (!resetvideo) 2599 { 2600 videoOutput->Show(ps); 2601 } 2466 2602 } 2467 }2468 2603 2469 repeat_delay = frame_interval * buffer->repeat_pict * 0.5;2604 repeat_delay = frame_interval * buffer->repeat_pict * 0.5; 2470 2605 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 } 2478 2615 } 2479 2616 2480 2617 if (output_jmeter && output_jmeter->RecordCycleTime()) 2481 2618 { 2482 2619 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") 2484 2621 .arg(avsync_delay / 1000).arg(avsync_avg / 1000) 2485 2622 .arg(warpfactor).arg(warpfactor_avg)); 2486 2623 } … … void NuppelVideoPlayer::AVSync(void) 2512 2649 audio_lock.unlock(); 2513 2650 #if 0 2514 2651 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") 2517 2654 .arg(currentaudiotime) 2518 2655 .arg(buffer->timecode) 2519 2656 .arg(frame_interval) 2520 2657 .arg(buffer->timecode - currentaudiotime) 2521 2658 .arg(avsync_avg) 2522 2659 .arg(tc_wrap[TC_AUDIO]) 2523 2660 ); 2524 2661 #endif 2525 2662 if (currentaudiotime != 0 && buffer->timecode != 0) 2526 2663 { // currentaudiotime == 0 after a seek … … bool NuppelVideoPlayer::StartPlaying(boo 3550 3687 3551 3688 play_speed = next_play_speed; 3552 3689 normal_speed = next_normal_speed; 3690 3553 3691 VERBOSE(VB_PLAYBACK, LOC + "Changing speed to " << play_speed); 3554 3692 3693 PredictFrameSkip(m_scan); 3694 3555 3695 if (play_speed == 0.0) 3556 3696 { 3557 3697 DoPause(); -
libs/libmythtv/NuppelVideoPlayer.h
old new class MPUBLIC NuppelVideoPlayer : public 431 431 FrameScanType detectInterlace(FrameScanType newScan, FrameScanType scan, 432 432 float fps, int video_height); 433 433 void AutoDeint(VideoFrame*); 434 void PredictFrameSkip(FrameScanType scan); 434 435 435 436 // Private Sets 436 437 void SetPlayingInfo(const ProgramInfo &pginfo); … … class MPUBLIC NuppelVideoPlayer : public 805 806 bool audio_paused; 806 807 int repeat_delay; 807 808 809 int m_frame_skip; 810 int m_frame_show; 811 int m_frame_skip_idx; 812 int m_frame_show_idx; 813 808 814 // Audio warping stuff 809 815 float warpfactor; 810 816 float warpfactor_avg;