static int check_frame(struct sxplayer_frame *f, double t, int opt_test_flags) { const double skip = (opt_test_flags & FLAG_SKIP) ? TESTVAL_SKIP : 0; const double trim_duration = (opt_test_flags & FLAG_TRIM_DURATION) ? TESTVAL_TRIM_DURATION : -1; const double playback_time = av_clipd(t, 0, trim_duration < 0 ? DBL_MAX : trim_duration); const double frame_ts = f ? f->ts : -1; const double estimated_time_from_ts = frame_ts - skip; const double diff_ts = fabs(playback_time - estimated_time_from_ts); if (!f) { fprintf(stderr, "no frame obtained for t=%f\n", t); return -1; } if (!(opt_test_flags & FLAG_AUDIO)) { const uint32_t c = *(const uint32_t *)f->data; const int r = c >> (N+16) & 0xf; const int g = c >> (N+ 8) & 0xf; const int b = c >> (N+ 0) & 0xf; const int frame_id = r<<(N*2) | g<<N | b; const double video_ts = frame_id * 1. / SOURCE_FPS; const double estimated_time_from_color = video_ts - skip; const double diff_color = fabs(playback_time - estimated_time_from_color); if (diff_color > 1./SOURCE_FPS) { fprintf(stderr, "requested t=%f (clipped to %f with trim_duration=%f),\n" "got video_ts=%f (frame id #%d), corresponding to t=%f (with skip=%f)\n" "diff_color: %f\n", t, playback_time, trim_duration, video_ts, frame_id, estimated_time_from_color, skip, diff_color); return -1; } } if (diff_ts > 1./SOURCE_FPS) { fprintf(stderr, "requested t=%f (clipped to %f with trim_duration=%f),\n" "got frame_ts=%f, corresponding to t=%f (with skip=%f)\n" "diff_ts: %f\n", t, playback_time, trim_duration, frame_ts, estimated_time_from_ts, skip, diff_ts); return -1; } return 0; }
static void filter_dblp(void **d, void **p, const void **s, int nb_samples, int channels, float mult, int clip) { int n, c; for (c = 0; c < channels; c++) { const double *src = s[c]; double *dst = d[c]; double *prv = p[c]; for (n = 0; n < nb_samples; n++) { double current = src[n]; dst[n] = current + (current - prv[0]) * mult; prv[0] = current; if (clip) { dst[n] = av_clipd(dst[n], -1, 1); } } } }
static int output_single_frame(AVFilterContext *ctx, AVFrame *in, double *var_values, int i, double *zoom, double *dx, double *dy) { ZPContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; int64_t pts = s->frame_count; int k, x, y, w, h, ret = 0; uint8_t *input[4]; int px[4], py[4]; AVFrame *out; var_values[VAR_PX] = s->x; var_values[VAR_PY] = s->y; var_values[VAR_PZOOM] = s->prev_zoom; var_values[VAR_PDURATION] = s->prev_nb_frames; var_values[VAR_TIME] = pts * av_q2d(outlink->time_base); var_values[VAR_FRAME] = i; var_values[VAR_ON] = outlink->frame_count + 1; if ((ret = av_expr_parse_and_eval(zoom, s->zoom_expr_str, var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) return ret; *zoom = av_clipd(*zoom, 1, 10); var_values[VAR_ZOOM] = *zoom; w = in->width * (1.0 / *zoom); h = in->height * (1.0 / *zoom); if ((ret = av_expr_parse_and_eval(dx, s->x_expr_str, var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) return ret; x = *dx = av_clipd(*dx, 0, FFMAX(in->width - w, 0)); var_values[VAR_X] = *dx; x &= ~((1 << s->desc->log2_chroma_w) - 1); if ((ret = av_expr_parse_and_eval(dy, s->y_expr_str, var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) return ret; y = *dy = av_clipd(*dy, 0, FFMAX(in->height - h, 0)); var_values[VAR_Y] = *dy; y &= ~((1 << s->desc->log2_chroma_h) - 1); out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { ret = AVERROR(ENOMEM); return ret; } px[1] = px[2] = AV_CEIL_RSHIFT(x, s->desc->log2_chroma_w); px[0] = px[3] = x; py[1] = py[2] = AV_CEIL_RSHIFT(y, s->desc->log2_chroma_h); py[0] = py[3] = y; s->sws = sws_alloc_context(); if (!s->sws) { ret = AVERROR(ENOMEM); return ret; } for (k = 0; in->data[k]; k++) input[k] = in->data[k] + py[k] * in->linesize[k] + px[k]; av_opt_set_int(s->sws, "srcw", w, 0); av_opt_set_int(s->sws, "srch", h, 0); av_opt_set_int(s->sws, "src_format", in->format, 0); av_opt_set_int(s->sws, "dstw", outlink->w, 0); av_opt_set_int(s->sws, "dsth", outlink->h, 0); av_opt_set_int(s->sws, "dst_format", outlink->format, 0); av_opt_set_int(s->sws, "sws_flags", SWS_BICUBIC, 0); if ((ret = sws_init_context(s->sws, NULL, NULL)) < 0) return ret; sws_scale(s->sws, (const uint8_t *const *)&input, in->linesize, 0, h, out->data, out->linesize); out->pts = pts; s->frame_count++; ret = ff_filter_frame(outlink, out); sws_freeContext(s->sws); s->sws = NULL; s->current_frame++; return ret; }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; ZPContext *s = ctx->priv; double var_values[VARS_NB], nb_frames, zoom, dx, dy; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(in->format); AVFrame *out; int i, k, x, y, w, h, ret = 0; var_values[VAR_IN_W] = var_values[VAR_IW] = in->width; var_values[VAR_IN_H] = var_values[VAR_IH] = in->height; var_values[VAR_OUT_W] = var_values[VAR_OW] = s->w; var_values[VAR_OUT_H] = var_values[VAR_OH] = s->h; var_values[VAR_IN] = inlink->frame_count + 1; var_values[VAR_ON] = outlink->frame_count + 1; var_values[VAR_PX] = s->x; var_values[VAR_PY] = s->y; var_values[VAR_X] = 0; var_values[VAR_Y] = 0; var_values[VAR_PZOOM] = s->prev_zoom; var_values[VAR_ZOOM] = 1; var_values[VAR_PDURATION] = s->prev_nb_frames; var_values[VAR_A] = (double) in->width / in->height; var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; var_values[VAR_HSUB] = 1 << desc->log2_chroma_w; var_values[VAR_VSUB] = 1 << desc->log2_chroma_h; if ((ret = av_expr_parse_and_eval(&nb_frames, s->duration_expr_str, var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail; var_values[VAR_DURATION] = nb_frames; for (i = 0; i < nb_frames; i++) { int px[4]; int py[4]; uint8_t *input[4]; int64_t pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base) + s->frame_count; var_values[VAR_TIME] = pts * av_q2d(outlink->time_base); var_values[VAR_FRAME] = i; var_values[VAR_ON] = outlink->frame_count + 1; if ((ret = av_expr_parse_and_eval(&zoom, s->zoom_expr_str, var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail; zoom = av_clipd(zoom, 1, 10); var_values[VAR_ZOOM] = zoom; w = in->width * (1.0 / zoom); h = in->height * (1.0 / zoom); if ((ret = av_expr_parse_and_eval(&dx, s->x_expr_str, var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail; x = dx = av_clipd(dx, 0, FFMAX(in->width - w, 0)); var_values[VAR_X] = dx; x &= ~((1 << desc->log2_chroma_w) - 1); if ((ret = av_expr_parse_and_eval(&dy, s->y_expr_str, var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail; y = dy = av_clipd(dy, 0, FFMAX(in->height - h, 0)); var_values[VAR_Y] = dy; y &= ~((1 << desc->log2_chroma_h) - 1); out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { ret = AVERROR(ENOMEM); goto fail; } px[1] = px[2] = FF_CEIL_RSHIFT(x, desc->log2_chroma_w); px[0] = px[3] = x; py[1] = py[2] = FF_CEIL_RSHIFT(y, desc->log2_chroma_h); py[0] = py[3] = y; s->sws = sws_alloc_context(); if (!s->sws) { ret = AVERROR(ENOMEM); goto fail; } for (k = 0; in->data[k]; k++) input[k] = in->data[k] + py[k] * in->linesize[k] + px[k]; av_opt_set_int(s->sws, "srcw", w, 0); av_opt_set_int(s->sws, "srch", h, 0); av_opt_set_int(s->sws, "src_format", in->format, 0); av_opt_set_int(s->sws, "dstw", outlink->w, 0); av_opt_set_int(s->sws, "dsth", outlink->h, 0); av_opt_set_int(s->sws, "dst_format", outlink->format, 0); av_opt_set_int(s->sws, "sws_flags", SWS_BICUBIC, 0); if ((ret = sws_init_context(s->sws, NULL, NULL)) < 0) goto fail; sws_scale(s->sws, (const uint8_t *const *)&input, in->linesize, 0, h, out->data, out->linesize); out->pts = pts; s->frame_count++; ret = ff_filter_frame(outlink, out); if (ret < 0) break; sws_freeContext(s->sws); s->sws = NULL; } s->x = dx; s->y = dy; s->prev_zoom = zoom; s->prev_nb_frames = nb_frames; fail: sws_freeContext(s->sws); s->sws = NULL; av_frame_free(&in); return ret; }
static int plot_freqs(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; ShowFreqsContext *s = ctx->priv; const int win_size = s->win_size; char *colors, *color, *saveptr = NULL; AVFrame *out; int ch, n; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); for (n = 0; n < outlink->h; n++) memset(out->data[0] + out->linesize[0] * n, 0, outlink->w * 4); /* fill FFT input with the number of samples available */ for (ch = 0; ch < s->nb_channels; ch++) { const float *p = (float *)in->extended_data[ch]; for (n = 0; n < in->nb_samples; n++) { s->fft_data[ch][n].re = p[n] * s->window_func_lut[n]; s->fft_data[ch][n].im = 0; } for (; n < win_size; n++) { s->fft_data[ch][n].re = 0; s->fft_data[ch][n].im = 0; } } /* run FFT on each samples set */ for (ch = 0; ch < s->nb_channels; ch++) { av_fft_permute(s->fft, s->fft_data[ch]); av_fft_calc(s->fft, s->fft_data[ch]); } #define RE(x, ch) s->fft_data[ch][x].re #define IM(x, ch) s->fft_data[ch][x].im #define M(a, b) (sqrt((a) * (a) + (b) * (b))) colors = av_strdup(s->colors); if (!colors) { av_frame_free(&out); return AVERROR(ENOMEM); } for (ch = 0; ch < s->nb_channels; ch++) { uint8_t fg[4] = { 0xff, 0xff, 0xff, 0xff }; int prev_y = -1, f; double a; color = av_strtok(ch == 0 ? colors : NULL, " |", &saveptr); if (color) av_parse_color(fg, color, -1, ctx); a = av_clipd(M(RE(0, ch), 0) / s->scale, 0, 1); plot_freq(s, ch, a, 0, fg, &prev_y, out, outlink); for (f = 1; f < s->nb_freq; f++) { a = av_clipd(M(RE(f, ch), IM(f, ch)) / s->scale, 0, 1); plot_freq(s, ch, a, f, fg, &prev_y, out, outlink); } } av_free(colors); out->pts = in->pts; return ff_filter_frame(outlink, out); }
static inline void plot_freq(ShowFreqsContext *s, int ch, double a, int f, uint8_t fg[4], int *prev_y, AVFrame *out, AVFilterLink *outlink) { const int w = s->w; const float avg = s->avg_data[ch][f]; const float bsize = get_bsize(s, f); const int sx = get_sx(s, f); int end = outlink->h; int x, y, i; switch(s->ascale) { case AS_SQRT: a = 1.0 - sqrt(a); break; case AS_CBRT: a = 1.0 - cbrt(a); break; case AS_LOG: a = log(av_clipd(a, 1e-6, 1)) / log(1e-6); break; case AS_LINEAR: a = 1.0 - a; break; } switch (s->cmode) { case COMBINED: y = a * outlink->h - 1; break; case SEPARATE: end = (outlink->h / s->nb_channels) * (ch + 1); y = (outlink->h / s->nb_channels) * ch + a * (outlink->h / s->nb_channels) - 1; break; } if (y < 0) return; switch (s->avg) { case 0: y = s->avg_data[ch][f] = !outlink->frame_count ? y : FFMIN(avg, y); break; case 1: break; default: s->avg_data[ch][f] = avg + y * (y - avg) / (FFMIN(outlink->frame_count + 1, s->avg) * y); y = s->avg_data[ch][f]; break; } switch(s->mode) { case LINE: if (*prev_y == -1) { *prev_y = y; } if (y <= *prev_y) { for (x = sx + 1; x < sx + bsize && x < w; x++) draw_dot(out, x, y, fg); for (i = y; i <= *prev_y; i++) draw_dot(out, sx, i, fg); } else { for (i = *prev_y; i <= y; i++) draw_dot(out, sx, i, fg); for (x = sx + 1; x < sx + bsize && x < w; x++) draw_dot(out, x, i - 1, fg); } *prev_y = y; break; case BAR: for (x = sx; x < sx + bsize && x < w; x++) for (i = y; i < end; i++) draw_dot(out, x, i, fg); break; case DOT: for (x = sx; x < sx + bsize && x < w; x++) draw_dot(out, x, y, fg); break; } }