Signed-off-by: Paul B Mahol <onemda@gmail.com>
Paul B Mahol authored on 2013/08/22 02:42:32... | ... |
@@ -4715,12 +4715,16 @@ defaults to "1". |
4715 | 4715 |
@item H |
4716 | 4716 |
Specify the hue angle as a number of radians. It accepts an |
4717 | 4717 |
expression, and defaults to "0". |
4718 |
+ |
|
4719 |
+@item b |
|
4720 |
+Specify the brightness in the [-10,10] range. It accepts an expression and |
|
4721 |
+defaults to "0". |
|
4718 | 4722 |
@end table |
4719 | 4723 |
|
4720 | 4724 |
@option{h} and @option{H} are mutually exclusive, and can't be |
4721 | 4725 |
specified at the same time. |
4722 | 4726 |
|
4723 |
-The @option{h}, @option{H} and @option{s} option values are |
|
4727 |
+The @option{b}, @option{h}, @option{H} and @option{s} option values are |
|
4724 | 4728 |
expressions containing the following constants: |
4725 | 4729 |
|
4726 | 4730 |
@table @option |
... | ... |
@@ -4790,10 +4794,11 @@ hue="s=max(0\, min(1\, (START+DURATION-t)/DURATION))" |
4790 | 4790 |
|
4791 | 4791 |
This filter supports the following commands: |
4792 | 4792 |
@table @option |
4793 |
+@item b |
|
4793 | 4794 |
@item s |
4794 | 4795 |
@item h |
4795 | 4796 |
@item H |
4796 |
-Modify the hue and/or the saturation of the input video. |
|
4797 |
+Modify the hue and/or the saturation and/or brightness of the input video. |
|
4797 | 4798 |
The command accepts the same syntax of the corresponding option. |
4798 | 4799 |
|
4799 | 4800 |
If the specified expression is not valid, it is kept at its current |
... | ... |
@@ -31,7 +31,7 @@ |
31 | 31 |
|
32 | 32 |
#define LIBAVFILTER_VERSION_MAJOR 3 |
33 | 33 |
#define LIBAVFILTER_VERSION_MINOR 82 |
34 |
-#define LIBAVFILTER_VERSION_MICRO 101 |
|
34 |
+#define LIBAVFILTER_VERSION_MICRO 102 |
|
35 | 35 |
|
36 | 36 |
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ |
37 | 37 |
LIBAVFILTER_VERSION_MINOR, \ |
... | ... |
@@ -68,11 +68,15 @@ typedef struct { |
68 | 68 |
float saturation; |
69 | 69 |
char *saturation_expr; |
70 | 70 |
AVExpr *saturation_pexpr; |
71 |
+ float brightness; |
|
72 |
+ char *brightness_expr; |
|
73 |
+ AVExpr *brightness_pexpr; |
|
71 | 74 |
int hsub; |
72 | 75 |
int vsub; |
73 | 76 |
int32_t hue_sin; |
74 | 77 |
int32_t hue_cos; |
75 | 78 |
double var_values[VAR_NB]; |
79 |
+ uint8_t lut_l[256]; |
|
76 | 80 |
uint8_t lut_u[256][256]; |
77 | 81 |
uint8_t lut_v[256][256]; |
78 | 82 |
} HueContext; |
... | ... |
@@ -86,6 +90,8 @@ static const AVOption hue_options[] = { |
86 | 86 |
{ .str = "1" }, .flags = FLAGS }, |
87 | 87 |
{ "H", "set the hue angle radians expression", OFFSET(hue_expr), AV_OPT_TYPE_STRING, |
88 | 88 |
{ .str = NULL }, .flags = FLAGS }, |
89 |
+ { "b", "set the brightness expression", OFFSET(brightness_expr), AV_OPT_TYPE_STRING, |
|
90 |
+ { .str = "0" }, .flags = FLAGS }, |
|
89 | 91 |
{ NULL } |
90 | 92 |
}; |
91 | 93 |
|
... | ... |
@@ -102,6 +108,16 @@ static inline void compute_sin_and_cos(HueContext *hue) |
102 | 102 |
hue->hue_cos = rint(cos(hue->hue) * (1 << 16) * hue->saturation); |
103 | 103 |
} |
104 | 104 |
|
105 |
+static inline void create_luma_lut(HueContext *h) |
|
106 |
+{ |
|
107 |
+ const float b = h->brightness; |
|
108 |
+ int i; |
|
109 |
+ |
|
110 |
+ for (i = 0; i < 256; i++) { |
|
111 |
+ h->lut_l[i] = av_clip_uint8(i + b * 25.5); |
|
112 |
+ } |
|
113 |
+} |
|
114 |
+ |
|
105 | 115 |
static inline void create_chrominance_lut(HueContext *h, const int32_t c, |
106 | 116 |
const int32_t s) |
107 | 117 |
{ |
... | ... |
@@ -181,14 +197,15 @@ static av_cold int init(AVFilterContext *ctx) |
181 | 181 |
if (ret < 0) \ |
182 | 182 |
return ret; \ |
183 | 183 |
} while (0) |
184 |
+ SET_EXPR(brightness, "b"); |
|
184 | 185 |
SET_EXPR(saturation, "s"); |
185 | 186 |
SET_EXPR(hue_deg, "h"); |
186 | 187 |
SET_EXPR(hue, "H"); |
187 | 188 |
#undef SET_EXPR |
188 | 189 |
|
189 | 190 |
av_log(ctx, AV_LOG_VERBOSE, |
190 |
- "H_expr:%s h_deg_expr:%s s_expr:%s\n", |
|
191 |
- hue->hue_expr, hue->hue_deg_expr, hue->saturation_expr); |
|
191 |
+ "H_expr:%s h_deg_expr:%s s_expr:%s b_expr:%s\n", |
|
192 |
+ hue->hue_expr, hue->hue_deg_expr, hue->saturation_expr, hue->brightness_expr); |
|
192 | 193 |
compute_sin_and_cos(hue); |
193 | 194 |
|
194 | 195 |
return 0; |
... | ... |
@@ -198,6 +215,7 @@ static av_cold void uninit(AVFilterContext *ctx) |
198 | 198 |
{ |
199 | 199 |
HueContext *hue = ctx->priv; |
200 | 200 |
|
201 |
+ av_expr_free(hue->brightness_pexpr); |
|
201 | 202 |
av_expr_free(hue->hue_deg_pexpr); |
202 | 203 |
av_expr_free(hue->hue_pexpr); |
203 | 204 |
av_expr_free(hue->saturation_pexpr); |
... | ... |
@@ -235,6 +253,22 @@ static int config_props(AVFilterLink *inlink) |
235 | 235 |
return 0; |
236 | 236 |
} |
237 | 237 |
|
238 |
+static void apply_luma_lut(HueContext *s, |
|
239 |
+ uint8_t *ldst, const int dst_linesize, |
|
240 |
+ uint8_t *lsrc, const int src_linesize, |
|
241 |
+ int w, int h) |
|
242 |
+{ |
|
243 |
+ int i; |
|
244 |
+ |
|
245 |
+ while (h--) { |
|
246 |
+ for (i = 0; i < w; i++) |
|
247 |
+ ldst[i] = s->lut_l[lsrc[i]]; |
|
248 |
+ |
|
249 |
+ lsrc += src_linesize; |
|
250 |
+ ldst += dst_linesize; |
|
251 |
+ } |
|
252 |
+} |
|
253 |
+ |
|
238 | 254 |
static void apply_lut(HueContext *s, |
239 | 255 |
uint8_t *udst, uint8_t *vdst, const int dst_linesize, |
240 | 256 |
uint8_t *usrc, uint8_t *vsrc, const int src_linesize, |
... | ... |
@@ -267,6 +301,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) |
267 | 267 |
AVFilterLink *outlink = inlink->dst->outputs[0]; |
268 | 268 |
AVFrame *outpic; |
269 | 269 |
const int32_t old_hue_sin = hue->hue_sin, old_hue_cos = hue->hue_cos; |
270 |
+ const float old_brightness = hue->brightness; |
|
270 | 271 |
int direct = 0; |
271 | 272 |
|
272 | 273 |
if (av_frame_is_writable(inpic)) { |
... | ... |
@@ -296,6 +331,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) |
296 | 296 |
} |
297 | 297 |
} |
298 | 298 |
|
299 |
+ if (hue->brightness_expr) { |
|
300 |
+ hue->brightness = av_expr_eval(hue->brightness_pexpr, hue->var_values, NULL); |
|
301 |
+ |
|
302 |
+ if (hue->brightness < -10 || hue->brightness > 10) { |
|
303 |
+ hue->brightness = av_clipf(hue->brightness, -10, 10); |
|
304 |
+ av_log(inlink->dst, AV_LOG_WARNING, |
|
305 |
+ "Brightness value not in range [%d,%d]: clipping value to %0.1f\n", |
|
306 |
+ -10, 10, hue->brightness); |
|
307 |
+ } |
|
308 |
+ } |
|
309 |
+ |
|
299 | 310 |
if (hue->hue_deg_expr) { |
300 | 311 |
hue->hue_deg = av_expr_eval(hue->hue_deg_pexpr, hue->var_values, NULL); |
301 | 312 |
hue->hue = hue->hue_deg * M_PI / 180; |
... | ... |
@@ -305,18 +351,22 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) |
305 | 305 |
} |
306 | 306 |
|
307 | 307 |
av_log(inlink->dst, AV_LOG_DEBUG, |
308 |
- "H:%0.1f*PI h:%0.1f s:%0.f t:%0.1f n:%d\n", |
|
309 |
- hue->hue/M_PI, hue->hue_deg, hue->saturation, |
|
308 |
+ "H:%0.1f*PI h:%0.1f s:%0.f b:%0.f t:%0.1f n:%d\n", |
|
309 |
+ hue->hue/M_PI, hue->hue_deg, hue->saturation, hue->brightness, |
|
310 | 310 |
hue->var_values[VAR_T], (int)hue->var_values[VAR_N]); |
311 | 311 |
|
312 | 312 |
compute_sin_and_cos(hue); |
313 | 313 |
if (old_hue_sin != hue->hue_sin || old_hue_cos != hue->hue_cos) |
314 | 314 |
create_chrominance_lut(hue, hue->hue_cos, hue->hue_sin); |
315 | 315 |
|
316 |
+ if (old_brightness != hue->brightness && hue->brightness) |
|
317 |
+ create_luma_lut(hue); |
|
318 |
+ |
|
316 | 319 |
if (!direct) { |
317 |
- av_image_copy_plane(outpic->data[0], outpic->linesize[0], |
|
318 |
- inpic->data[0], inpic->linesize[0], |
|
319 |
- inlink->w, inlink->h); |
|
320 |
+ if (!hue->brightness) |
|
321 |
+ av_image_copy_plane(outpic->data[0], outpic->linesize[0], |
|
322 |
+ inpic->data[0], inpic->linesize[0], |
|
323 |
+ inlink->w, inlink->h); |
|
320 | 324 |
if (inpic->data[3]) |
321 | 325 |
av_image_copy_plane(outpic->data[3], outpic->linesize[3], |
322 | 326 |
inpic->data[3], inpic->linesize[3], |
... | ... |
@@ -327,6 +377,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) |
327 | 327 |
inpic->data[1], inpic->data[2], inpic->linesize[1], |
328 | 328 |
FF_CEIL_RSHIFT(inlink->w, hue->hsub), |
329 | 329 |
FF_CEIL_RSHIFT(inlink->h, hue->vsub)); |
330 |
+ if (hue->brightness) |
|
331 |
+ apply_luma_lut(hue, outpic->data[0], outpic->linesize[0], |
|
332 |
+ inpic->data[0], inpic->linesize[0], inlink->w, inlink->h); |
|
330 | 333 |
|
331 | 334 |
if (!direct) |
332 | 335 |
av_frame_free(&inpic); |
... | ... |
@@ -355,6 +408,8 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar |
355 | 355 |
av_freep(&hue->hue_deg_expr); |
356 | 356 |
} else if (!strcmp(cmd, "s")) { |
357 | 357 |
SET_EXPR(saturation, "s"); |
358 |
+ } else if (!strcmp(cmd, "b")) { |
|
359 |
+ SET_EXPR(brightness, "b"); |
|
358 | 360 |
} else |
359 | 361 |
return AVERROR(ENOSYS); |
360 | 362 |
|