49 #define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D))
51 #define INTERPOLATE(A, B) (((A & hi_pixel_mask) >> 1) + ((B & hi_pixel_mask) >> 1) + (A & B & lo_pixel_mask))
53 #define Q_INTERPOLATE(A, B, C, D) ((A & q_hi_pixel_mask) >> 2) + ((B & q_hi_pixel_mask) >> 2) + ((C & q_hi_pixel_mask) >> 2) + ((D & q_hi_pixel_mask) >> 2) \
54 + ((((A & q_lo_pixel_mask) + (B & q_lo_pixel_mask) + (C & q_lo_pixel_mask) + (D & q_lo_pixel_mask)) >> 2) & q_lo_pixel_mask)
64 unsigned char *src_line[4];
65 const int bpp = sai->
bpp;
74 src_line[2] = src + src_linesize*
FFMIN(1, height-1);
75 src_line[3] = src + src_linesize*
FFMIN(2, height-1);
77 #define READ_COLOR4(dst, src_line, off) dst = *((const uint32_t *)src_line + off)
78 #define READ_COLOR3(dst, src_line, off) dst = AV_RL24 (src_line + 3*off)
79 #define READ_COLOR2(dst, src_line, off) dst = sai->is_be ? AV_RB16(src_line + 2 * off) : AV_RL16(src_line + 2 * off)
81 for (y = 0; y <
height; y++) {
84 dst_line[0] = dst + dst_linesize*2*
y;
85 dst_line[1] = dst + dst_linesize*(2*y+1);
107 for (x = 0; x <
width; x++) {
108 uint32_t product1a, product1b, product2a, product2b;
115 if (color[2][1] == color[1][2] && color[1][1] != color[2][2]) {
116 product2b = color[2][1];
117 product1b = product2b;
118 }
else if (color[1][1] == color[2][2] && color[2][1] != color[1][2]) {
119 product2b = color[1][1];
120 product1b = product2b;
121 }
else if (color[1][1] == color[2][2] && color[2][1] == color[1][2]) {
124 r +=
GET_RESULT(color[1][2], color[1][1], color[1][0], color[3][1]);
125 r +=
GET_RESULT(color[1][2], color[1][1], color[2][0], color[0][1]);
126 r +=
GET_RESULT(color[1][2], color[1][1], color[3][2], color[2][3]);
127 r +=
GET_RESULT(color[1][2], color[1][1], color[0][2], color[1][3]);
130 product1b = color[1][2];
132 product1b = color[1][1];
136 product2b = product1b;
138 if (color[1][2] == color[2][2] && color[2][2] == color[3][1] && color[2][1] != color[3][2] && color[2][2] != color[3][0])
139 product2b =
Q_INTERPOLATE(color[2][2], color[2][2], color[2][2], color[2][1]);
140 else if (color[1][1] == color[2][1] && color[2][1] == color[3][2] && color[3][1] != color[2][2] && color[2][1] != color[3][3])
141 product2b =
Q_INTERPOLATE(color[2][1], color[2][1], color[2][1], color[2][2]);
145 if (color[1][2] == color[2][2] && color[1][2] == color[0][1] && color[1][1] != color[0][2] && color[1][2] != color[0][0])
146 product1b =
Q_INTERPOLATE(color[1][2], color[1][2], color[1][2], color[1][1]);
147 else if (color[1][1] == color[2][1] && color[1][1] == color[0][2] && color[0][1] != color[1][2] && color[1][1] != color[0][3])
148 product1b =
Q_INTERPOLATE(color[1][2], color[1][1], color[1][1], color[1][1]);
153 if (color[1][1] == color[2][2] && color[2][1] != color[1][2] && color[1][0] == color[1][1] && color[1][1] != color[3][2])
155 else if (color[1][1] == color[2][0] && color[1][2] == color[1][1] && color[1][0] != color[2][1] && color[1][1] != color[3][0])
158 product2a = color[2][1];
160 if (color[2][1] == color[1][2] && color[1][1] != color[2][2] && color[2][0] == color[2][1] && color[2][1] != color[0][2])
162 else if (color[1][0] == color[2][1] && color[2][2] == color[2][1] && color[2][0] != color[1][1] && color[2][1] != color[0][0])
165 product1a = color[1][1];
170 AV_WN32A(dst_line[0] + x * 8, product1a);
171 AV_WN32A(dst_line[0] + x * 8 + 4, product1b);
172 AV_WN32A(dst_line[1] + x * 8, product2a);
173 AV_WN32A(dst_line[1] + x * 8 + 4, product2b);
176 AV_WL24(dst_line[0] + x * 6, product1a);
177 AV_WL24(dst_line[0] + x * 6 + 3, product1b);
178 AV_WL24(dst_line[1] + x * 6, product2a);
179 AV_WL24(dst_line[1] + x * 6 + 3, product2b);
183 AV_WB32(dst_line[0] + x * 4, product1a | (product1b << 16));
184 AV_WB32(dst_line[1] + x * 4, product2a | (product2b << 16));
186 AV_WL32(dst_line[0] + x * 4, product1a | (product1b << 16));
187 AV_WL32(dst_line[1] + x * 4, product2a | (product2b << 16));
192 color[0][0] = color[0][1]; color[0][1] = color[0][2]; color[0][2] = color[0][3];
193 color[1][0] = color[1][1]; color[1][1] = color[1][2]; color[1][2] = color[1][3];
194 color[2][0] = color[2][1]; color[2][1] = color[2][2]; color[2][2] = color[2][3];
195 color[3][0] = color[3][1]; color[3][1] = color[3][2]; color[3][2] = color[3][3];
223 src_line[0] = src_line[1];
224 src_line[1] = src_line[2];
225 src_line[2] = src_line[3];
228 src_line[3] = src_line[2];
230 src_line[3] += src_linesize;
298 outlink->
w = inlink->
w*2;
299 outlink->
h = inlink->
h*2;
303 inlink->
w, inlink->
h, outlink->
w, outlink->
h);
317 outpicref->
width = outlink->
w;
318 outpicref->
height = outlink->
h;
322 inlink->
w, inlink->
h);
348 .
name =
"super2xsai",
349 .description =
NULL_IF_CONFIG_SMALL(
"Scale the input by 2x using the Super2xSaI pixel art algorithm."),
int bpp
bytes per pixel, pixel stride for each (packed) pixel
This structure describes decoded (raw) audio or video data.
static const AVFilterPad outputs[]
Main libavfilter public API header.
packed RGB 8:8:8, 24bpp, RGBRGB...
int h
agreed upon image height
#define READ_COLOR3(dst, src_line, off)
#define INTERPOLATE(A, B)
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined ...
packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
#define GET_RESULT(A, B, C, D)
static void super2xsai(AVFilterContext *ctx, uint8_t *src, int src_linesize, uint8_t *dst, int dst_linesize, int width, int height)
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
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.
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
#define AV_LOG_VERBOSE
Detailed information.
static int config_input(AVFilterLink *inlink)
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. ...
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
void * priv
private data for use by the filter
#define READ_COLOR4(dst, src_line, off)
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
int w
agreed upon image width
static const AVFilterPad super2xsai_outputs[]
packed RGB 8:8:8, 24bpp, BGRBGR...
AVFilterContext * src
source filter
packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
static int config_output(AVFilterLink *outlink)
int format
agreed upon media format
#define READ_COLOR2(dst, src_line, off)
static const AVFilterPad super2xsai_inputs[]
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
AVFilter ff_vf_super2xsai
BYTE int const BYTE int int int height
static const AVFilterPad inputs[]
const char * name
Filter name.
packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined ...
AVFilterLink ** outputs
array of pointers to output links
#define Q_INTERPOLATE(A, B, C, D)
static enum AVPixelFormat pix_fmts[]
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
static int query_formats(AVFilterContext *ctx)
struct AVFilterPad AVFilterPad
AVFilterContext * dst
dest filter
packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
AVPixelFormat
Pixel format.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.