00001
00002 #include <cstdlib>
00003
00004
00005 #include <algorithm>
00006 using namespace std;
00007
00008 #include "mythconfig.h"
00009
00010
00011 extern "C" {
00012 #include "libavcodec/avcodec.h"
00013 }
00014
00015
00016 #include "frame.h"
00017 #include "mythplayer.h"
00018
00019
00020 #include "FrameAnalyzer.h"
00021 #include "EdgeDetector.h"
00022
00023 namespace edgeDetector {
00024
00025 using namespace frameAnalyzer;
00026
00027 unsigned int *
00028 sgm_init_exclude(unsigned int *sgm, const AVPicture *src, int srcheight,
00029 int excluderow, int excludecol, int excludewidth, int excludeheight)
00030 {
00031
00032
00033
00034
00035
00036
00037
00038 const int srcwidth = src->linesize[0];
00039 int rr, cc, dx, dy, rr2, cc2;
00040 unsigned char *rr0, *rr1;
00041
00042 memset(sgm, 0, srcwidth * srcheight * sizeof(*sgm));
00043 rr2 = srcheight - 1;
00044 cc2 = srcwidth - 1;
00045 for (rr = 0; rr < rr2; rr++)
00046 {
00047 for (cc = 0; cc < cc2; cc++)
00048 {
00049 if (!rrccinrect(rr, cc, excluderow, excludecol,
00050 excludewidth, excludeheight))
00051 {
00052 rr0 = &src->data[0][rr * srcwidth + cc];
00053 rr1 = &src->data[0][(rr + 1) * srcwidth + cc];
00054 dx = rr1[1] - rr0[0];
00055 dy = rr1[0] - rr0[1];
00056 sgm[rr * srcwidth + cc] = dx * dx + dy * dy;
00057 }
00058 }
00059 }
00060 return sgm;
00061 }
00062
00063 #ifdef LATER
00064 unsigned int *
00065 sgm_init(unsigned int *sgm, const AVPicture *src, int srcheight)
00066 {
00067 return sgm_init_exclude(sgm, src, srcheight, 0, 0, 0, 0);
00068 }
00069 #endif
00070
00071 static int sort_ascending(const void *aa, const void *bb)
00072 {
00073 return *(unsigned int*)aa - *(unsigned int*)bb;
00074 }
00075
00076 static int
00077 edge_mark(AVPicture *dst, int dstheight,
00078 int extratop, int extraright, int extrabottom, int extraleft,
00079 const unsigned int *sgm, unsigned int *sgmsorted, int percentile,
00080 int excluderow, int excludecol, int excludewidth, int excludeheight)
00081 {
00082
00083
00084
00085
00086
00087
00088
00089
00090 static const int MINTHRESHOLDPCT = 95;
00091
00092 const int dstwidth = dst->linesize[0];
00093 const int padded_width = extraleft + dstwidth + extraright;
00094 unsigned int thresholdval;
00095 int nn, dstnn, ii, rr, cc, first, last, last2;
00096
00097 (void)extrabottom;
00098
00099
00100
00101
00102
00103
00104
00105 nn = 0;
00106 for (rr = 0; rr < dstheight; rr++)
00107 {
00108 for (cc = 0; cc < dstwidth; cc++)
00109 {
00110 if (!rrccinrect(rr, cc, excluderow, excludecol,
00111 excludewidth, excludeheight))
00112 {
00113 sgmsorted[nn++] = sgm[(extratop + rr) * padded_width +
00114 extraleft + cc];
00115 }
00116 }
00117 }
00118
00119 dstnn = dstwidth * dstheight;
00120 #if 0
00121 assert(nn == dstnn -
00122 (min(max(0, excluderow + excludeheight), dstheight) -
00123 min(max(0, excluderow), dstheight)) *
00124 (min(max(0, excludecol + excludewidth), dstwidth) -
00125 min(max(0, excludecol), dstwidth)));
00126 #endif
00127 memset(dst->data[0], 0, dstnn * sizeof(*dst->data[0]));
00128
00129 if (!nn)
00130 {
00131
00132 return 0;
00133 }
00134
00135 qsort(sgmsorted, nn, sizeof(*sgmsorted), sort_ascending);
00136
00137 ii = percentile * nn / 100;
00138 thresholdval = sgmsorted[ii];
00139
00140
00141
00142
00143
00144 for (first = ii; first > 0 && sgmsorted[first] == thresholdval; first--) ;
00145 if (sgmsorted[first] != thresholdval)
00146 first++;
00147 if (first * 100 / nn < MINTHRESHOLDPCT)
00148 {
00149 unsigned int newthresholdval;
00150
00151 last2 = nn - 1;
00152 for (last = ii; last < last2 && sgmsorted[last] == thresholdval;
00153 last++) ;
00154 if (sgmsorted[last] != thresholdval)
00155 last--;
00156
00157 newthresholdval = sgmsorted[min(last + 1, nn - 1)];
00158 if (thresholdval == newthresholdval)
00159 {
00160
00161 return 0;
00162 }
00163
00164 thresholdval = newthresholdval;
00165 }
00166
00167
00168 for (rr = 0; rr < dstheight; rr++)
00169 {
00170 for (cc = 0; cc < dstwidth; cc++)
00171 {
00172 if (!rrccinrect(rr, cc, excluderow, excludecol,
00173 excludewidth, excludeheight) &&
00174 sgm[(extratop + rr) * padded_width + extraleft + cc] >=
00175 thresholdval)
00176 dst->data[0][rr * dstwidth + cc] = UCHAR_MAX;
00177 }
00178 }
00179 return 0;
00180 }
00181
00182 #ifdef LATER
00183 int edge_mark_uniform(AVPicture *dst, int dstheight, int extramargin,
00184 const unsigned int *sgm, unsigned int *sgmsorted,
00185 int percentile)
00186 {
00187 return edge_mark(dst, dstheight,
00188 extramargin, extramargin, extramargin, extramargin,
00189 sgm, sgmsorted, percentile, 0, 0, 0, 0);
00190 }
00191 #endif
00192
00193 int edge_mark_uniform_exclude(AVPicture *dst, int dstheight, int extramargin,
00194 const unsigned int *sgm, unsigned int *sgmsorted, int percentile,
00195 int excluderow, int excludecol, int excludewidth, int excludeheight)
00196 {
00197 return edge_mark(dst, dstheight,
00198 extramargin, extramargin, extramargin, extramargin,
00199 sgm, sgmsorted, percentile,
00200 excluderow, excludecol, excludewidth, excludeheight);
00201 }
00202
00203 };
00204
00205 EdgeDetector::~EdgeDetector(void)
00206 {
00207 }
00208
00209 int
00210 EdgeDetector::setExcludeArea(int row, int col, int width, int height)
00211 {
00212 (void)row;
00213 (void)col;
00214 (void)width;
00215 (void)height;
00216 return 0;
00217 }
00218
00219