MythTV
master
libs
libmythtv
recordingquality.cpp
Go to the documentation of this file.
1
#include <algorithm>
2
#include <utility>
3
4
#include "
libmythbase/mythcorecontext.h
"
5
#include "
libmythbase/mythlogging.h
"
6
#include "
libmythbase/stringutil.h
"
7
8
#include "
recordinginfo.h
"
9
#include "
recordingquality.h
"
10
11
static
void
merge_overlapping
(
RecordingGaps
&gaps);
12
static
double
score_gaps
(
const
RecordingInfo
&
/*ri*/
,
const
RecordingGaps
&
/*gaps*/
);
13
static
QDateTime
get_start
(
const
RecordingInfo
&
/*ri*/
);
14
static
QDateTime
get_end
(
const
RecordingInfo
&
/*ri*/
);
15
16
RecordingQuality::RecordingQuality
(
const
RecordingInfo
*ri,
17
RecordingGaps
rg)
18
: m_recordingGaps(
std
::move(rg))
19
{
20
if
(!ri)
21
return
;
22
23
std::stable_sort(
m_recordingGaps
.begin(),
m_recordingGaps
.end());
24
merge_overlapping
(
m_recordingGaps
);
25
26
m_overallScore
=
score_gaps
(*ri,
m_recordingGaps
);
27
28
LOG
(VB_RECORD, LOG_INFO,
29
QString(
"RecordingQuality() score(%3)"
).arg(
m_overallScore
));
30
}
31
32
RecordingQuality::RecordingQuality
(
33
const
RecordingInfo
*ri,
RecordingGaps
rg,
34
const
QDateTime &first,
const
QDateTime &latest) :
35
m_recordingGaps(
std
::move(rg))
36
{
37
if
(!ri)
38
return
;
39
40
m_programKey
= ri->
MakeUniqueKey
();
41
42
// trim start
43
QDateTime start =
get_start
(*ri);
44
while
(!
m_recordingGaps
.empty() &&
45
m_recordingGaps
.first().GetStart() < start)
46
{
47
RecordingGap
&firstGap =
m_recordingGaps
.first();
48
if
(start < firstGap.
GetEnd
())
49
firstGap =
RecordingGap
(start, firstGap.
GetEnd
());
50
else
51
m_recordingGaps
.pop_front();
52
}
53
54
// trim end
55
QDateTime end =
get_end
(*ri);
56
while
(!
m_recordingGaps
.empty() &&
57
m_recordingGaps
.back().GetEnd() > end)
58
{
59
RecordingGap
&
back
=
m_recordingGaps
.back();
60
if
(
back
.GetStart() < end)
61
back
=
RecordingGap
(
back
.GetStart(), end);
62
else
63
m_recordingGaps
.pop_back();
64
}
65
66
// account for late start
67
int
start_gap = (first.isValid()) ? start.secsTo(first) : 0;
68
if
(start_gap >
gCoreContext
->
GetNumSetting
(
"MaxStartGap"
, 15))
69
m_recordingGaps
.push_front(
RecordingGap
(start, first));
70
71
// account for missing end
72
int
end_gap = (latest.isValid()) ? latest.secsTo(end) : 0;
73
if
(end_gap >
gCoreContext
->
GetNumSetting
(
"MaxEndGap"
, 15))
74
m_recordingGaps
.push_back(
RecordingGap
(latest, end));
75
76
std::stable_sort(
m_recordingGaps
.begin(),
m_recordingGaps
.end());
77
merge_overlapping
(
m_recordingGaps
);
78
79
m_overallScore
=
score_gaps
(*ri,
m_recordingGaps
);
80
81
LOG
(VB_RECORD, LOG_INFO,
82
QString(
"RecordingQuality() start(%1) end(%2) score(%3)"
)
83
.arg(
MythDate::toString
(start,
MythDate::ISODate
),
84
MythDate::toString
(end,
MythDate::ISODate
),
85
QString::number(
m_overallScore
)));
86
}
87
88
void
RecordingQuality::AddTSStatistics
(
89
int
continuity_error_count,
int
packet_count)
90
{
91
m_continuityErrorCount
= continuity_error_count;
92
m_packetCount
= packet_count;
93
if
(!
m_packetCount
)
94
return
;
95
96
double
er = double(
m_continuityErrorCount
) / double(
m_packetCount
);
97
if
(er >= 0.01)
98
m_overallScore
= std::max(
m_overallScore
* 0.60, 0.0);
99
else
if
(er >= 0.001)
100
m_overallScore
= std::max(
m_overallScore
* 0.80, 0.0);
101
else
if
(er >= 0.0001)
102
m_overallScore
= std::max(
m_overallScore
* 0.90, 0.0);
103
104
if
(er >= 0.01)
105
m_overallScore
= std::min(
m_overallScore
, 0.5);
106
}
107
108
bool
RecordingQuality::IsDamaged
(
void
)
const
109
{
110
return
(
m_overallScore
* 100) <
111
gCoreContext
->
GetNumSetting
(
"MinimumRecordingQuality"
, 95);
112
}
113
114
QString
RecordingQuality::toStringXML
(
void
)
const
115
{
116
QString str =
117
QString(R
"(<RecordingQuality overall_score="%1" key="%2")")
118
.arg(
m_overallScore
).arg(
m_programKey
);
119
120
if
(
m_packetCount
)
121
{
122
str += QString(R
"( continuity_error_count="%1" packet_count="%2")")
123
.arg(
m_continuityErrorCount
).arg(
m_packetCount
);
124
}
125
126
if
(
m_recordingGaps
.empty())
127
return
str +
" />"
;
128
129
str +=
">\n"
;
130
131
auto
add_gap = [](
const
QString& s,
const
auto
& gap) {
132
return
s +
StringUtil::indentSpaces
(1) +
133
QString(
"<Gap start=\"%1\" end=\"%2\" duration=\"%3\" />\n"
)
134
.arg(gap.GetStart().toString(
Qt::ISODate
))
135
.arg(gap.GetEnd().toString(
Qt::ISODate
))
136
.arg(gap.GetStart().secsTo(gap.GetEnd()));
137
};
138
str = std::accumulate(
m_recordingGaps
.cbegin(),
m_recordingGaps
.cend(),
139
str, add_gap);
140
141
return
str +
"</RecordingQuality>"
;
142
}
143
144
static
void
merge_overlapping
(
RecordingGaps
&gaps)
145
{
146
if
(gaps.empty())
147
return
;
148
149
RecordingGaps::iterator it = gaps.begin();
150
RecordingGaps::iterator next = it; ++next;
151
while
(next != gaps.end())
152
{
153
if
((*it).GetEnd() >= (*next).GetStart())
154
{
155
(*it) =
RecordingGap
((*it).GetStart(), (*next).GetEnd());
156
next = gaps.erase(next);
157
}
158
else
159
{
160
it = next;
161
++next;
162
}
163
}
164
}
165
166
static
double
score_gaps
(
const
RecordingInfo
&ri,
const
RecordingGaps
&gaps)
167
{
168
RecordingGaps::const_iterator it = gaps.begin();
169
if
(it == gaps.end())
170
return
1.0;
171
172
QDateTime start =
get_start
(ri);
173
174
double
program_length = start.secsTo(
get_end
(ri));
175
if
(program_length < 1.0)
176
return
0.0;
177
178
double
score = 1.0;
179
for
(; it != gaps.end(); ++it)
180
{
181
double
gap_start = start.secsTo((*it).GetStart());
182
double
gap_end = start.secsTo((*it).GetEnd());
183
double
gap_length = gap_end - gap_start;
184
double
rel_start = gap_start / program_length;
185
double
rel_end = gap_end / program_length;
186
double
rel_center = (rel_start + rel_end) * 0.5;
187
double
rel_length = rel_end - rel_start;
188
189
/*
190
LOG(VB_GENERAL, LOG_INFO,
191
QString("%1 gap(%2,%3,%4) rel(%5,%6,%7)")
192
.arg((*it).toString())
193
.arg(gap_start).arg(gap_end).arg(gap_length)
194
.arg(rel_start).arg(rel_end).arg(rel_length));
195
*/
196
197
if
(rel_center >= 0.9 || rel_end >= 0.95)
198
rel_length *= 4;
199
200
if
(rel_center < 0.1)
201
rel_length *= 2;
202
203
if
(gap_length > 5)
// 5 secs
204
rel_length *= 1.5;
205
206
if
(gap_length > 120)
// 2 minutes
207
rel_length *= 5;
208
209
// NOTE: many more scoring adjustments could be made here
210
// and we may want to tune this differently depending on
211
// program length.
212
213
score -= rel_length;
214
}
215
216
return
(score > 0.0) ? score : 0.0;
217
}
218
219
static
QDateTime
get_start
(
const
RecordingInfo
&ri)
220
{
221
if
(ri.
GetDesiredStartTime
().isValid())
222
{
223
return
(ri.
GetScheduledStartTime
() > ri.
GetDesiredStartTime
()) ?
224
ri.
GetScheduledStartTime
() : ri.
GetDesiredStartTime
();
225
}
226
return
ri.
GetScheduledStartTime
();
227
}
228
229
static
QDateTime
get_end
(
const
RecordingInfo
&ri)
230
{
231
if
(ri.
GetDesiredEndTime
().isValid())
232
{
233
return
(ri.
GetScheduledEndTime
() < ri.
GetDesiredEndTime
()) ?
234
ri.
GetScheduledEndTime
() : ri.
GetDesiredEndTime
();
235
}
236
return
ri.
GetScheduledEndTime
();
237
}
ProgramInfo::MakeUniqueKey
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
Definition:
programinfo.h:339
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition:
mythdate.cpp:84
merge_overlapping
static void merge_overlapping(RecordingGaps &gaps)
Definition:
recordingquality.cpp:144
RecordingInfo::GetDesiredStartTime
QDateTime GetDesiredStartTime(void) const
Definition:
recordinginfo.h:245
back
static guint32 * back
Definition:
goom_core.cpp:25
RecordingQuality::m_recordingGaps
RecordingGaps m_recordingGaps
Definition:
recordingquality.h:52
RecordingQuality::RecordingQuality
RecordingQuality(const RecordingInfo *ri, RecordingGaps rg)
Definition:
recordingquality.cpp:16
score_gaps
static double score_gaps(const RecordingInfo &, const RecordingGaps &)
Definition:
recordingquality.cpp:166
RecordingInfo
Holds information on a TV Program one might wish to record.
Definition:
recordinginfo.h:35
StringUtil::indentSpaces
QString indentSpaces(unsigned int level, unsigned int size=4)
Definition:
stringutil.h:33
ProgramInfo::GetScheduledEndTime
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition:
programinfo.h:397
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition:
mythlogging.h:39
RecordingQuality::IsDamaged
bool IsDamaged(void) const
Definition:
recordingquality.cpp:108
RecordingQuality::m_overallScore
double m_overallScore
Definition:
recordingquality.h:51
RecordingQuality::toStringXML
QString toStringXML(void) const
Definition:
recordingquality.cpp:114
ProgramInfo::GetScheduledStartTime
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition:
programinfo.h:390
mythlogging.h
RecordingQuality::m_programKey
QString m_programKey
Definition:
recordingquality.h:50
get_end
static QDateTime get_end(const RecordingInfo &)
Definition:
recordingquality.cpp:229
stringutil.h
RecordingQuality::AddTSStatistics
void AddTSStatistics(int continuity_error_count, int packet_count)
Definition:
recordingquality.cpp:88
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition:
mythcorecontext.cpp:54
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition:
mythcorecontext.cpp:910
RecordingGap::GetEnd
QDateTime GetEnd(void) const
Definition:
recordingquality.h:20
recordinginfo.h
RecordingQuality::m_packetCount
int m_packetCount
Definition:
recordingquality.h:49
recordingquality.h
RecordingQuality::m_continuityErrorCount
int m_continuityErrorCount
Definition:
recordingquality.h:48
RecordingGap
Definition:
recordingquality.h:14
mythcorecontext.h
std
Definition:
mythchrono.h:23
MythDate::ISODate
@ ISODate
Default UTC.
Definition:
mythdate.h:17
get_start
static QDateTime get_start(const RecordingInfo &)
Definition:
recordingquality.cpp:219
RecordingInfo::GetDesiredEndTime
QDateTime GetDesiredEndTime(void) const
Definition:
recordinginfo.h:246
RecordingGaps
QList< RecordingGap > RecordingGaps
Definition:
recordingquality.h:32
Generated on Thu Jun 1 2023 03:21:32 for MythTV by
1.8.17