36 #define LB_MASK 0x00FEFEFE
37 #define RED_BLUE_MASK 0x00FF00FF
38 #define GREEN_MASK 0x0000FF00
46 uint32_t rgbtoyuv[1<<24];
54 #define OFFSET(x) offsetof(XBRContext, x)
55 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
63 static uint32_t
pixel_diff(uint32_t x, uint32_t y,
const uint32_t *r2y)
65 #define YMASK 0xff0000
66 #define UMASK 0x00ff00
67 #define VMASK 0x0000ff
68 #define ABSDIFF(a,b) (abs((int)(a)-(int)(b)))
70 uint32_t yuv1 = r2y[x & 0xffffff];
71 uint32_t yuv2 = r2y[y & 0xffffff];
78 #define ALPHA_BLEND_128_W(a, b) ((((a) & LB_MASK) >> 1) + (((b) & LB_MASK) >> 1))
79 #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)))) \
80 | (GREEN_MASK & (((a) & GREEN_MASK) + (((((b) & GREEN_MASK) - ((a) & GREEN_MASK)) * (m)) >> (s)))))
81 #define ALPHA_BLEND_32_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 3)
82 #define ALPHA_BLEND_64_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 2)
83 #define ALPHA_BLEND_192_W(a, b) ALPHA_BLEND_BASE(a, b, 3, 2)
84 #define ALPHA_BLEND_224_W(a, b) ALPHA_BLEND_BASE(a, b, 7, 3)
86 #define df(A, B) pixel_diff(A, B, r2y)
87 #define eq(A, B) (df(A, B) < 155)
89 #define FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
90 N0, N1, N2, N3) do { \
91 if (PE != PH && PE != PF) { \
92 const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
93 const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
95 const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
96 if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI) \
97 && (!eq(PF,I4) && !eq(PH,I5)) \
98 || eq(PE,PG) || eq(PE,PC))) { \
99 const unsigned ke = df(PF,PG); \
100 const unsigned ki = df(PH,PC); \
101 const int left = ke<<1 <= ki && PE != PG && PD != PG; \
102 const int up = ke >= ki<<1 && PE != PC && PB != PC; \
104 E[N3] = ALPHA_BLEND_224_W(E[N3], px); \
105 E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
108 E[N3] = ALPHA_BLEND_192_W(E[N3], px); \
109 E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
111 E[N3] = ALPHA_BLEND_192_W(E[N3], px); \
112 E[N1] = ALPHA_BLEND_64_W( E[N1], px); \
114 E[N3] = ALPHA_BLEND_128_W(E[N3], px); \
117 E[N3] = ALPHA_BLEND_128_W(E[N3], px); \
123 #define FILT3(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
124 N0, N1, N2, N3, N4, N5, N6, N7, N8) do { \
125 if (PE != PH && PE != PF) { \
126 const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
127 const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
129 const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
130 if (e < i && (!eq(PF,PB) && !eq(PF,PC) || !eq(PH,PD) && !eq(PH,PG) || eq(PE,PI) \
131 && (!eq(PF,F4) && !eq(PF,I4) || !eq(PH,H5) && !eq(PH,I5)) \
132 || eq(PE,PG) || eq(PE,PC))) { \
133 const unsigned ke = df(PF,PG); \
134 const unsigned ki = df(PH,PC); \
135 const int left = ke<<1 <= ki && PE != PG && PD != PG; \
136 const int up = ke >= ki<<1 && PE != PC && PB != PC; \
138 E[N7] = ALPHA_BLEND_192_W(E[N7], px); \
139 E[N6] = ALPHA_BLEND_64_W( E[N6], px); \
144 E[N7] = ALPHA_BLEND_192_W(E[N7], px); \
145 E[N5] = ALPHA_BLEND_64_W( E[N5], px); \
146 E[N6] = ALPHA_BLEND_64_W( E[N6], px); \
149 E[N5] = ALPHA_BLEND_192_W(E[N5], px); \
150 E[N7] = ALPHA_BLEND_64_W( E[N7], px); \
151 E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
154 E[N8] = ALPHA_BLEND_224_W(E[N8], px); \
155 E[N5] = ALPHA_BLEND_32_W( E[N5], px); \
156 E[N7] = ALPHA_BLEND_32_W( E[N7], px); \
159 E[N8] = ALPHA_BLEND_128_W(E[N8], px); \
165 #define FILT4(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
166 N15, N14, N11, N3, N7, N10, N13, N12, N9, N6, N2, N1, N5, N8, N4, N0) do { \
167 if (PE != PH && PE != PF) { \
168 const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
169 const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
171 const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
172 if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI) \
173 && (!eq(PF,I4) && !eq(PH,I5)) \
174 || eq(PE,PG) || eq(PE,PC))) { \
175 const unsigned ke = df(PF,PG); \
176 const unsigned ki = df(PH,PC); \
177 const int left = ke<<1 <= ki && PE != PG && PD != PG; \
178 const int up = ke >= ki<<1 && PE != PC && PB != PC; \
180 E[N13] = ALPHA_BLEND_192_W(E[N13], px); \
181 E[N12] = ALPHA_BLEND_64_W( E[N12], px); \
182 E[N15] = E[N14] = E[N11] = px; \
183 E[N10] = E[N3] = E[N12]; \
186 E[N11] = ALPHA_BLEND_192_W(E[N11], px); \
187 E[N13] = ALPHA_BLEND_192_W(E[N13], px); \
188 E[N10] = ALPHA_BLEND_64_W( E[N10], px); \
189 E[N12] = ALPHA_BLEND_64_W( E[N12], px); \
193 E[N14] = ALPHA_BLEND_192_W(E[N14], px); \
194 E[N7 ] = ALPHA_BLEND_192_W(E[N7 ], px); \
195 E[N10] = ALPHA_BLEND_64_W( E[N10], px); \
196 E[N3 ] = ALPHA_BLEND_64_W( E[N3 ], px); \
200 E[N11] = ALPHA_BLEND_128_W(E[N11], px); \
201 E[N14] = ALPHA_BLEND_128_W(E[N14], px); \
205 E[N15] = ALPHA_BLEND_128_W(E[N15], px); \
217 const int slice_start = (input->
height * jobnr ) / nb_jobs;
219 const int nl = output->
linesize[0] >> 2;
220 const int nl1 = nl + nl;
221 const int nl2 = nl1 + nl;
223 for (y = slice_start; y <
slice_end; y++) {
225 uint32_t *
E = (uint32_t *)(output->
data[0] + y * output->
linesize[0] * n);
226 const uint32_t *sa2 = (uint32_t *)(input->
data[0] + y * input->
linesize[0] - 8);
227 const uint32_t *sa1 = sa2 - (input->
linesize[0]>>2);
228 const uint32_t *sa0 = sa1 - (input->
linesize[0]>>2);
229 const uint32_t *sa3 = sa2 + (input->
linesize[0]>>2);
230 const uint32_t *sa4 = sa3 + (input->
linesize[0]>>2);
239 if (y >= input->
height - 2) {
241 if (y == input->
height - 1) {
246 for (x = 0; x < input->
width; x++) {
247 const uint32_t
B1 = sa0[2];
248 const uint32_t PB = sa1[2];
249 const uint32_t PE = sa2[2];
250 const uint32_t PH = sa3[2];
251 const uint32_t H5 = sa4[2];
253 const int pprev = 2 - (x > 0);
254 const uint32_t
A1 = sa0[pprev];
255 const uint32_t PA = sa1[pprev];
256 const uint32_t
PD = sa2[pprev];
257 const uint32_t PG = sa3[pprev];
258 const uint32_t G5 = sa4[pprev];
260 const int pprev2 = pprev - (x > 1);
261 const uint32_t A0 = sa1[pprev2];
262 const uint32_t D0 = sa2[pprev2];
263 const uint32_t G0 = sa3[pprev2];
265 const int pnext = 3 - (x == input->
width - 1);
266 const uint32_t
C1 = sa0[pnext];
267 const uint32_t PC = sa1[pnext];
268 const uint32_t
PF = sa2[pnext];
269 const uint32_t PI = sa3[pnext];
270 const uint32_t I5 = sa4[pnext];
272 const int pnext2 = pnext + 1 - (x >= input->
width - 2);
273 const uint32_t
C4 = sa1[pnext2];
274 const uint32_t F4 = sa2[pnext2];
275 const uint32_t I4 = sa3[pnext2];
279 E[nl] = E[nl + 1] = PE;
281 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);
282 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);
283 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);
284 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);
287 E[nl] = E[nl+1] = E[nl+2] =
288 E[nl1] = E[nl1+1] = E[nl1+2] = PE;
290 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);
291 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);
292 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);
293 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);
295 E[0] = E[1] = E[2] = E[3] =
296 E[nl] = E[nl+1] = E[nl+2] = E[nl+3] =
297 E[nl1] = E[nl1+1] = E[nl1+2] = E[nl1+3] =
298 E[nl2] = E[nl2+1] = E[nl2+2] = E[nl2+3] = PE;
300 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);
301 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);
302 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);
303 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);
317 #define XBR_FUNC(size) \
318 static int xbr##size##x(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
320 xbr_filter(arg, jobnr, nb_jobs, size); \
335 outlink->
w = inlink->
w * s->
n;
336 outlink->h = inlink->
h * s->
n;
382 static const xbrfunc_t xbrfuncs[] = {xbr2x, xbr3x, xbr4x};
387 for (bg = -255; bg < 256; bg++) {
388 for (rg = -255; rg < 256; rg++) {
389 const uint32_t
u = (uint32_t)((-169*rg + 500*bg)/1000) + 128;
390 const uint32_t v = (uint32_t)(( 500*rg - 81*bg)/1000) + 128;
391 int startg =
FFMAX3(-bg, -rg, 0);
392 int endg =
FFMIN3(255-bg, 255-rg, 255);
393 uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000);
394 c = bg + (rg<<16) + 0x010101 * startg;
395 for (g = startg; g <= endg; g++) {
396 s->
rgbtoyuv[
c] = ((y++) << 16) + (u << 8) + v;
402 s->
func = xbrfuncs[s->
n - 2];
431 .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