27 int *frow,
int *fcol,
int *fwidth,
int *fheight,
31 std::array<quint32,UCHAR_MAX + 1> counter {};
33 QByteArray fname =
filename.toLocal8Bit();
34 FILE *fp = fopen(fname.constData(),
"r");
38 for (
long long frameno = 0; frameno < nframes; frameno++)
40 int monochromaticval = 0;
47 float stddevval = NAN;
48 int nitems = fscanf(fp,
"%20d %20f %20d %20f %20d %20d %20d %20d",
49 &monochromaticval, &meanval, &medianval, &stddevval,
50 &widthval, &heightval, &colval, &rowval);
53 LOG(VB_COMMFLAG, LOG_ERR,
54 QString(
"Not enough data in %1: frame %2")
58 if (monochromaticval < 0 || monochromaticval > 1 ||
59 medianval < 0 || (
uint)medianval > UCHAR_MAX ||
60 widthval < 0 || heightval < 0 || colval < 0 || rowval < 0)
62 LOG(VB_COMMFLAG, LOG_ERR,
63 QString(
"Data out of range in %1: frame %2")
67 for (
uint & ctr : counter)
69 if (fscanf(fp,
"%20x", &ctr) != 1)
71 LOG(VB_COMMFLAG, LOG_ERR,
72 QString(
"Not enough data in %1: frame %2")
78 LOG(VB_COMMFLAG, LOG_ERR,
79 QString(
"Data out of range in %1: frame %2")
84 mean[frameno] = meanval;
85 median[frameno] = medianval;
86 stddev[frameno] = stddevval;
87 frow[frameno] = rowval;
88 fcol[frameno] = colval;
89 fwidth[frameno] = widthval;
90 fheight[frameno] = heightval;
91 for (
size_t ii = 0; ii < counter.size(); ii++)
92 histogram[frameno][ii] = counter[ii];
93 monochromatic[frameno] = !widthval || !heightval ? 1 : 0;
100 LOG(VB_COMMFLAG, LOG_ERR, QString(
"Error closing %1: %2")
106 LOG(VB_COMMFLAG, LOG_ERR, QString(
"Error closing %1: %2")
113 int *frow,
int *fcol,
int *fwidth,
int *fheight,
117 QByteArray fname =
filename.toLocal8Bit();
118 FILE *fp = fopen(fname,
"w");
121 for (
long long frameno = 0; frameno < nframes; frameno++)
123 (void)fprintf(fp,
"%3u %10.6f %3u %10.6f %5d %5d %5d %5d",
124 monochromatic[frameno],
125 static_cast<double>(mean[frameno]), median[frameno],
126 static_cast<double>(stddev[frameno]),
127 fwidth[frameno], fheight[frameno],
128 fcol[frameno], frow[frameno]);
129 for (
unsigned int ii = 0; ii < UCHAR_MAX + 1; ii++)
130 (
void)fprintf(fp,
" %02x", histogram[frameno][ii]);
131 (void)fprintf(fp,
"\n");
134 LOG(VB_COMMFLAG, LOG_ERR, QString(
"Error closing %1: %2")
142 std::shared_ptr<BorderDetector> bd,
143 const QString& debugdir)
144 : m_pgmConverter(std::move(pgmc))
145 , m_borderDetector(std::move(bd))
147 , m_debugdata(debugdir +
"/HistogramAnalyzer-pgm.txt")
149 , m_debugdata(debugdir +
"/HistogramAnalyzer-yuv.txt")
162 QString(
"HistogramAnalyzer debugLevel %1").arg(
m_debugLevel));
191 unsigned int width = buf_dim.width();
192 unsigned int height = buf_dim.height();
204 QString details =
m_logo ? QString(
"logo %1x%2@(%3,%4)")
208 LOG(VB_COMMFLAG, LOG_INFO,
209 QString(
"HistogramAnalyzer::MythPlayerInited %1x%2: %3")
210 .arg(width).arg(height).arg(details));
218 m_mean =
new float[nframes];
219 m_median =
new unsigned char[nframes];
221 m_fRow =
new int[nframes];
222 m_fCol =
new int[nframes];
238 unsigned int npixels = width * height;
239 m_buf =
new unsigned char[npixels];
246 LOG(VB_COMMFLAG, LOG_INFO,
247 QString(
"HistogramAnalyzer::MythPlayerInited read %1")
263 static constexpr
int ROUNDUP(
int a,
int b) {
return (a + b - 1) / b * b; }
272 static constexpr
int kDefaultColor = 0;
282 static constexpr
int kRInc = 4;
283 static constexpr
int kCInc = 4;
287 bool ismonochromatic =
false;
292 unsigned int borderpixels = 0;
293 unsigned int livepixels = 0;
294 unsigned int npixels = 0;
295 unsigned int halfnpixels = 0;
296 unsigned char *
pp =
nullptr;
297 unsigned char bordercolor = 0;
298 unsigned long long sumval = 0;
299 unsigned long long sumsquares = 0;
306 std::chrono::microseconds start {0us};
307 std::chrono::microseconds end {0us};
317 &croprow, &cropcol, &cropwidth, &cropheight) != 0;
319 start = nowAsDuration<std::chrono::microseconds>();
321 m_fRow[frameno] = croprow;
322 m_fCol[frameno] = cropcol;
329 croprow = pgmheight * 3 / 8;
330 cropheight = pgmheight / 4;
331 cropcol = pgmwidth * 3 / 8;
332 cropwidth = pgmwidth / 4;
337 rr2 =
ROUNDUP(croprow + cropheight, kRInc);
338 cc2 =
ROUNDUP(cropcol + cropwidth, kCInc);
339 rr3 =
ROUNDUP(pgmheight, kRInc);
340 cc3 =
ROUNDUP(pgmwidth, kCInc);
342 borderpixels = (rr1 / kRInc) * (cc3 / kCInc) +
343 ((rr2 - rr1) / kRInc) * (cc1 / kCInc) +
344 ((rr2 - rr1) / kRInc) * ((cc3 - cc2) / kCInc) +
345 ((rr3 - rr2) / kRInc) * (cc3 / kCInc);
349 m_histVal[kDefaultColor] += borderpixels;
350 for (
int rr = rr1; rr < rr2; rr += kRInc)
352 int rroffset = rr * pgmwidth;
354 for (
int cc = cc1;
cc < cc2;
cc += kCInc)
360 unsigned char val = pgm->data[0][rroffset +
cc];
363 sumsquares += 1ULL * val * val;
368 npixels = borderpixels + livepixels;
371 halfnpixels = npixels / 2;
372 for (
unsigned int color = 0; color < UCHAR_MAX + 1; color++)
374 (
m_histVal[color] * UCHAR_MAX + halfnpixels) / npixels;
377 if (ismonochromatic && livepixels)
383 bordercolor = (sumval + livepixels - 1) / livepixels;
384 sumval += 1ULL * borderpixels * bordercolor;
385 sumsquares += 1ULL * borderpixels * bordercolor * bordercolor;
388 memset(
m_buf, bordercolor, borderpixels *
sizeof(*
m_buf));
390 m_mean[frameno] = (float)sumval / npixels;
393 sqrt((sumsquares - (
float)sumval * sumval / npixels) / (npixels - 1)) :
396 end = nowAsDuration<std::chrono::microseconds>();
404 LOG(VB_COMMFLAG, LOG_ERR,
405 QString(
"HistogramAnalyzer::analyzeFrame error at frame %1")
419 LOG(VB_COMMFLAG, LOG_INFO,
420 QString(
"HistogramAnalyzer::finished wrote %1")
438 LOG(VB_COMMFLAG, LOG_INFO, QString(
"HA Time: analyze=%1s")