128#define OFFSET(x) offsetof(MorphoContext, x)
129#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM
142 {
"first",
"process only first structure, ignore rest", 0,
AV_OPT_TYPE_CONST, {.i64=0}, 0, 0,
FLAGS, .unit =
"str" },
171static void min_fun(uint8_t *
c,
const uint8_t *
a,
const uint8_t *
b,
int x)
173 for (
int i = 0;
i < x;
i++)
179 for (
int i = 0;
i < x;
i++)
183static void max_fun(uint8_t *
c,
const uint8_t *
a,
const uint8_t *
b,
int x)
185 for (
int i = 0;
i < x;
i++)
191 for (
int i = 0;
i < x;
i++)
197 for (
int i = 0;
i < x;
i++)
203 for (
int i = 0;
i < x;
i++)
207static void min16_fun(uint8_t *cc,
const uint8_t *aa,
const uint8_t *bb,
int x)
209 const uint16_t *
a = (
const uint16_t *)aa;
210 const uint16_t *
b = (
const uint16_t *)bb;
211 uint16_t *
c = (uint16_t *)cc;
213 for (
int i = 0;
i < x;
i++)
219 uint16_t *
a = (uint16_t *)aa;
220 const uint16_t *
b = (
const uint16_t *)bb;
222 for (
int i = 0;
i < x;
i++)
228 const uint16_t *
b = (
const uint16_t *)bb;
229 uint16_t *
a = (uint16_t *)aa;
231 for (
int i = 0;
i < x;
i++)
237 uint16_t *
a = (uint16_t *)aa;
238 const uint16_t *
b = (
const uint16_t *)bb;
240 for (
int i = 0;
i < x;
i++)
244static void max16_fun(uint8_t *cc,
const uint8_t *aa,
const uint8_t *bb,
int x)
246 const uint16_t *
a = (
const uint16_t *)aa;
247 const uint16_t *
b = (
const uint16_t *)bb;
248 uint16_t *
c = (uint16_t *)cc;
250 for (
int i = 0;
i < x;
i++)
256 uint16_t *
a = (uint16_t *)aa;
257 const uint16_t *
b = (
const uint16_t *)bb;
259 for (
int i = 0;
i < x;
i++)
270 pre_pad_x = 0 -
SE->minX;
281 for (
int i = 0;
i < Ty->
I;
i++) {
286 memset(arr[
i], UINT8_MAX, pre_pad_x * type_size);
290 arr[
i] = &(arr[
i][pre_pad_x * type_size]);
304 if (!
table->base_arr)
310 for (
int i = 0;
i <
table->I;
i++) {
325 if (!Ty->
arr || Ty->
I !=
SE->Lnum ||
329 Ty->
max_r !=
SE->maxY + num - 1) {
337 Ty->
max_r =
SE->maxY + num - 1;
369 for (
int i = 1;
i <
SE->Lnum;
i++) {
370 int d =
SE->R[
i] -
SE->R[
i - 1];
376 memcpy(Ty->
arr[
r][
i] + (Ty->
X - d) *
f->type_size,
377 Ty->
arr[
r][
i - 1] + (Ty->
X - d) *
f->type_size,
384 for (
int i = 0;
i < num;
i++)
410 for (
int i = 1;
i <
SE->Lnum;
i++) {
411 int d =
SE->R[
i] -
SE->R[
i - 1];
417 memcpy(Ty->
arr[
r][
i] + (Ty->
X - d) *
f->type_size,
418 Ty->
arr[
r][
i - 1] + (Ty->
X - d) *
f->type_size,
425 for (
int i = 0;
i < num;
i++)
445 memset(
g->img[y], 0,
g->w *
g->type_size);
447 for (
int c = 0;
c <
SE->size;
c++) {
448 g->max_in_place(
g->img[y],
456 memset(
g->img[y], UINT8_MAX,
g->w *
g->type_size);
458 for (
int c = 0;
c <
SE->size;
c++) {
459 g->min_in_place(
g->img[y],
472 for (
int y = y0 + 1; y < y1; y++) {
487 for (
int y = y0 + 1; y < y1; y++) {
497 for (
int y = y0; y < y1; y++)
498 f->diff_in_place(
g->img[y],
f->img[y],
f->w);
503 for (
int y = y0; y < y1; y++)
504 f->diff_rin_place(
g->img[y],
f->img[y],
f->w);
510 if (chords->
size == chords->
cap) {
518 chords->
C[chords->
size].
x =
c.x;
519 chords->
C[chords->
size].
y =
c.y;
520 chords->
C[chords->
size++].
l =
c.l;
551 chords->
minX = INT16_MAX;
552 chords->
maxX = INT16_MIN;
553 chords->
minY = INT16_MAX;
554 chords->
maxY = INT16_MIN;
565 return (
a.l >
b.l) - (
a.l <
b.l);
574 return (
a.y >
b.y) - (
a.y <
b.y);
579 const int mid = 1 << (
SE->depth - 1);
580 int chord_length_index;
581 int chord_start,
val, ret;
582 int centerX, centerY;
593 centerX = (
SE->w - 1) / 2;
594 centerY = (
SE->h - 1) / 2;
599 for (
int y = 0; y <
SE->h; y++) {
603 for (x = 0; x <
SE->w; x++) {
604 if (
SE->type_size == 1) {
607 if (
SE->img[y][x] >= mid && chord_start == -1) {
610 }
else if (
SE->img[y][x] < mid && chord_start != -1) {
612 c.x = chord_start - centerX;
614 c.l = x - chord_start;
623 if (
AV_RN16(&
SE->img[y][x * 2]) >= mid && chord_start == -1) {
626 }
else if (
AV_RN16(&
SE->img[y][x * 2]) < mid && chord_start != -1) {
628 c.x = chord_start - centerX;
630 c.l = x - chord_start;
638 if (chord_start != -1) {
640 c.x = chord_start - centerX;
642 c.l = x - chord_start;
662 if (chords->
size > 0) {
664 if (chords->
Lnum >= r_cap) {
670 chords->
R[chords->
Lnum++] = 1;
674 for (
int i = 0;
i < chords->
size;
i++) {
675 if (
val != chords->
C[
i].
l) {
677 if (chords->
Lnum >= r_cap) {
684 chords->
R[chords->
Lnum++] = 2 *
val;
689 if (chords->
Lnum >= r_cap) {
704 chord_length_index = 0;
705 for (
int i = 0;
i < chords->
size;
i++) {
706 while (chords->
R[chord_length_index] < chords->
C[
i].
l)
707 chord_length_index++;
708 chords->
C[
i].
i = chord_length_index;
727 int w,
int h,
int R,
int type_size,
int depth)
746 for (
int y = 0; y <
h; y++)
747 imp->
img[y] = (uint8_t *)
dst + y * dst_linesize;
757 s->depth =
desc->comp[0].depth;
758 s->type_size = (
s->depth + 7) / 8;
759 s->nb_planes =
desc->nb_components;
761 s->planewidth[0] =
s->planewidth[3] = inlink->
w;
763 s->planeheight[0] =
s->planeheight[3] = inlink->
h;
777 s->splanewidth[0] =
s->splanewidth[3] = inlink->
w;
779 s->splaneheight[0] =
s->splaneheight[3] = inlink->
h;
802 for (
int p = 0; p <
s->nb_planes; p++) {
803 const int width =
s->planewidth[p];
804 const int height =
s->planeheight[p];
807 const int depth =
s->depth;
809 if (
ctx->is_disabled || !(
s->planes & (1 << p))) {
815 width * ((depth + 7) / 8),
820 if (
s->SE[p].minX == INT16_MAX ||
821 s->SE[p].minY == INT16_MAX ||
822 s->SE[p].maxX == INT16_MIN ||
823 s->SE[p].maxY == INT16_MIN)
828 ret =
erode(&
s->g[p], &
s->f[p], &
s->SE[p], &
s->Ty[jobnr][0][p], y0, y1);
832 ret =
dilate(&
s->g[p], &
s->f[p], &
s->SE[p], &
s->Ty[jobnr][0][p], y0, y1);
836 ret =
erode(&
s->h[p], &
s->f[p], &
s->SE[p], &
s->Ty[jobnr][0][p], y0, y1);
840 ret =
dilate(&
s->h[p], &
s->f[p], &
s->SE[p], &
s->Ty[jobnr][0][p], y0, y1);
858 for (
int p = 0; p <
s->nb_planes; p++) {
859 const int height =
s->planeheight[p];
863 if (
ctx->is_disabled || !(
s->planes & (1 << p))) {
868 if (
s->SE[p].minX == INT16_MAX ||
869 s->SE[p].minY == INT16_MAX ||
870 s->SE[p].maxX == INT16_MIN ||
871 s->SE[p].maxY == INT16_MIN)
876 ret =
dilate(&
s->g[p], &
s->h[p], &
s->SE[p], &
s->Ty[jobnr][1][p], y0, y1);
879 ret =
erode(&
s->g[p], &
s->h[p], &
s->SE[p], &
s->Ty[jobnr][1][p], y0, y1);
882 ret =
erode(&
s->h[p], &
s->f[p], &
s->SE[p], &
s->Ty[jobnr][1][p], y0, y1);
888 ret =
dilate(&
s->g[p], &
s->h[p], &
s->SE[p], &
s->Ty[jobnr][1][p], y0, y1);
894 ret =
erode(&
s->g[p], &
s->h[p], &
s->SE[p], &
s->Ty[jobnr][1][p], y0, y1);
933 for (
int p = 0; p <
s->nb_planes; p++) {
934 const uint8_t *ssrc = structurepic->data[p];
935 const int ssrc_linesize = structurepic->linesize[p];
936 const int swidth =
s->splanewidth[p];
937 const int sheight =
s->splaneheight[p];
938 const uint8_t *
src = in->
data[p];
940 uint8_t *
dst =
out->data[p];
941 int dst_linesize =
out->linesize[p];
942 const int width =
s->planewidth[p];
943 const int height =
s->planeheight[p];
944 const int depth =
s->depth;
945 int type_size =
s->type_size;
947 if (!
s->got_structure[p] ||
s->structures) {
950 ret =
read_iplane(&
s->SEimg[p], ssrc, ssrc_linesize, swidth, sheight, 1, type_size, depth);
956 s->got_structure[p] = 1;
963 ret =
read_iplane(&
s->g[p],
dst, dst_linesize,
s->f[p].w,
s->f[p].h,
s->f[p].range, type_size, depth);
983 FFMIN3(
s->planeheight[1],
s->planeheight[2],
987 FFMIN3(
s->planeheight[1],
s->planeheight[2],
1013 outlink->
w = mainlink->
w;
1014 outlink->
h = mainlink->
h;
1027 s->plane_f =
av_calloc(outlink->
w * outlink->
h,
sizeof(*
s->plane_f));
1028 s->plane_g =
av_calloc(outlink->
w * outlink->
h,
sizeof(*
s->plane_g));
1029 if (!
s->plane_f || !
s->plane_g)
1039 for (
int p = 0; p < 4; p++) {
1065 .name =
"structure",
1082 .p.priv_class = &morpho_class,
1085 .preinit = morpho_framesync_preinit,
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static double val(void *priv, double ch)
static int config_input(AVFilterLink *inlink)
const FFFilter ff_vf_morpho
static AVFormatContext * ctx
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
#define fs(width, name, subs,...)
#define AV_CEIL_RSHIFT(a, b)
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
#define FRAMESYNC_DEFINE_CLASS(name, context, field)
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_INT
Underlying C type is int.
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will have its filter_frame() c...
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
static int config_output(AVBitStreamFilterLink *outlink)
#define FILTER_INPUTS(array)
#define FILTER_OUTPUTS(array)
static int ff_slice_pos(int total, int jobnr, int nb_jobs)
Compute the boundary index for a slice when work of size total is split into nb_jobs slices.
#define FILTER_PIXFMTS_ARRAY(array)
static FilterLink * ff_filter_link(AVFilterLink *link)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static enum AVPixelFormat pix_fmts[]
static const struct @257111027162314367033347246032313251342043035002 planes[]
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
#define AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_YUV420P16
#define AV_PIX_FMT_YUV444P12
#define AV_PIX_FMT_YUV444P9
#define AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV440P12
#define AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_YUV422P9
#define AV_PIX_FMT_YUVA444P10
#define AV_PIX_FMT_YUVA420P16
#define AV_PIX_FMT_YUV420P12
#define AV_PIX_FMT_YUVA420P10
#define AV_PIX_FMT_YUVA422P9
#define AV_PIX_FMT_YUV422P12
#define AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_YUV420P9
#define AV_PIX_FMT_YUVA420P9
#define AV_PIX_FMT_YUVA422P10
#define AV_PIX_FMT_YUV420P14
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
@ AV_PIX_FMT_YUVJ440P
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
@ AV_PIX_FMT_YUVJ411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
@ AV_PIX_FMT_YUVJ422P
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
@ AV_PIX_FMT_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
#define AV_PIX_FMT_YUVA422P12
#define AV_PIX_FMT_YUV422P14
#define AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY14
#define AV_PIX_FMT_YUV422P16
#define AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_YUVA444P16
#define AV_PIX_FMT_YUVA422P16
#define AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_YUV444P14
#define AV_PIX_FMT_YUVA444P9
#define AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_YUVA444P12
#define AV_PIX_FMT_YUV444P16
#define AV_PIX_FMT_YUV444P10
static const uint16_t table[]
Describe the class of an AVClass context structure.
void * priv
private data for use by the filter
A link between two filters.
int w
agreed upon image width
int h
agreed upon image height
AVFilterContext * src
source filter
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link.
AVRational sample_aspect_ratio
agreed upon sample aspect ratio
AVFilterContext * dst
dest filter
int format
agreed upon media format
A filter pad used for either input or output.
This structure describes decoded (raw) audio or video data.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Link properties exposed to filter code, but not external callers.
AVRational frame_rate
Frame rate of the stream on the link, or 1/0 if unknown or variable.
void(* max_in_place)(uint8_t *a, const uint8_t *b, int x)
void(* max_out_place)(uint8_t *c, const uint8_t *a, const uint8_t *b, int x)
void(* min_in_place)(uint8_t *a, const uint8_t *b, int x)
void(* diff_in_place)(uint8_t *a, const uint8_t *b, int x)
void(* diff_rin_place)(uint8_t *a, const uint8_t *b, int x)
void(* min_out_place)(uint8_t *c, const uint8_t *a, const uint8_t *b, int x)
LUT Ty[MAX_THREADS][2][4]
Used for passing data between threads.
#define av_realloc_f(p, o, n)
static void update_min_lut(IPlane *f, LUT *Ty, chord_set *SE, int y, int tid, int num)
static int insert_chord_set(chord_set *chords, chord c)
static void min16_fun(uint8_t *cc, const uint8_t *aa, const uint8_t *bb, int x)
static int compute_max_lut(LUT *Ty, IPlane *f, chord_set *SE, int y, int num)
static void compute_max_row(IPlane *f, LUT *Ty, chord_set *SE, int r, int y)
static int alloc_lut_if_necessary(LUT *Ty, IPlane *f, chord_set *SE, int num, enum MorphModes mode)
static const AVFilterPad morpho_inputs[]
static int erode(IPlane *g, IPlane *f, chord_set *SE, LUT *Ty, int y0, int y1)
static void free_chord_set(chord_set *SE)
static void line_dilate(IPlane *g, LUT *Ty, chord_set *SE, int y, int tid)
static int comp_chord(const void *p, const void *q)
static void update_max_lut(IPlane *f, LUT *Ty, chord_set *SE, int y, int tid, int num)
static void maxinplace_fun(uint8_t *a, const uint8_t *b, int x)
static int read_iplane(IPlane *imp, const uint8_t *dst, int dst_linesize, int w, int h, int R, int type_size, int depth)
static int init_chordset(chord_set *chords)
static void diff16_fun(uint8_t *aa, const uint8_t *bb, int x)
static int config_input(AVFilterLink *inlink)
static void difference(IPlane *g, IPlane *f, int y0, int y1)
static int morpho_sliceX(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static void free_iplane(IPlane *imp)
static void diffinplace_fun(uint8_t *a, const uint8_t *b, int x)
static int do_morpho(FFFrameSync *fs)
static void diffinplace16_fun(uint8_t *aa, const uint8_t *bb, int x)
static int compute_min_lut(LUT *Ty, IPlane *f, chord_set *SE, int y, int num)
static void mininplace_fun(uint8_t *a, const uint8_t *b, int x)
static int build_chord_set(IPlane *SE, chord_set *chords)
static void line_erode(IPlane *g, LUT *Ty, chord_set *SE, int y, int tid)
static void mininplace16_fun(uint8_t *aa, const uint8_t *bb, int x)
static const AVOption morpho_options[]
static const AVFilterPad morpho_outputs[]
static int alloc_lut(LUT *Ty, chord_set *SE, int type_size, int mode)
static int dilate(IPlane *g, IPlane *f, chord_set *SE, LUT *Ty, int y0, int y1)
static int activate(AVFilterContext *ctx)
static av_cold void uninit(AVFilterContext *ctx)
static void difference2(IPlane *g, IPlane *f, int y0, int y1)
static void max_fun(uint8_t *c, const uint8_t *a, const uint8_t *b, int x)
static int config_output(AVFilterLink *outlink)
static int comp_chord_length(const void *p, const void *q)
static void diff_fun(uint8_t *a, const uint8_t *b, int x)
static void compute_min_row(IPlane *f, LUT *Ty, chord_set *SE, int r, int y)
static void maxinplace16_fun(uint8_t *aa, const uint8_t *bb, int x)
static int morpho_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int config_input_structure(AVFilterLink *inlink)
static void circular_swap(LUT *Ty)
static void min_fun(uint8_t *c, const uint8_t *a, const uint8_t *b, int x)
static void max16_fun(uint8_t *cc, const uint8_t *aa, const uint8_t *bb, int x)
static void free_lut(LUT *table)
static void copy(const float *p1, float *p2, const int length)
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.