FFmpeg
vf_noise.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
3  * Copyright (c) 2013 Paul B Mahol
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "libavutil/attributes.h"
23 #include "libavutil/x86/cpu.h"
24 #include "libavutil/x86/asm.h"
25 #include "libavfilter/vf_noise.h"
26 
27 #if HAVE_INLINE_ASM
28 static void line_noise_mmx(uint8_t *dst, const uint8_t *src,
29  const int8_t *noise, int len, int shift)
30 {
31  x86_reg mmx_len= len & (~7);
32  noise += shift;
33 
34  __asm__ volatile(
35  "mov %3, %%"FF_REG_a" \n\t"
36  "pcmpeqb %%mm7, %%mm7 \n\t"
37  "psllw $15, %%mm7 \n\t"
38  "packsswb %%mm7, %%mm7 \n\t"
39  ".p2align 4 \n\t"
40  "1: \n\t"
41  "movq (%0, %%"FF_REG_a"), %%mm0 \n\t"
42  "movq (%1, %%"FF_REG_a"), %%mm1 \n\t"
43  "pxor %%mm7, %%mm0 \n\t"
44  "paddsb %%mm1, %%mm0 \n\t"
45  "pxor %%mm7, %%mm0 \n\t"
46  "movq %%mm0, (%2, %%"FF_REG_a") \n\t"
47  "add $8, %%"FF_REG_a" \n\t"
48  " js 1b \n\t"
49  :: "r" (src+mmx_len), "r" (noise+mmx_len), "r" (dst+mmx_len), "g" (-mmx_len)
50  : "%"FF_REG_a
51  );
52  if (mmx_len != len)
53  ff_line_noise_c(dst+mmx_len, src+mmx_len, noise+mmx_len, len-mmx_len, 0);
54 }
55 
56 #if HAVE_6REGS
57 static void line_noise_avg_mmx(uint8_t *dst, const uint8_t *src,
58  int len, const int8_t * const *shift)
59 {
60  x86_reg mmx_len = len & (~7);
61 
62  __asm__ volatile(
63  "mov %5, %%"FF_REG_a" \n\t"
64  ".p2align 4 \n\t"
65  "1: \n\t"
66  "movq (%1, %%"FF_REG_a"), %%mm1 \n\t"
67  "movq (%0, %%"FF_REG_a"), %%mm0 \n\t"
68  "paddb (%2, %%"FF_REG_a"), %%mm1\n\t"
69  "paddb (%3, %%"FF_REG_a"), %%mm1\n\t"
70  "movq %%mm0, %%mm2 \n\t"
71  "movq %%mm1, %%mm3 \n\t"
72  "punpcklbw %%mm0, %%mm0 \n\t"
73  "punpckhbw %%mm2, %%mm2 \n\t"
74  "punpcklbw %%mm1, %%mm1 \n\t"
75  "punpckhbw %%mm3, %%mm3 \n\t"
76  "pmulhw %%mm0, %%mm1 \n\t"
77  "pmulhw %%mm2, %%mm3 \n\t"
78  "paddw %%mm1, %%mm1 \n\t"
79  "paddw %%mm3, %%mm3 \n\t"
80  "paddw %%mm0, %%mm1 \n\t"
81  "paddw %%mm2, %%mm3 \n\t"
82  "psrlw $8, %%mm1 \n\t"
83  "psrlw $8, %%mm3 \n\t"
84  "packuswb %%mm3, %%mm1 \n\t"
85  "movq %%mm1, (%4, %%"FF_REG_a") \n\t"
86  "add $8, %%"FF_REG_a" \n\t"
87  " js 1b \n\t"
88  :: "r" (src+mmx_len), "r" (shift[0]+mmx_len), "r" (shift[1]+mmx_len), "r" (shift[2]+mmx_len),
89  "r" (dst+mmx_len), "g" (-mmx_len)
90  : "%"FF_REG_a
91  );
92 
93  if (mmx_len != len){
94  const int8_t *shift2[3] = { shift[0]+mmx_len, shift[1]+mmx_len, shift[2]+mmx_len };
95  ff_line_noise_avg_c(dst+mmx_len, src+mmx_len, len-mmx_len, shift2);
96  }
97 }
98 #endif /* HAVE_6REGS */
99 
100 static void line_noise_mmxext(uint8_t *dst, const uint8_t *src,
101  const int8_t *noise, int len, int shift)
102 {
103  x86_reg mmx_len = len & (~7);
104  noise += shift;
105 
106  __asm__ volatile(
107  "mov %3, %%"FF_REG_a" \n\t"
108  "pcmpeqb %%mm7, %%mm7 \n\t"
109  "psllw $15, %%mm7 \n\t"
110  "packsswb %%mm7, %%mm7 \n\t"
111  ".p2align 4 \n\t"
112  "1: \n\t"
113  "movq (%0, %%"FF_REG_a"), %%mm0 \n\t"
114  "movq (%1, %%"FF_REG_a"), %%mm1 \n\t"
115  "pxor %%mm7, %%mm0 \n\t"
116  "paddsb %%mm1, %%mm0 \n\t"
117  "pxor %%mm7, %%mm0 \n\t"
118  "movntq %%mm0, (%2, %%"FF_REG_a") \n\t"
119  "add $8, %%"FF_REG_a" \n\t"
120  " js 1b \n\t"
121  :: "r" (src+mmx_len), "r" (noise+mmx_len), "r" (dst+mmx_len), "g" (-mmx_len)
122  : "%"FF_REG_a
123  );
124  if (mmx_len != len)
125  ff_line_noise_c(dst+mmx_len, src+mmx_len, noise+mmx_len, len-mmx_len, 0);
126 }
127 #endif /* HAVE_INLINE_ASM */
128 
130 {
131 #if HAVE_INLINE_ASM
132  int cpu_flags = av_get_cpu_flags();
133 
134  if (INLINE_MMX(cpu_flags)) {
135  n->line_noise = line_noise_mmx;
136 #if HAVE_6REGS
137  n->line_noise_avg = line_noise_avg_mmx;
138 #endif
139  }
140  if (INLINE_MMXEXT(cpu_flags)) {
141  n->line_noise = line_noise_mmxext;
142  }
143 #endif
144 }
INLINE_MMX
#define INLINE_MMX(flags)
Definition: cpu.h:86
cpu.h
noise
static void noise(uint8_t *dst, const uint8_t *src, int dst_linesize, int src_linesize, int width, int start, int end, NoiseContext *n, int comp)
Definition: vf_noise.c:190
av_get_cpu_flags
int av_get_cpu_flags(void)
Return the flags which specify extensions supported by the CPU.
Definition: cpu.c:98
vf_noise.h
cpu_flags
static atomic_int cpu_flags
Definition: cpu.c:50
NoiseContext
Definition: noise_bsf.c:63
av_cold
#define av_cold
Definition: attributes.h:90
NoiseContext::line_noise
void(* line_noise)(uint8_t *dst, const uint8_t *src, const int8_t *noise, int len, int shift)
Definition: vf_noise.h:55
src
#define src
Definition: vp8dsp.c:255
ff_noise_init_x86
av_cold void ff_noise_init_x86(NoiseContext *n)
Definition: vf_noise.c:129
asm.h
attributes.h
shift2
static const int shift2[6]
Definition: dxa.c:51
ff_line_noise_avg_c
void ff_line_noise_avg_c(uint8_t *dst, const uint8_t *src, int len, const int8_t *const *shift)
Definition: vf_noise.c:178
len
int len
Definition: vorbis_enc_data.h:426
__asm__
__asm__(".macro parse_r var r\n\t" "\\var = -1\n\t" _IFC_REG(0) _IFC_REG(1) _IFC_REG(2) _IFC_REG(3) _IFC_REG(4) _IFC_REG(5) _IFC_REG(6) _IFC_REG(7) _IFC_REG(8) _IFC_REG(9) _IFC_REG(10) _IFC_REG(11) _IFC_REG(12) _IFC_REG(13) _IFC_REG(14) _IFC_REG(15) _IFC_REG(16) _IFC_REG(17) _IFC_REG(18) _IFC_REG(19) _IFC_REG(20) _IFC_REG(21) _IFC_REG(22) _IFC_REG(23) _IFC_REG(24) _IFC_REG(25) _IFC_REG(26) _IFC_REG(27) _IFC_REG(28) _IFC_REG(29) _IFC_REG(30) _IFC_REG(31) ".iflt \\var\n\t" ".error \"Unable to parse register name \\r\"\n\t" ".endif\n\t" ".endm")
ff_line_noise_c
void ff_line_noise_c(uint8_t *dst, const uint8_t *src, const int8_t *noise, int len, int shift)
Definition: vf_noise.c:165
NoiseContext::line_noise_avg
void(* line_noise_avg)(uint8_t *dst, const uint8_t *src, int len, const int8_t *const *shift)
Definition: vf_noise.h:56
INLINE_MMXEXT
#define INLINE_MMXEXT(flags)
Definition: cpu.h:87
shift
static int shift(int a, int b)
Definition: sonic.c:83
x86_reg
int x86_reg
Definition: asm.h:72