From: Hector Martin Date: Sat, 12 Mar 2011 16:16:34 +0000 (+0100) Subject: Tracer infrastructure rewrite X-Git-Url: https://gitweb.aptx.org/?a=commitdiff_plain;h=057016cebded680284bf3ff2d7bc7f90023832e2;p=openlase.git Tracer infrastructure rewrite - Beginnings of new API to support more flexible tracing - Traced points now go to a buffer (can be displayed several times) - Now maintains a start point buffer to only scan frame once - Get rid of the spiral frame scanning stuff - Playvid now traces once per input frame, not once per output frame Regression: overdraw went away for now Regression: the avstream/slides stuff is broken for now --- diff --git a/tools/playvid.c b/tools/playvid.c index a4474bc..c400ec7 100644 --- a/tools/playvid.c +++ b/tools/playvid.c @@ -426,7 +426,20 @@ int main (int argc, char *argv[]) OLFrameInfo info; - void *tmp = malloc(pCodecCtx->width * pCodecCtx->height*2); + OLTraceParams tparams = { + .mode = OL_TRACE_THRESHOLD, + .width = pCodecCtx->width, + .height = pCodecCtx->height, + .sigma = 0 + }; + + OLTraceCtx *trace_ctx; + + OLTraceResult result; + + memset(&result, 0, sizeof(result)); + + olTraceInit(&trace_ctx, &tparams); while(GetNextFrame(pFormatCtx, pCodecCtx, videoStream, &frame)) { if (inf == 0) @@ -439,36 +452,51 @@ int main (int argc, char *argv[]) } vidtime += frametime; + int thresh; + int obj; + int bsum = 0; + int c; + for (c=edge_off; c<(pCodecCtx->width-edge_off); c++) { + bsum += frame->data[0][c+edge_off*frame->linesize[0]]; + bsum += frame->data[0][c+(pCodecCtx->height-edge_off-1)*frame->linesize[0]]; + } + for (c=edge_off; c<(pCodecCtx->height-edge_off); c++) { + bsum += frame->data[0][edge_off+c*frame->linesize[0]]; + bsum += frame->data[0][(c+1)*frame->linesize[0]-1-edge_off]; + } + bsum /= (2*(pCodecCtx->width+pCodecCtx->height)); + if (bg_white == -1) + bg_white = bsum > 128; + if (bg_white && bsum < sw_dark) + bg_white = 0; + if (!bg_white && bsum > sw_light) + bg_white = 1; + + if (bg_white) + thresh = thresh_light; + else + thresh = thresh_dark; + + tparams.threshold = thresh; + olTraceReInit(&trace_ctx, &tparams); + olTraceFree(&result); + obj = olTrace(trace_ctx, frame->data[0], frame->linesize[0], &result); + do { - int thresh; - int obj; - int bsum = 0; - int c; - for (c=edge_off; c<(pCodecCtx->width-edge_off); c++) { - bsum += frame->data[0][c+edge_off*frame->linesize[0]]; - bsum += frame->data[0][c+(pCodecCtx->height-edge_off-1)*frame->linesize[0]]; - } - for (c=edge_off; c<(pCodecCtx->height-edge_off); c++) { - bsum += frame->data[0][edge_off+c*frame->linesize[0]]; - bsum += frame->data[0][(c+1)*frame->linesize[0]-1-edge_off]; + int i, j; + for (i = 0; i < result.count; i++) { + OLTraceObject *o = &result.objects[i]; + olBegin(OL_POINTS); + OLTracePoint *p = o->points; + for (j = 0; j < o->count; j++) { + if (j % decimate == 0) + olVertex(p->x, p->y, C_WHITE); + p++; + } + olEnd(); } - bsum /= (2*(pCodecCtx->width+pCodecCtx->height)); - if (bg_white == -1) - bg_white = bsum > 128; - if (bg_white && bsum < sw_dark) - bg_white = 0; - if (!bg_white && bsum > sw_light) - bg_white = 1; - - if (bg_white) - thresh = thresh_light; - else - thresh = thresh_dark; - - obj = trace(frame->data[0], tmp, thresh, - pCodecCtx->width, pCodecCtx->height, frame->linesize[0], decimate); - - ftime = olRenderFrame(100); + + ftime = olRenderFrame(200); olGetFrameInfo(&info); frames++; time += ftime; @@ -485,7 +513,7 @@ int main (int argc, char *argv[]) } for(i=0;i #include #include +#include #include "trace.h" +struct OLTraceCtx { + OLTraceParams p; + uint16_t *tracebuf; + + OLTracePoint *sb; + OLTracePoint *sbp; + OLTracePoint *sb_end; + unsigned int sb_size; + + OLTracePoint *pb; + OLTracePoint *pbp; + OLTracePoint *pb_end; + unsigned int pb_size; +}; + #define ABS(a) ((a)<0?(-(a)):(a)) -#define OVERDRAW 6 +#define OVERDRAW 8 //#define DEBUG @@ -60,14 +76,40 @@ static const int tdy[8] = { 0, -1, -1, -1, 0, 1, 1, 1 }; static const int tdx2[16] = { 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2, -1, 0, 1, 2, 2 }; static const int tdy2[16] = { 0, -1, -2, -2, -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1 }; -static int trace_pixels(uint8_t *buf, int s, int decimate, int *cx, int *cy, int flag) +static inline void add_bufpoint(OLTraceCtx *ctx, uint32_t x, uint32_t y) { - int i; - int x = *cx; - int y = *cy; + ctx->pbp->x = x; + ctx->pbp->y = y; + ctx->pbp++; + if (ctx->pbp == ctx->pb_end) { + int cur = ctx->pbp - ctx->pb; + ctx->pb_size *= 2; + ctx->pb = realloc(ctx->pb, ctx->pb_size * sizeof(*ctx->pb)); + ctx->pbp = ctx->pb + cur; + ctx->pb_end = ctx->pb + ctx->pb_size; + } +} + +static inline void add_startpoint(OLTraceCtx *ctx, uint32_t x, uint32_t y) +{ + ctx->sbp->x = x; + ctx->sbp->y = y; + ctx->sbp++; + if (ctx->sbp == ctx->sb_end) { + int cur = ctx->sbp - ctx->sb; + ctx->sb_size *= 2; + ctx->sb = realloc(ctx->sb, ctx->sb_size * sizeof(*ctx->sb)); + ctx->sbp = ctx->sb + cur; + ctx->sb_end = ctx->sb + ctx->sb_size; + } +} + +static int trace_pixels(OLTraceCtx *ctx, uint16_t *buf, int s, int output, uint32_t *cx, uint32_t *cy, uint16_t flag) +{ + unsigned int x = *cx; + unsigned int y = *cy; int iters = 0; int start = 1; - int div = 0; #ifdef DEBUG if (decimate != -1) { pc = pc + 47; @@ -76,24 +118,12 @@ static int trace_pixels(uint8_t *buf, int s, int decimate, int *cx, int *cy, int #endif int lidx = 0; int dir = 0; - int bufx[OVERDRAW], bufy[OVERDRAW]; - while (1) { int idx = y*s+x; - if (decimate != -1) { - if (div == 0) { - if (iters < OVERDRAW) { - bufx[iters] = x; - bufy[iters] = y; - } - olVertex(x, y, C_WHITE); - iters++; - } - div = (div+1)%decimate; - } else { - iters++; - } + if (output) + add_bufpoint(ctx, x, y); + iters++; buf[idx] &= ~flag; if (start) { // just pick any direction the first time @@ -166,143 +196,188 @@ static int trace_pixels(uint8_t *buf, int s, int decimate, int *cx, int *cy, int } } #ifdef DEBUG - if (decimate != -1) { - if (!start) - dbg[idx][2] = 96+pc; - } + if (!start) + dbg[idx][2] = 96+pc; #endif start = 0; lidx = idx; } #ifdef DEBUG /* - if (decimate != -1) { - dbg[lidx][0] = 255; - dbg[lidx][1] = 0; - dbg[lidx][2] = 0; - } + dbg[lidx][0] = 255; + dbg[lidx][1] = 0; + dbg[lidx][2] = 0; */ #endif - if (decimate != -1 && iters) { - if (ABS(*cx-x) <= 2 && ABS(*cy-y) <= 2 && iters > 10) { - if (iters > OVERDRAW) - iters = OVERDRAW; - for (i=0; ip = *params; + ctx->tracebuf = malloc(ctx->p.width * ctx->p.height * sizeof(*ctx->tracebuf)); + + ctx->sb_size = ctx->p.width * 16; + ctx->sb = malloc(ctx->sb_size * sizeof(*ctx->sb)); + ctx->sbp = ctx->sb; + ctx->sb_end = ctx->sb + ctx->sb_size; + + ctx->pb_size = ctx->p.width * 16; + ctx->pb = malloc(ctx->pb_size * sizeof(*ctx->pb)); + ctx->pbp = ctx->pb; + ctx->pb_end = ctx->pb + ctx->pb_size; + + + *pctx = ctx; + return 0; +} +int olTraceReInit(OLTraceCtx **ctx, OLTraceParams *params) +{ + (*ctx)->p = *params; + return 0; +} + +void olTraceFree(OLTraceResult *result) +{ + if (!result) + return; + if (result->objects) { + if (result->objects[0].points) + free(result->objects[0].points); + free(result->objects); + } +} + + +void olTraceDeinit(OLTraceCtx *ctx) +{ +} + +static void find_edges_thresh(OLTraceCtx *ctx, uint8_t *src, unsigned int stride) +{ + unsigned int thresh = ctx->p.threshold; + uint32_t x, y, w, h; + w = ctx->p.width; + h = ctx->p.height; for (y=2; y thresh && (!(field[idx-s] > thresh) - || !(field[idx-1] > thresh))) { - tmp[idx] = 255; + int idx = y*stride+x; + int oidx = y*w+x; + if (src[idx] > thresh && (!(src[idx-stride] > thresh) + || !(src[idx-1] > thresh))) { + ctx->tracebuf[oidx] = 0xFFFF; + add_startpoint(ctx, x, y); #ifdef DEBUG - dbg[idx][0] = 64; - dbg[idx][1] = 64; - dbg[idx][2] = 64; + dbg[oidx][0] = 64; + dbg[oidx][1] = 64; + dbg[oidx][2] = 64; #endif } - if (field[idx] <= thresh && (!(field[idx-s] <= thresh) - || !(field[idx-1] <= thresh))) { - tmp[idx] = 255; + if (src[idx] <= thresh && (!(src[idx-stride] <= thresh) + || !(src[idx-1] <= thresh))) { + ctx->tracebuf[oidx] = 0xFFFF; + add_startpoint(ctx, x, y); #ifdef DEBUG - dbg[idx][0] = 64; - dbg[idx][1] = 64; - dbg[idx][2] = 64; + dbg[oidx][0] = 64; + dbg[oidx][1] = 64; + dbg[oidx][2] = 64; #endif } } } +} - int scandir = 0; - int total = h*w; - int minx = 0, miny = 0; - int maxx = w-1, maxy = h-1; +int olTrace(OLTraceCtx *ctx, uint8_t *src, unsigned int stride, OLTraceResult *result) +{ + uint32_t x, y; + int i; + unsigned int objects = 0; + int w = ctx->p.width; + int h = ctx->p.height; - x = 0; - y = 0; - while (total--) - { + memset(ctx->tracebuf, 0, w*h*2); +#ifdef DEBUG + memset(dbg, 0, 3*w*h); +#endif + + ctx->sbp = ctx->sb; + ctx->pbp = ctx->pb; + + find_edges_thresh(ctx, src, stride); + + OLTracePoint *ps = ctx->sb; + while (ps != ctx->sbp) { + x = ps->x; + y = ps->y; + ps++; int flg = 1; - while (tmp[y*s+x] & 128) { - int tx = x, ty = y; + while (ctx->tracebuf[y*w+x] & 0x8000) { + uint32_t tx = x, ty = y; if (flg != 64) flg <<= 1; - trace_pixels(tmp, s, -1, &tx, &ty, flg); + trace_pixels(ctx, ctx->tracebuf, w, 0, &tx, &ty, flg); #ifdef DEBUG - int sx = tx, sy = ty; + uint32_t sx = tx, sy = ty; #endif - olBegin(OL_POINTS); - if (trace_pixels(tmp, s, decimate, &tx, &ty, 255)) + if (trace_pixels(ctx, ctx->tracebuf, w, 1, &tx, &ty, 0xFFFF)) { + ctx->pbp[-1].x |= 1<<31; objects++; - olEnd(); + } #ifdef DEBUG - dbg[y*s+x][0] = 255; - dbg[y*s+x][1] = 255; - dbg[y*s+x][2] = 0; + dbg[y*w+x][0] = 255; + dbg[y*w+x][1] = 255; + dbg[y*w+x][2] = 0; - dbg[sy*s+sx][0] = 0; - dbg[sy*s+sx][1] = 255; - dbg[sy*s+sx][2] = 255; + dbg[sy*w+sx][0] = 0; + dbg[sy*w+sx][1] = 255; + dbg[sy*w+sx][2] = 255; - dbg[ty*s+tx][0] = 255; - dbg[ty*s+tx][1] = 0; - dbg[ty*s+tx][2] = 0; + dbg[ty*w+tx][0] = 255; + dbg[ty*w+tx][1] = 0; + dbg[ty*w+tx][2] = 0; printf("%d: %d,%d %d,%d %d,%d\n", tframe, x, y, sx, sy, tx, ty); #endif } - switch(scandir) { - case 0: - x++; - if (x > maxx) { - x--; y++; maxx--; scandir++; - } - break; - case 1: - y++; - if (y > maxy) { - y--; x--; maxy--; scandir++; - } - break; - case 2: - x--; - if (x < minx) { - x++; y--; minx++; scandir++; - } - break; - case 3: - y--; - if (y < miny) { - y++; x++; miny++; scandir=0; - } - break; - } } #ifdef DEBUG char name[64]; sprintf(name, "dump%05d.bin", tframe++); FILE *f = fopen(name,"wb"); - fwrite(dbg, h, s*3, f); + fwrite(dbg, h, w*3, f); fclose(f); #endif //printf("Dup'd: %d\n", dpcnt); + + result->count = objects; + if (objects == 0) { + result->objects = NULL; + } else { + OLTracePoint *p, *q; + q = malloc((ctx->pbp - ctx->pb) * sizeof(*q)); + result->objects = malloc(objects * sizeof(*result->objects)); + OLTraceObject *o = result->objects; + o->count = 0; + o->points = q; + for (p = ctx->pb; p != ctx->pbp; p++) { + q->x = p->x & ~(1<<31); + q->y = p->y; + q++; + o->count++; + if (p->x & (1<<31)) { + o++; + if ((p+1) != ctx->pbp) { + o->count = 0; + o->points = q; + } + } + } + } + return objects; } - diff --git a/tools/trace.h b/tools/trace.h index 1551a89..c8fb189 100644 --- a/tools/trace.h +++ b/tools/trace.h @@ -20,6 +20,40 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #ifndef TRACE_H #define TRACE_H -int trace(uint8_t *field, uint8_t *tmp, uint8_t thresh, int width, int height, int stride, int decimate); +typedef struct OLTraceCtx OLTraceCtx; -#endif \ No newline at end of file +typedef enum { + OL_TRACE_THRESHOLD, + OL_TRACE_CANNY +} OLTraceMode; + +typedef struct { + OLTraceMode mode; + unsigned int width, height; + float sigma; + unsigned int threshold; +} OLTraceParams; + +typedef struct { + uint32_t x, y; +} OLTracePoint; + +typedef struct { + unsigned int count; + OLTracePoint *points; +} OLTraceObject; + +typedef struct { + unsigned int count; + OLTraceObject *objects; +} OLTraceResult; + +int olTraceInit(OLTraceCtx **ctx, OLTraceParams *params); +int olTraceReInit(OLTraceCtx **ctx, OLTraceParams *params); + +int olTrace(OLTraceCtx *ctx, uint8_t *src, unsigned int stride, OLTraceResult *result); +void olTraceFree(OLTraceResult *result); + +void olTraceDeinit(OLTraceCtx *ctx); + +#endif