mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-26 09:12:33 +00:00
avfilter/vf_xmedian: refactor slice function
This commit is contained in:
parent
b40419c99b
commit
cca6fe7fe0
@ -45,7 +45,7 @@ typedef struct XMedianContext {
|
||||
int depth;
|
||||
int max;
|
||||
int nb_planes;
|
||||
int linesize[4];
|
||||
int linesizes[4];
|
||||
int width[4];
|
||||
int height[4];
|
||||
|
||||
@ -107,101 +107,70 @@ typedef struct ThreadData {
|
||||
AVFrame **in, *out;
|
||||
} ThreadData;
|
||||
|
||||
static int comparei(const void *p1, const void *p2)
|
||||
static int compare8(const void *p1, const void *p2)
|
||||
{
|
||||
int left = *(const int *)p1;
|
||||
int right = *(const int *)p2;
|
||||
int left = *(const uint8_t *)p1;
|
||||
int right = *(const uint8_t *)p2;
|
||||
return FFDIFFSIGN(left, right);
|
||||
}
|
||||
|
||||
static int median_frames16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||
static int compare16(const void *p1, const void *p2)
|
||||
{
|
||||
XMedianContext *s = ctx->priv;
|
||||
ThreadData *td = arg;
|
||||
AVFrame **in = td->in;
|
||||
AVFrame *out = td->out;
|
||||
const int nb_inputs = s->nb_inputs;
|
||||
const int radius = s->radius;
|
||||
const int index = s->index;
|
||||
int values[256];
|
||||
|
||||
for (int p = 0; p < s->nb_planes; p++) {
|
||||
const int slice_start = (s->height[p] * jobnr) / nb_jobs;
|
||||
const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs;
|
||||
uint16_t *dst = (uint16_t *)(out->data[p] + slice_start * out->linesize[p]);
|
||||
|
||||
if (!((1 << p) & s->planes)) {
|
||||
av_image_copy_plane((uint8_t *)dst, out->linesize[p],
|
||||
in[radius]->data[p] + slice_start * in[radius]->linesize[p],
|
||||
in[radius]->linesize[p],
|
||||
s->linesize[p], slice_end - slice_start);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int y = slice_start; y < slice_end; y++) {
|
||||
for (int x = 0; x < s->width[p]; x++) {
|
||||
for (int i = 0; i < nb_inputs; i++) {
|
||||
const uint16_t *src = (const uint16_t *)(in[i]->data[p] + y * in[i]->linesize[p]);
|
||||
values[i] = src[x];
|
||||
}
|
||||
|
||||
AV_QSORT(values, nb_inputs, int, comparei);
|
||||
if (nb_inputs & 1)
|
||||
dst[x] = values[index];
|
||||
else
|
||||
dst[x] = (values[index] + values[index - 1]) >> 1;
|
||||
}
|
||||
|
||||
dst += out->linesize[p] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
int left = *(const uint16_t *)p1;
|
||||
int right = *(const uint16_t *)p2;
|
||||
return FFDIFFSIGN(left, right);
|
||||
}
|
||||
|
||||
static int median_frames8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||
{
|
||||
XMedianContext *s = ctx->priv;
|
||||
ThreadData *td = arg;
|
||||
AVFrame **in = td->in;
|
||||
AVFrame *out = td->out;
|
||||
const int nb_inputs = s->nb_inputs;
|
||||
const int radius = s->radius;
|
||||
const int index = s->index;
|
||||
int values[256];
|
||||
|
||||
for (int p = 0; p < s->nb_planes; p++) {
|
||||
const int slice_start = (s->height[p] * jobnr) / nb_jobs;
|
||||
const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs;
|
||||
uint8_t *dst = out->data[p] + slice_start * out->linesize[p];
|
||||
|
||||
if (!((1 << p) & s->planes)) {
|
||||
av_image_copy_plane(dst, out->linesize[p],
|
||||
in[radius]->data[p] + slice_start * in[radius]->linesize[p],
|
||||
in[radius]->linesize[p],
|
||||
s->linesize[p], slice_end - slice_start);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int y = slice_start; y < slice_end; y++) {
|
||||
for (int x = 0; x < s->width[p]; x++) {
|
||||
for (int i = 0; i < nb_inputs; i++)
|
||||
values[i] = in[i]->data[p][y * in[i]->linesize[p] + x];
|
||||
|
||||
AV_QSORT(values, nb_inputs, int, comparei);
|
||||
if (nb_inputs & 1)
|
||||
dst[x] = values[index];
|
||||
else
|
||||
dst[x] = (values[index] + values[index - 1]) >> 1;
|
||||
}
|
||||
|
||||
dst += out->linesize[p];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
#define MEDIAN_SLICE(name, type, comparei) \
|
||||
static int median_frames ## name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
|
||||
{ \
|
||||
XMedianContext *s = ctx->priv; \
|
||||
ThreadData *td = arg; \
|
||||
AVFrame **in = td->in; \
|
||||
AVFrame *out = td->out; \
|
||||
const int nb_inputs = s->nb_inputs; \
|
||||
const int radius = s->radius; \
|
||||
const int index = s->index; \
|
||||
type values[256]; \
|
||||
\
|
||||
for (int p = 0; p < s->nb_planes; p++) { \
|
||||
const int slice_start = (s->height[p] * jobnr) / nb_jobs; \
|
||||
const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; \
|
||||
type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
|
||||
ptrdiff_t dst_linesize = out->linesize[p] / sizeof(type); \
|
||||
\
|
||||
if (!((1 << p) & s->planes)) { \
|
||||
av_image_copy_plane((uint8_t *)dst, out->linesize[p], \
|
||||
in[radius]->data[p] + slice_start * in[radius]->linesize[p], \
|
||||
in[radius]->linesize[p], \
|
||||
s->linesizes[p], slice_end - slice_start); \
|
||||
continue; \
|
||||
} \
|
||||
\
|
||||
for (int y = slice_start; y < slice_end; y++) { \
|
||||
for (int x = 0; x < s->width[p]; x++) { \
|
||||
for (int i = 0; i < nb_inputs; i++) { \
|
||||
const type *src = (const type *)(in[i]->data[p] + y * in[i]->linesize[p]); \
|
||||
values[i] = src[x]; \
|
||||
} \
|
||||
\
|
||||
AV_QSORT(values, nb_inputs, type, comparei); \
|
||||
if (nb_inputs & 1) \
|
||||
dst[x] = values[index]; \
|
||||
else \
|
||||
dst[x] = (values[index] + values[index - 1]) >> 1; \
|
||||
} \
|
||||
\
|
||||
dst += dst_linesize; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
MEDIAN_SLICE(8, uint8_t, compare8)
|
||||
MEDIAN_SLICE(16, uint16_t, compare16)
|
||||
|
||||
static int process_frame(FFFrameSync *fs)
|
||||
{
|
||||
AVFilterContext *ctx = fs->parent;
|
||||
@ -267,7 +236,7 @@ static int config_output(AVFilterLink *outlink)
|
||||
else
|
||||
s->median_frames = median_frames16;
|
||||
|
||||
if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
|
||||
if ((ret = av_image_fill_linesizes(s->linesizes, inlink->format, inlink->w)) < 0)
|
||||
return ret;
|
||||
|
||||
s->width[1] = s->width[2] = AV_CEIL_RSHIFT(inlink->w, s->desc->log2_chroma_w);
|
||||
|
Loading…
Reference in New Issue
Block a user