Emulate the mp=rotate passthrough mode.
Stefano Sabatini authored on 2012/09/01 18:14:27... | ... |
@@ -3454,7 +3454,7 @@ It accepts a parameter representing an integer, which can assume the |
3454 | 3454 |
values: |
3455 | 3455 |
|
3456 | 3456 |
@table @samp |
3457 |
-@item 0 |
|
3457 |
+@item 0, 4 |
|
3458 | 3458 |
Rotate by 90 degrees counterclockwise and vertically flip (default), that is: |
3459 | 3459 |
@example |
3460 | 3460 |
L.R L.l |
... | ... |
@@ -3462,7 +3462,7 @@ L.R L.l |
3462 | 3462 |
l.r R.r |
3463 | 3463 |
@end example |
3464 | 3464 |
|
3465 |
-@item 1 |
|
3465 |
+@item 1, 5 |
|
3466 | 3466 |
Rotate by 90 degrees clockwise, that is: |
3467 | 3467 |
@example |
3468 | 3468 |
L.R l.L |
... | ... |
@@ -3470,7 +3470,7 @@ L.R l.L |
3470 | 3470 |
l.r r.R |
3471 | 3471 |
@end example |
3472 | 3472 |
|
3473 |
-@item 2 |
|
3473 |
+@item 2, 6 |
|
3474 | 3474 |
Rotate by 90 degrees counterclockwise, that is: |
3475 | 3475 |
@example |
3476 | 3476 |
L.R R.r |
... | ... |
@@ -3478,7 +3478,7 @@ L.R R.r |
3478 | 3478 |
l.r L.l |
3479 | 3479 |
@end example |
3480 | 3480 |
|
3481 |
-@item 3 |
|
3481 |
+@item 3, 7 |
|
3482 | 3482 |
Rotate by 90 degrees clockwise and vertically flip, that is: |
3483 | 3483 |
@example |
3484 | 3484 |
L.R r.R |
... | ... |
@@ -3487,6 +3487,9 @@ l.r l.L |
3487 | 3487 |
@end example |
3488 | 3488 |
@end table |
3489 | 3489 |
|
3490 |
+For values between 4-7 transposition is only done if the input video |
|
3491 |
+geometry is portrait and not landscape. |
|
3492 |
+ |
|
3490 | 3493 |
@section unsharp |
3491 | 3494 |
|
3492 | 3495 |
Sharpen or blur the input video. |
... | ... |
@@ -30,7 +30,7 @@ |
30 | 30 |
|
31 | 31 |
#define LIBAVFILTER_VERSION_MAJOR 3 |
32 | 32 |
#define LIBAVFILTER_VERSION_MINOR 15 |
33 |
-#define LIBAVFILTER_VERSION_MICRO 102 |
|
33 |
+#define LIBAVFILTER_VERSION_MICRO 103 |
|
34 | 34 |
|
35 | 35 |
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ |
36 | 36 |
LIBAVFILTER_VERSION_MINOR, \ |
... | ... |
@@ -45,6 +45,7 @@ typedef struct { |
45 | 45 |
/* 2 Rotate by 90 degrees counterclockwise. */ |
46 | 46 |
/* 3 Rotate by 90 degrees clockwise and vflip. */ |
47 | 47 |
int dir; |
48 |
+ int passthrough; ///< landscape passthrough mode enabled |
|
48 | 49 |
} TransContext; |
49 | 50 |
|
50 | 51 |
static av_cold int init(AVFilterContext *ctx, const char *args) |
... | ... |
@@ -55,8 +56,8 @@ static av_cold int init(AVFilterContext *ctx, const char *args) |
55 | 55 |
if (args) |
56 | 56 |
sscanf(args, "%d", &trans->dir); |
57 | 57 |
|
58 |
- if (trans->dir < 0 || trans->dir > 3) { |
|
59 |
- av_log(ctx, AV_LOG_ERROR, "Invalid value %d not between 0 and 3.\n", |
|
58 |
+ if (trans->dir < 0 || trans->dir > 7) { |
|
59 |
+ av_log(ctx, AV_LOG_ERROR, "Invalid value %d not between 0 and 7.\n", |
|
60 | 60 |
trans->dir); |
61 | 61 |
return AVERROR(EINVAL); |
62 | 62 |
} |
... | ... |
@@ -97,6 +98,18 @@ static int config_props_output(AVFilterLink *outlink) |
97 | 97 |
AVFilterLink *inlink = ctx->inputs[0]; |
98 | 98 |
const AVPixFmtDescriptor *pixdesc = &av_pix_fmt_descriptors[outlink->format]; |
99 | 99 |
|
100 |
+ if (trans->dir&4) { |
|
101 |
+ trans->dir &= 3; |
|
102 |
+ if (inlink->w >= inlink->h) { |
|
103 |
+ trans->passthrough = 1; |
|
104 |
+ |
|
105 |
+ av_log(ctx, AV_LOG_VERBOSE, |
|
106 |
+ "w:%d h:%d -> w:%d h:%d (landscape passthrough mode)\n", |
|
107 |
+ inlink->w, inlink->h, outlink->w, outlink->h); |
|
108 |
+ return 0; |
|
109 |
+ } |
|
110 |
+ } |
|
111 |
+ |
|
100 | 112 |
trans->hsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_w; |
101 | 113 |
trans->vsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_h; |
102 | 114 |
|
... | ... |
@@ -117,11 +130,24 @@ static int config_props_output(AVFilterLink *outlink) |
117 | 117 |
return 0; |
118 | 118 |
} |
119 | 119 |
|
120 |
+static AVFilterBufferRef *get_video_buffer(AVFilterLink *inlink, int perms, int w, int h) |
|
121 |
+{ |
|
122 |
+ TransContext *trans = inlink->dst->priv; |
|
123 |
+ |
|
124 |
+ return trans->passthrough ? |
|
125 |
+ ff_null_get_video_buffer (inlink, perms, w, h) : |
|
126 |
+ ff_default_get_video_buffer(inlink, perms, w, h); |
|
127 |
+} |
|
128 |
+ |
|
120 | 129 |
static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) |
121 | 130 |
{ |
131 |
+ TransContext *trans = inlink->dst->priv; |
|
122 | 132 |
AVFilterLink *outlink = inlink->dst->outputs[0]; |
123 | 133 |
AVFilterBufferRef *buf_out; |
124 | 134 |
|
135 |
+ if (trans->passthrough) |
|
136 |
+ return ff_null_start_frame(inlink, picref); |
|
137 |
+ |
|
125 | 138 |
outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE, |
126 | 139 |
outlink->w, outlink->h); |
127 | 140 |
if (!outlink->out_buf) |
... | ... |
@@ -150,6 +176,9 @@ static int end_frame(AVFilterLink *inlink) |
150 | 150 |
AVFilterLink *outlink = inlink->dst->outputs[0]; |
151 | 151 |
int plane, ret; |
152 | 152 |
|
153 |
+ if (trans->passthrough) |
|
154 |
+ return ff_null_end_frame(inlink); |
|
155 |
+ |
|
153 | 156 |
for (plane = 0; outpic->data[plane]; plane++) { |
154 | 157 |
int hsub = plane == 1 || plane == 2 ? trans->hsub : 0; |
155 | 158 |
int vsub = plane == 1 || plane == 2 ? trans->vsub : 0; |
... | ... |
@@ -205,7 +234,12 @@ static int end_frame(AVFilterLink *inlink) |
205 | 205 |
return 0; |
206 | 206 |
} |
207 | 207 |
|
208 |
-static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { return 0; } |
|
208 |
+static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) |
|
209 |
+{ |
|
210 |
+ TransContext *trans = inlink->dst->priv; |
|
211 |
+ |
|
212 |
+ return trans->passthrough ? ff_null_draw_slice(inlink, y, h, slice_dir) : 0; |
|
213 |
+} |
|
209 | 214 |
|
210 | 215 |
AVFilter avfilter_vf_transpose = { |
211 | 216 |
.name = "transpose", |
... | ... |
@@ -218,8 +252,9 @@ AVFilter avfilter_vf_transpose = { |
218 | 218 |
|
219 | 219 |
.inputs = (const AVFilterPad[]) {{ .name = "default", |
220 | 220 |
.type = AVMEDIA_TYPE_VIDEO, |
221 |
+ .get_video_buffer= get_video_buffer, |
|
221 | 222 |
.start_frame = start_frame, |
222 |
- .draw_slice = null_draw_slice, |
|
223 |
+ .draw_slice = draw_slice, |
|
223 | 224 |
.end_frame = end_frame, |
224 | 225 |
.min_perms = AV_PERM_READ, }, |
225 | 226 |
{ .name = NULL}}, |