26 readData(
const QString&
filename,
float *mean,
unsigned char *median,
float *stddev,
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")
112 writeData(
const QString&
filename,
float *mean,
unsigned char *median,
float *stddev,
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();
200 QString details =
m_logo ? QString(
"logo %1x%2@(%3,%4)")
204 LOG(VB_COMMFLAG, LOG_INFO,
205 QString(
"HistogramAnalyzer::MythPlayerInited %1x%2: %3")
206 .arg(width).arg(height).arg(details));
214 m_mean =
new float[nframes];
215 m_median =
new unsigned char[nframes];
217 m_fRow =
new int[nframes];
218 m_fCol =
new int[nframes];
234 unsigned int npixels = width * height;
235 m_buf =
new unsigned char[npixels];
242 LOG(VB_COMMFLAG, LOG_INFO,
243 QString(
"HistogramAnalyzer::MythPlayerInited read %1")
259 static constexpr
int ROUNDUP(
int a,
int b) {
return (a + b - 1) / b * b; }
268 static constexpr
int kDefaultColor = 0;
278 static constexpr
int kRInc = 4;
279 static constexpr
int kCInc = 4;
283 bool ismonochromatic =
false;
288 unsigned int borderpixels = 0;
289 unsigned int livepixels = 0;
290 unsigned int npixels = 0;
291 unsigned int halfnpixels = 0;
292 unsigned char *
pp =
nullptr;
293 unsigned char bordercolor = 0;
294 unsigned long long sumval = 0;
295 unsigned long long sumsquares = 0;
302 std::chrono::microseconds start {0us};
303 std::chrono::microseconds end {0us};
313 &croprow, &cropcol, &cropwidth, &cropheight) != 0;
315 start = nowAsDuration<std::chrono::microseconds>();
317 m_fRow[frameno] = croprow;
318 m_fCol[frameno] = cropcol;
325 croprow = pgmheight * 3 / 8;
326 cropheight = pgmheight / 4;
327 cropcol = pgmwidth * 3 / 8;
328 cropwidth = pgmwidth / 4;
333 rr2 =
ROUNDUP(croprow + cropheight, kRInc);
334 cc2 =
ROUNDUP(cropcol + cropwidth, kCInc);
335 rr3 =
ROUNDUP(pgmheight, kRInc);
336 cc3 =
ROUNDUP(pgmwidth, kCInc);
338 borderpixels = (rr1 / kRInc) * (cc3 / kCInc) +
339 ((rr2 - rr1) / kRInc) * (cc1 / kCInc) +
340 ((rr2 - rr1) / kRInc) * ((cc3 - cc2) / kCInc) +
341 ((rr3 - rr2) / kRInc) * (cc3 / kCInc);
345 m_histVal[kDefaultColor] += borderpixels;
346 for (
int rr = rr1; rr < rr2; rr += kRInc)
348 int rroffset = rr * pgmwidth;
350 for (
int cc = cc1;
cc < cc2;
cc += kCInc)
356 unsigned char val = pgm->data[0][rroffset +
cc];
359 sumsquares += 1ULL * val * val;
364 npixels = borderpixels + livepixels;
367 halfnpixels = npixels / 2;
368 for (
unsigned int color = 0; color < UCHAR_MAX + 1; color++)
370 (
m_histVal[color] * UCHAR_MAX + halfnpixels) / npixels;
373 if (ismonochromatic && livepixels)
379 bordercolor = (sumval + livepixels - 1) / livepixels;
380 sumval += 1ULL * borderpixels * bordercolor;
381 sumsquares += 1ULL * borderpixels * bordercolor * bordercolor;
384 memset(
m_buf, bordercolor, borderpixels *
sizeof(*
m_buf));
386 m_mean[frameno] = (float)sumval / npixels;
389 sqrt((sumsquares - (
float)sumval * sumval / npixels) / (npixels - 1)) :
392 end = nowAsDuration<std::chrono::microseconds>();
400 LOG(VB_COMMFLAG, LOG_ERR,
401 QString(
"HistogramAnalyzer::analyzeFrame error at frame %1")
415 LOG(VB_COMMFLAG, LOG_INFO,
416 QString(
"HistogramAnalyzer::finished wrote %1")
434 LOG(VB_COMMFLAG, LOG_INFO, QString(
"HA Time: analyze=%1s")