36 #define LB_MASK 0x00FEFEFE
37 #define RED_BLUE_MASK 0x00FF00FF
38 #define GREEN_MASK 0x0000FF00
50 uint32_t rgbtoyuv[1<<24];
58 #define OFFSET(x) offsetof(XBRContext, x)
59 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
67 static uint32_t
pixel_diff(uint32_t x, uint32_t y,
const uint32_t *r2y)
69 #define YMASK 0xff0000
70 #define UMASK 0x00ff00
71 #define VMASK 0x0000ff
72 #define ABSDIFF(a,b) (abs((int)(a)-(int)(b)))
74 uint32_t yuv1 = r2y[x & 0xffffff];
75 uint32_t yuv2 = r2y[y & 0xffffff];
82 #define ALPHA_BLEND_128_W(a, b) ((((a) & LB_MASK) >> 1) + (((b) & LB_MASK) >> 1))
83 #define ALPHA_BLEND_BASE(a, b, m, s) ( (RED_BLUE_MASK & (((a) & RED_BLUE_MASK) + (((((b) & RED_BLUE_MASK) - ((a) & RED_BLUE_MASK)) * (m)) >> (s)))) \
84 | (GREEN_MASK & (((a) & GREEN_MASK) + (((((b) & GREEN_MASK) - ((a) & GREEN_MASK)) * (m)) >> (s)))))
85 #define ALPHA_BLEND_32_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 3)
86 #define ALPHA_BLEND_64_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 2)
87 #define ALPHA_BLEND_192_W(a, b) ALPHA_BLEND_BASE(a, b, 3, 2)
88 #define ALPHA_BLEND_224_W(a, b) ALPHA_BLEND_BASE(a, b, 7, 3)
90 #define df(A, B) pixel_diff(A, B, r2y)
91 #define eq(A, B) (df(A, B) < 155)
93 #define FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
94 N0, N1, N2, N3) do { \
95 if (PE != PH && PE != PF) { \
96 const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
97 const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
99 const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
100 if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI) \
101 && (!eq(PF,I4) && !eq(PH,I5)) \
102 || eq(PE,PG) || eq(PE,PC))) { \
103 const unsigned ke = df(PF,PG); \
104 const unsigned ki = df(PH,PC); \
105 const int left = ke<<1 <= ki && PE != PG && PD != PG; \
106 const int up = ke >= ki<<1 && PE != PC && PB != PC; \
108 E[N3] = ALPHA_BLEND_224_W(E[N3], px); \
109 E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
112 E[N3] = ALPHA_BLEND_192_W(E[N3], px); \
113 E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
115 E[N3] = ALPHA_BLEND_192_W(E[N3], px); \
116 E[N1] = ALPHA_BLEND_64_W( E[N1], px); \
118 E[N3] = ALPHA_BLEND_128_W(E[N3], px); \
121 E[N3] = ALPHA_BLEND_128_W(E[N3], px); \
127 #define FILT3(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
128 N0, N1, N2, N3, N4, N5, N6, N7, N8) do { \
129 if (PE != PH && PE != PF) { \
130 const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
131 const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
133 const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
134 if (e < i && (!eq(PF,PB) && !eq(PF,PC) || !eq(PH,PD) && !eq(PH,PG) || eq(PE,PI) \
135 && (!eq(PF,F4) && !eq(PF,I4) || !eq(PH,H5) && !eq(PH,I5)) \
136 || eq(PE,PG) || eq(PE,PC))) { \
137 const unsigned ke = df(PF,PG); \
138 const unsigned ki = df(PH,PC); \
139 const int left = ke<<1 <= ki && PE != PG && PD != PG; \
140 const int up = ke >= ki<<1 && PE != PC && PB != PC; \
142 E[N7] = ALPHA_BLEND_192_W(E[N7], px); \
143 E[N6] = ALPHA_BLEND_64_W( E[N6], px); \
148 E[N7] = ALPHA_BLEND_192_W(E[N7], px); \
149 E[N5] = ALPHA_BLEND_64_W( E[N5], px); \
150 E[N6] = ALPHA_BLEND_64_W( E[N6], px); \
153 E[N5] = ALPHA_BLEND_192_W(E[N5], px); \
154 E[N7] = ALPHA_BLEND_64_W( E[N7], px); \
155 E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
158 E[N8] = ALPHA_BLEND_224_W(E[N8], px); \
159 E[N5] = ALPHA_BLEND_32_W( E[N5], px); \
160 E[N7] = ALPHA_BLEND_32_W( E[N7], px); \
163 E[N8] = ALPHA_BLEND_128_W(E[N8], px); \
169 #define FILT4(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
170 N15, N14, N11, N3, N7, N10, N13, N12, N9, N6, N2, N1, N5, N8, N4, N0) do { \
171 if (PE != PH && PE != PF) { \
172 const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
173 const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
175 const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
176 if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI) \
177 && (!eq(PF,I4) && !eq(PH,I5)) \
178 || eq(PE,PG) || eq(PE,PC))) { \
179 const unsigned ke = df(PF,PG); \
180 const unsigned ki = df(PH,PC); \
181 const int left = ke<<1 <= ki && PE != PG && PD != PG; \
182 const int up = ke >= ki<<1 && PE != PC && PB != PC; \
184 E[N13] = ALPHA_BLEND_192_W(E[N13], px); \
185 E[N12] = ALPHA_BLEND_64_W( E[N12], px); \
186 E[N15] = E[N14] = E[N11] = px; \
187 E[N10] = E[N3] = E[N12]; \
190 E[N11] = ALPHA_BLEND_192_W(E[N11], px); \
191 E[N13] = ALPHA_BLEND_192_W(E[N13], px); \
192 E[N10] = ALPHA_BLEND_64_W( E[N10], px); \
193 E[N12] = ALPHA_BLEND_64_W( E[N12], px); \
197 E[N14] = ALPHA_BLEND_192_W(E[N14], px); \
198 E[N7 ] = ALPHA_BLEND_192_W(E[N7 ], px); \
199 E[N10] = ALPHA_BLEND_64_W( E[N10], px); \
200 E[N3 ] = ALPHA_BLEND_64_W( E[N3 ], px); \
204 E[N11] = ALPHA_BLEND_128_W(E[N11], px); \
205 E[N14] = ALPHA_BLEND_128_W(E[N14], px); \
209 E[N15] = ALPHA_BLEND_128_W(E[N15], px); \
221 const int slice_start = (input->
height * jobnr ) / nb_jobs;
223 const int nl = output->
linesize[0] >> 2;
224 const int nl1 = nl + nl;
225 const int nl2 = nl1 + nl;
227 for (y = slice_start; y <
slice_end; y++) {
229 uint32_t *
E = (uint32_t *)(output->
data[0] + y * output->
linesize[0] * n);
230 const uint32_t *sa2 = (uint32_t *)(input->
data[0] + y * input->
linesize[0] - 8);
231 const uint32_t *sa1 = sa2 - (input->
linesize[0]>>2);
232 const uint32_t *sa0 = sa1 - (input->
linesize[0]>>2);
233 const uint32_t *sa3 = sa2 + (input->
linesize[0]>>2);
234 const uint32_t *sa4 = sa3 + (input->
linesize[0]>>2);
243 if (y >= input->
height - 2) {
245 if (y == input->
height - 1) {
250 for (x = 0; x < input->
width; x++) {
251 const uint32_t
B1 = sa0[2];
252 const uint32_t PB = sa1[2];
253 const uint32_t PE = sa2[2];
254 const uint32_t PH = sa3[2];
255 const uint32_t H5 = sa4[2];
257 const int pprev = 2 - (x > 0);
258 const uint32_t
A1 = sa0[pprev];
259 const uint32_t PA = sa1[pprev];
260 const uint32_t
PD = sa2[pprev];
261 const uint32_t PG = sa3[pprev];
262 const uint32_t G5 = sa4[pprev];
264 const int pprev2 = pprev - (x > 1);
265 const uint32_t A0 = sa1[pprev2];
266 const uint32_t D0 = sa2[pprev2];
267 const uint32_t G0 = sa3[pprev2];
269 const int pnext = 3 - (x == input->
width - 1);
270 const uint32_t
C1 = sa0[pnext];
271 const uint32_t PC = sa1[pnext];
272 const uint32_t
PF = sa2[pnext];
273 const uint32_t PI = sa3[pnext];
274 const uint32_t I5 = sa4[pnext];
276 const int pnext2 = pnext + 1 - (x >= input->
width - 2);
277 const uint32_t
C4 = sa1[pnext2];
278 const uint32_t F4 = sa2[pnext2];
279 const uint32_t I4 = sa3[pnext2];
283 E[nl] = E[nl + 1] = PE;
285 FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, 0, 1, nl, nl+1);
286 FILT2(PE, PC, PF, PB, PI, PA, PH, PD, PG, I4, A1, I5, H5, A0, D0, B1, C1, F4, C4, G5, G0, nl, 0, nl+1, 1);
287 FILT2(PE, PA, PB, PD, PC, PG, PF, PH, PI, C1, G0, C4, F4, G5, H5, D0, A0, B1, A1, I4, I5, nl+1, nl, 1, 0);
288 FILT2(PE, PG, PD, PH, PA, PI, PB, PF, PC, A0, I5, A1, B1, I4, F4, H5, G5, D0, G0, C1, C4, 1, nl+1, 0, nl);
291 E[nl] = E[nl+1] = E[nl+2] =
292 E[nl1] = E[nl1+1] = E[nl1+2] = PE;
294 FILT3(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, 0, 1, 2, nl, nl+1, nl+2, nl1, nl1+1, nl1+2);
295 FILT3(PE, PC, PF, PB, PI, PA, PH, PD, PG, I4, A1, I5, H5, A0, D0, B1, C1, F4, C4, G5, G0, nl1, nl, 0, nl1+1, nl+1, 1, nl1+2, nl+2, 2);
296 FILT3(PE, PA, PB, PD, PC, PG, PF, PH, PI, C1, G0, C4, F4, G5, H5, D0, A0, B1, A1, I4, I5, nl1+2, nl1+1, nl1, nl+2, nl+1, nl, 2, 1, 0);
297 FILT3(PE, PG, PD, PH, PA, PI, PB, PF, PC, A0, I5, A1, B1, I4, F4, H5, G5, D0, G0, C1, C4, 2, nl+2, nl1+2, 1, nl+1, nl1+1, 0, nl, nl1);
299 E[0] = E[1] = E[2] = E[3] =
300 E[nl] = E[nl+1] = E[nl+2] = E[nl+3] =
301 E[nl1] = E[nl1+1] = E[nl1+2] = E[nl1+3] =
302 E[nl2] = E[nl2+1] = E[nl2+2] = E[nl2+3] = PE;
304 FILT4(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, nl2+3, nl2+2, nl1+3, 3, nl+3, nl1+2, nl2+1, nl2, nl1+1, nl+2, 2, 1, nl+1, nl1, nl, 0);
305 FILT4(PE, PC, PF, PB, PI, PA, PH, PD, PG, I4, A1, I5, H5, A0, D0, B1, C1, F4, C4, G5, G0, 3, nl+3, 2, 0, 1, nl+2, nl1+3, nl2+3, nl1+2, nl+1, nl, nl1, nl1+1, nl2+2, nl2+1, nl2);
306 FILT4(PE, PA, PB, PD, PC, PG, PF, PH, PI, C1, G0, C4, F4, G5, H5, D0, A0, B1, A1, I4, I5, 0, 1, nl, nl2, nl1, nl+1, 2, 3, nl+2, nl1+1, nl2+1, nl2+2, nl1+2, nl+3, nl1+3, nl2+3);
307 FILT4(PE, PG, PD, PH, PA, PI, PB, PF, PC, A0, I5, A1, B1, I4, F4, H5, G5, D0, G0, C1, C4, nl2, nl1, nl2+1, nl2+3, nl2+2, nl1+1, nl, 0, nl+1, nl1+2, nl1+3, nl+3, nl+2, 1, 2, 3);
321 #define XBR_FUNC(size) \
322 static int xbr##size##x(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
324 xbr_filter(arg, jobnr, nb_jobs, size); \
339 outlink->
w = inlink->
w * s->
n;
340 outlink->h = inlink->
h * s->
n;
386 static const xbrfunc_t xbrfuncs[] = {xbr2x, xbr3x, xbr4x};
391 for (bg = -255; bg < 256; bg++) {
392 for (rg = -255; rg < 256; rg++) {
393 const uint32_t
u = (uint32_t)((-169*rg + 500*bg)/1000) + 128;
394 const uint32_t v = (uint32_t)(( 500*rg - 81*bg)/1000) + 128;
395 int startg =
FFMAX3(-bg, -rg, 0);
396 int endg =
FFMIN3(255-bg, 255-rg, 255);
397 uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000);
398 c = bg + (rg<<16) + 0x010101 * startg;
399 for (g = startg; g <= endg; g++) {
400 s->
rgbtoyuv[
c] = ((y++) << 16) + (u << 8) + v;
406 s->
func = xbrfuncs[s->
n - 2];
435 .priv_class = &xbr_class,
This structure describes decoded (raw) audio or video data.
static const AVOption xbr_options[]
int h
agreed upon image height
static const AVFilterPad xbr_inputs[]
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
const char * name
Pad name.
AVFilterLink ** inputs
array of pointers to input links
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
int(* xbrfunc_t)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define FILT3(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1,N0, N1, N2, N3, N4, N5, N6, N7, N8)
#define FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1,N0, N1, N2, N3)
A filter pad used for either input or output.
A link between two filters.
int width
width and height of the video frame
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void * priv
private data for use by the filter
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
static int config_output(AVFilterLink *outlink)
simple assert() macros that are a bit more flexible than ISO C assert().
static int query_formats(AVFilterContext *ctx)
int w
agreed upon image width
static av_always_inline void xbr_filter(const ThreadData *td, int jobnr, int nb_jobs, int n)
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
const uint32_t * rgbtoyuv
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> in
Describe the class of an AVClass context structure.
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
static uint32_t pixel_diff(uint32_t x, uint32_t y, const uint32_t *r2y)
const char * name
Filter name.
#define PD(a, b)
Pack two delta values (a,b) into one 16-bit word according with endianness of the host machine...
AVFilterLink ** outputs
array of pointers to output links
static enum AVPixelFormat pix_fmts[]
AVFilterInternal * internal
An opaque struct for libavfilter internal use.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
avfilter_execute_func * execute
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
AVFilterContext * dst
dest filter
#define FILT4(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1,N15, N14, N11, N3, N7, N10, N13, N12, N9, N6, N2, N1, N5, N8, N4, N0)
static const AVFilterPad xbr_outputs[]
static int init(AVFilterContext *ctx)
AVPixelFormat
Pixel format.
AVFILTER_DEFINE_CLASS(xbr)
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
uint32_t rgbtoyuv[1<< 24]
#define AV_PIX_FMT_0RGB32