MythTV  master
mythvideoscantracker.cpp
Go to the documentation of this file.
1 // MythTV
3 #include "mythframe.h"
4 #include "mythavutil.h"
5 #include "mythplayerui.h"
6 #include "mythvideoout.h"
7 #include "mythvideoscantracker.h"
8 
9 #define LOC QString("ScanTracker: ")
10 
12  : m_parentPlayer(Parent)
13 {
14 }
15 
17 {
18  // Default to interlaced playback but set the tracker to progressive
19  // Enable autodetection of interlaced/progressive from video stream
20  // Previously we set to interlaced and the scan tracker to 2 but this
21  // mis-'detected' a number of streams as interlaced when they are progressive.
22  // This significantly reduces the number of errors and also ensures we do not
23  // needlessly setup deinterlacers - which may consume significant resources.
24  // We set to interlaced for those streams whose frame rate is initially detected
25  // as e.g. 59.9 when it is actually 29.97 interlaced.
27  m_scanLocked = false;
28  m_scanTracker = -2;
29  if (VideoOutput)
30  VideoOutput->SetDeinterlacing(true, m_parentPlayer->CanSupportDoubleRate());
31 }
32 
34 {
35  m_scanInitialized = false;
36  m_scanLocked = false;
37 }
38 
40 {
41  m_scanLocked = false;
42  m_scanTracker = (m_scan == kScan_Interlaced) ? 2 : 0;
43 }
44 
46 {
47  int next = m_scanOverride + 1;
48  if (next > kScan_Progressive)
49  next = kScan_Detect;
50  return static_cast<FrameScanType>(next);
51 }
52 
54 {
55  if (m_scanOverride == Scan)
56  return;
57 
58  m_scanOverride = Scan;
60  {
61  m_scanLocked = false;
62  m_scanInitialized = false;
63  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Reverting to auto detection of scan");
64  }
65 }
66 
68 {
69  if (!Frame)
70  return kScan_Progressive;
71 
72  // Update details for debug OSD
73  m_lastDeinterlacer = Frame->m_deinterlaceInuse;
74  m_lastDeinterlacer2x = Frame->m_deinterlaceInuse2x;
75  // We use the underlying pix_fmt as it retains the distinction between hardware
76  // and software frames for decode only decoders.
77  m_lastFrameCodec = MythAVUtil::PixelFormatToFrameType(static_cast<AVPixelFormat>(Frame->m_pixFmt));
78 
79  // Decide on type and rate
80  FrameScanType result = m_scan;
81  if ((kScan_Detect == m_scan) || (kScan_Ignore == m_scan) || Frame->m_alreadyDeinterlaced)
82  {
83  result = kScan_Progressive;
84  }
85  else if (is_interlaced(m_scan))
86  {
87  result = kScan_Interlaced;
88  Frame->m_interlacedReverse = (m_scan == kScan_Intr2ndField);
89  }
90 
91  // Only display the second field if needed.
92  // This is somewhat circular - we check for double rate support when enabling
93  // deinterlacing, request that in the video buffers and the differing implementations
94  // then set m_lastDeinterlacer2x when they are actually using double rate
95  SecondField = is_interlaced(result) && m_lastDeinterlacer2x;
96  return result;
97 }
98 
100 {
101  return m_scan;
102 }
103 
105 {
107  return m_scanOverride;
108  return m_scan;
109 }
110 
111 void MythVideoScanTracker::CheckScanUpdate(MythVideoOutput* VideoOutput, std::chrono::microseconds FrameInterval)
112 {
113  if (m_resetScan != kScan_Ignore)
114  SetScanType(m_resetScan, VideoOutput, FrameInterval);
115 }
116 
118 {
120 }
121 
123  std::chrono::microseconds FrameInterval)
124 {
126  {
127  m_resetScan = Scan;
128  return;
129  }
130 
131  if (!VideoOutput)
132  return;
133 
135 
136  if (m_scanInitialized && (m_scan == Scan) && (m_lastFrameInterval == FrameInterval))
137  return;
138 
139  m_scanLocked = (Scan != kScan_Detect);
140  m_scanInitialized = true;
141  m_lastFrameInterval = FrameInterval;
142 
143  if (is_interlaced(Scan))
144  {
145  float currentspeed = m_parentPlayer->GetPlaySpeed();
146  bool normal = (currentspeed > 0.99F) && (currentspeed < 1.01F) && m_parentPlayer->AtNormalSpeed();
147  VideoOutput->SetDeinterlacing(true, m_parentPlayer->CanSupportDoubleRate() && normal);
148  }
149  else if (kScan_Progressive == Scan)
150  {
151  VideoOutput->SetDeinterlacing(false, false);
152  }
153 
154  m_scan = Scan;
155 }
156 
178  std::chrono::microseconds FrameInterval, bool AllowLock)
179 {
180  if (!Frame)
181  return;
182 
184  {
185  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Locking scan override to '%1'")
186  .arg(ScanTypeToUserString(m_scanOverride, true)));
187  SetScanType(m_scanOverride, VideoOutput, FrameInterval);
188  }
189 
190  // This is currently only signalled for H264 content
191  if (Frame->m_newGOP)
192  {
194  ((Frame->m_interlaced && !is_interlaced(m_scan)) ||
195  (!Frame->m_interlaced && is_interlaced(m_scan))))
196  {
197  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Unlocking frame scan");
198  m_scanLocked = false;
199  }
200  }
201 
202  if (m_scanLocked)
203  return;
204 
205  if (Frame->m_interlaced)
206  {
207  if (m_scanTracker < 0)
208  {
209  LOG(VB_PLAYBACK, LOG_INFO, LOC +
210  QString("Interlaced frame seen after %1 progressive frames")
211  .arg(abs(m_scanTracker)));
212  m_scanTracker = 2;
213  if (AllowLock)
214  {
215  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Locking scan to Interlaced.");
216  SetScanType(kScan_Interlaced, VideoOutput, FrameInterval);
217  return;
218  }
219  }
220  m_scanTracker++;
221  }
222  else
223  {
224  if (m_scanTracker > 0)
225  {
226  LOG(VB_PLAYBACK, LOG_INFO, LOC +
227  QString("Progressive frame seen after %1 interlaced frames")
228  .arg(m_scanTracker));
229  m_scanTracker = 0;
230  }
231  m_scanTracker--;
232  }
233 
234  int min_count = !AllowLock ? 0 : 2;
235  if (abs(m_scanTracker) <= min_count)
236  return;
237 
239  VideoOutput, FrameInterval);
240  m_scanLocked = false;
241 }
242 
244 {
246  QString dbg = QString("DetectInterlace(") + ScanTypeToString(NewScan) +
247  QString(", ") + ScanTypeToString(scan) + QString(", ") +
248  QString("%1").arg(static_cast<double>(Rate)) + QString(", ") +
249  QString("%1").arg(VideoHeight) + QString(") ->");
250 
251  if (kScan_Ignore != NewScan || kScan_Detect == scan)
252  {
253  // The scanning mode should be decoded from the stream - otherwise guess
254  // default to interlaced
256  // 720P, outside interlaced frame rates or too large for interlaced
257  if ((720 == VideoHeight) || (Rate < 25) || (Rate > 30) || (VideoHeight > 1080))
259  if (kScan_Detect != NewScan)
260  scan = NewScan;
261  }
262 
263  LOG(VB_PLAYBACK, LOG_INFO, LOC + dbg + ScanTypeToString(scan));
264  return scan;
265 }
MythVideoScanTracker::m_scanInitialized
bool m_scanInitialized
Definition: mythvideoscantracker.h:45
MythPlayer::AtNormalSpeed
bool AtNormalSpeed(void) const
Definition: mythplayer.h:159
ScanTypeToUserString
QString ScanTypeToUserString(FrameScanType Scan, bool Forced=false)
Definition: videoouttypes.h:198
MythVideoOutput
Definition: mythvideoout.h:35
mythvideoout.h
kScan_Detect
@ kScan_Detect
Definition: videoouttypes.h:97
VideoOutput
This class serves as the base class for all video output methods.
mythplayerui.h
MythVideoScanTracker::m_scan
FrameScanType m_scan
Definition: mythvideoscantracker.h:42
Frame
Definition: zmdefines.h:93
MythVideoScanTracker::m_scanOverride
FrameScanType m_scanOverride
Definition: mythvideoscantracker.h:43
MythVideoScanTracker::NextScanOverride
FrameScanType NextScanOverride()
Definition: mythvideoscantracker.cpp:45
FrameScanType
FrameScanType
Definition: videoouttypes.h:94
MythVideoScanTracker::m_lastFrameCodec
VideoFrameType m_lastFrameCodec
Definition: mythvideoscantracker.h:49
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
is_current_thread
bool is_current_thread(MThread *thread)
Use this to determine if you are in the named thread.
Definition: mthread.cpp:40
mythframe.h
MythVideoScanTracker::m_resetScan
FrameScanType m_resetScan
Definition: mythvideoscantracker.h:41
hardwareprofile.scan.scan
def scan(profile, smoonURL, gate)
Definition: scan.py:55
MythVideoScanTracker::m_lastDeinterlacer
MythDeintType m_lastDeinterlacer
Definition: mythvideoscantracker.h:48
MythPlayer::GetPlaySpeed
float GetPlaySpeed(void) const
Definition: mythplayer.h:139
MythVideoScanTracker::DetectInterlace
FrameScanType DetectInterlace(FrameScanType NewScan, float Rate, int VideoHeight)
Definition: mythvideoscantracker.cpp:243
MythPlayerUI
Definition: mythplayerui.h:10
kScan_Intr2ndField
@ kScan_Intr2ndField
Definition: videoouttypes.h:99
MythVideoScanTracker::m_parentPlayer
MythPlayerUI * m_parentPlayer
Definition: mythvideoscantracker.h:39
MythVideoScanTracker::CheckScanUpdate
void CheckScanUpdate(MythVideoOutput *VideoOutput, std::chrono::microseconds FrameInterval)
Definition: mythvideoscantracker.cpp:111
mythlogging.h
kScan_Progressive
@ kScan_Progressive
Definition: videoouttypes.h:100
MythVideoScanTracker::m_scanLocked
bool m_scanLocked
Definition: mythvideoscantracker.h:44
mythvideoscantracker.h
ScanTypeToString
QString ScanTypeToString(FrameScanType Scan)
Definition: videoouttypes.h:211
MythVideoScanTracker::m_lastDeinterlacer2x
bool m_lastDeinterlacer2x
Definition: mythvideoscantracker.h:47
MythVideoScanTracker::GetScanForDisplay
FrameScanType GetScanForDisplay(MythVideoFrame *Frame, bool &SecondField)
Definition: mythvideoscantracker.cpp:67
LOC
#define LOC
Definition: mythvideoscantracker.cpp:9
MythAVUtil::PixelFormatToFrameType
static VideoFrameType PixelFormatToFrameType(AVPixelFormat Fmt)
Definition: mythavutil.cpp:71
MythVideoScanTracker::MythVideoScanTracker
MythVideoScanTracker(MythPlayerUI *Parent)
Definition: mythvideoscantracker.cpp:11
MythVideoScanTracker::AutoDeint
virtual void AutoDeint(MythVideoFrame *Frame, MythVideoOutput *VideoOutput, std::chrono::microseconds FrameInterval, bool AllowLock=true)
Check whether deinterlacing should be enabled.
Definition: mythvideoscantracker.cpp:177
MythVideoScanTracker::InitialiseScan
void InitialiseScan(MythVideoOutput *VideoOutput)
Definition: mythvideoscantracker.cpp:16
MythVideoScanTracker::SetScanType
void SetScanType(FrameScanType Scan, MythVideoOutput *VideoOutput, std::chrono::microseconds FrameInterval)
Definition: mythvideoscantracker.cpp:122
MythVideoScanTracker::m_lastFrameInterval
std::chrono::microseconds m_lastFrameInterval
Definition: mythvideoscantracker.h:46
MythVideoScanTracker::SetScanOverride
void SetScanOverride(FrameScanType Scan)
Definition: mythvideoscantracker.cpp:53
kScan_Interlaced
@ kScan_Interlaced
Definition: videoouttypes.h:98
MythVideoFrame::DeinterlacerName
static QString DeinterlacerName(MythDeintType Deint, bool DoubleRate, VideoFrameType Format=FMT_NONE)
Definition: mythframe.cpp:462
mythavutil.h
MythVideoScanTracker::GetScanTypeWithOverride
FrameScanType GetScanTypeWithOverride() const
Definition: mythvideoscantracker.cpp:104
MythVideoScanTracker::GetDeinterlacerName
QString GetDeinterlacerName()
Definition: mythvideoscantracker.cpp:117
MythVideoFrame
Definition: mythframe.h:88
MythVideoScanTracker::ResetTracker
void ResetTracker()
Definition: mythvideoscantracker.cpp:39
MythVideoScanTracker::m_scanTracker
long long m_scanTracker
Definition: mythvideoscantracker.h:40
MythVideoScanTracker::GetScanType
FrameScanType GetScanType() const
Definition: mythvideoscantracker.cpp:99
MythVideoScanTracker::m_mainThread
QThread * m_mainThread
Definition: mythvideoscantracker.h:51
MythVideoScanTracker::UnlockScan
void UnlockScan()
Definition: mythvideoscantracker.cpp:33
MythPlayerUI::CanSupportDoubleRate
bool CanSupportDoubleRate()
Definition: mythplayerui.cpp:805
is_interlaced
bool is_interlaced(FrameScanType Scan)
Definition: videoouttypes.h:188
kScan_Ignore
@ kScan_Ignore
Definition: videoouttypes.h:96