static int filter_frame(AVFilterLink *inlink, AVFrame *in) { HistogramContext *h = inlink->dst->priv; AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; int i, j, k, l, m; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } out->pts = in->pts; for (k = 0; k < 4 && out->data[k]; k++) { const int is_chroma = (k == 1 || k == 2); const int dst_h = AV_CEIL_RSHIFT(outlink->h, (is_chroma ? h->odesc->log2_chroma_h : 0)); const int dst_w = AV_CEIL_RSHIFT(outlink->w, (is_chroma ? h->odesc->log2_chroma_w : 0)); if (h->histogram_size <= 256) { for (i = 0; i < dst_h ; i++) memset(out->data[h->odesc->comp[k].plane] + i * out->linesize[h->odesc->comp[k].plane], h->bg_color[k], dst_w); } else { const int mult = h->mult; for (i = 0; i < dst_h ; i++) for (j = 0; j < dst_w; j++) AV_WN16(out->data[h->odesc->comp[k].plane] + i * out->linesize[h->odesc->comp[k].plane] + j * 2, h->bg_color[k] * mult); } } for (m = 0, k = 0; k < h->ncomp; k++) { const int p = h->desc->comp[k].plane; const int height = h->planeheight[p]; const int width = h->planewidth[p]; double max_hval_log; unsigned max_hval = 0; int start; if (!((1 << k) & h->components)) continue; start = m++ * (h->level_height + h->scale_height) * h->display_mode; if (h->histogram_size <= 256) { for (i = 0; i < height; i++) { const uint8_t *src = in->data[p] + i * in->linesize[p]; for (j = 0; j < width; j++) h->histogram[src[j]]++; } } else { for (i = 0; i < height; i++) { const uint16_t *src = (const uint16_t *)(in->data[p] + i * in->linesize[p]); for (j = 0; j < width; j++) h->histogram[src[j]]++; } } for (i = 0; i < h->histogram_size; i++) max_hval = FFMAX(max_hval, h->histogram[i]); max_hval_log = log2(max_hval + 1); for (i = 0; i < outlink->w; i++) { int col_height; if (h->levels_mode) col_height = lrint(h->level_height * (1. - (log2(h->histogram[i] + 1) / max_hval_log))); else col_height = h->level_height - (h->histogram[i] * (int64_t)h->level_height + max_hval - 1) / max_hval; if (h->histogram_size <= 256) { for (j = h->level_height - 1; j >= col_height; j--) { if (h->display_mode) { for (l = 0; l < h->dncomp; l++) out->data[l][(j + start) * out->linesize[l] + i] = h->fg_color[l]; } else { out->data[p][(j + start) * out->linesize[p] + i] = 255; } } for (j = h->level_height + h->scale_height - 1; j >= h->level_height; j--) out->data[p][(j + start) * out->linesize[p] + i] = i; } else { const int mult = h->mult; for (j = h->level_height - 1; j >= col_height; j--) { if (h->display_mode) { for (l = 0; l < h->dncomp; l++) AV_WN16(out->data[l] + (j + start) * out->linesize[l] + i * 2, h->fg_color[l] * mult); } else { AV_WN16(out->data[p] + (j + start) * out->linesize[p] + i * 2, 255 * mult); } } for (j = h->level_height + h->scale_height - 1; j >= h->level_height; j--) AV_WN16(out->data[p] + (j + start) * out->linesize[p] + i * 2, i); } } memset(h->histogram, 0, h->histogram_size * sizeof(unsigned)); } av_frame_free(&in); return ff_filter_frame(outlink, out); }
static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int pd) { const uint16_t * const *src = (const uint16_t * const *)in->data; const int slinesizex = in->linesize[s->x] / 2; const int slinesizey = in->linesize[s->y] / 2; const int slinesized = in->linesize[pd] / 2; const int dlinesize = out->linesize[0] / 2; const int intensity = s->intensity; const int px = s->x, py = s->y; const int h = s->planeheight[py]; const int w = s->planewidth[px]; const uint16_t *spx = src[px]; const uint16_t *spy = src[py]; const uint16_t *spd = src[pd]; const int hsub = s->hsub; const int vsub = s->vsub; uint16_t **dst = (uint16_t **)out->data; uint16_t *dpx = dst[px]; uint16_t *dpy = dst[py]; uint16_t *dpd = dst[pd]; const int max = s->size - 1; const int mid = s->size / 2; const int tmin = s->tmin; const int tmax = s->tmax; int i, j, k; for (k = 0; k < 4 && dst[k]; k++) { for (i = 0; i < out->height ; i++) for (j = 0; j < out->width; j++) AV_WN16(out->data[k] + i * out->linesize[k] + j * 2, (s->mode == COLOR || s->mode == COLOR5) && k == s->pd ? 0 : s->bg_color[k]); } switch (s->mode) { case COLOR: case COLOR5: case GRAY: if (s->is_yuv) { for (i = 0; i < h; i++) { const int iwx = i * slinesizex; const int iwy = i * slinesizey; const int iwd = i * slinesized; for (j = 0; j < w; j++) { const int x = FFMIN(spx[iwx + j], max); const int y = FFMIN(spy[iwy + j], max); const int z = spd[iwd + j]; const int pos = y * dlinesize + x; if (z < tmin || z > tmax) continue; dpd[pos] = FFMIN(dpd[pos] + intensity, max); if (dst[3]) dst[3][pos] = max; } } } else { for (i = 0; i < h; i++) { const int iwx = i * slinesizex; const int iwy = i * slinesizey; const int iwd = i * slinesized; for (j = 0; j < w; j++) { const int x = FFMIN(spx[iwx + j], max); const int y = FFMIN(spy[iwy + j], max); const int z = spd[iwd + j]; const int pos = y * dlinesize + x; if (z < tmin || z > tmax) continue; dst[0][pos] = FFMIN(dst[0][pos] + intensity, max); dst[1][pos] = FFMIN(dst[1][pos] + intensity, max); dst[2][pos] = FFMIN(dst[2][pos] + intensity, max); if (dst[3]) dst[3][pos] = max; } } } break; case COLOR2: if (s->is_yuv) { for (i = 0; i < h; i++) { const int iw1 = i * slinesizex; const int iw2 = i * slinesizey; const int iwd = i * slinesized; for (j = 0; j < w; j++) { const int x = FFMIN(spx[iw1 + j], max); const int y = FFMIN(spy[iw2 + j], max); const int z = spd[iwd + j]; const int pos = y * dlinesize + x; if (z < tmin || z > tmax) continue; if (!dpd[pos]) dpd[pos] = FFABS(mid - x) + FFABS(mid - y); dpx[pos] = x; dpy[pos] = y; if (dst[3]) dst[3][pos] = max; } } } else { for (i = 0; i < h; i++) { const int iw1 = i * slinesizex; const int iw2 = i * slinesizey; const int iwd = i * slinesized; for (j = 0; j < w; j++) { const int x = FFMIN(spx[iw1 + j], max); const int y = FFMIN(spy[iw2 + j], max); const int z = spd[iwd + j]; const int pos = y * dlinesize + x; if (z < tmin || z > tmax) continue; if (!dpd[pos]) dpd[pos] = FFMIN(x + y, max); dpx[pos] = x; dpy[pos] = y; if (dst[3]) dst[3][pos] = max; } } } break; case COLOR3: for (i = 0; i < h; i++) { const int iw1 = i * slinesizex; const int iw2 = i * slinesizey; const int iwd = i * slinesized; for (j = 0; j < w; j++) { const int x = FFMIN(spx[iw1 + j], max); const int y = FFMIN(spy[iw2 + j], max); const int z = spd[iwd + j]; const int pos = y * dlinesize + x; if (z < tmin || z > tmax) continue; dpd[pos] = FFMIN(max, dpd[pos] + intensity); dpx[pos] = x; dpy[pos] = y; if (dst[3]) dst[3][pos] = max; } } break; case COLOR4: for (i = 0; i < in->height; i++) { const int iwx = (i >> vsub) * slinesizex; const int iwy = (i >> vsub) * slinesizey; const int iwd = i * slinesized; for (j = 0; j < in->width; j++) { const int x = FFMIN(spx[iwx + (j >> hsub)], max); const int y = FFMIN(spy[iwy + (j >> hsub)], max); const int z = spd[iwd + j]; const int pos = y * dlinesize + x; if (z < tmin || z > tmax) continue; dpd[pos] = FFMAX(z, dpd[pos]); dpx[pos] = x; dpy[pos] = y; if (dst[3]) dst[3][pos] = max; } } break; default: av_assert0(0); } envelope16(s, out); if (s->mode == COLOR) { for (i = 0; i < out->height; i++) { for (j = 0; j < out->width; j++) { if (!dpd[i * dlinesize + j]) { dpx[i * dlinesize + j] = j; dpy[i * dlinesize + j] = i; dpd[i * dlinesize + j] = mid; } } } } else if (s->mode == COLOR5) { for (i = 0; i < out->height; i++) { for (j = 0; j < out->width; j++) { if (!dpd[i * dlinesize + j]) { dpx[i * dlinesize + j] = j; dpy[i * dlinesize + j] = i; dpd[i * dlinesize + j] = mid * M_SQRT2 - hypot(i - mid, j - mid); } } } } }