[FFmpeg-devel] [PATCH v4 1/2] fftools/ffmpeg_filter, ffplay: Add flip support to rotation
Jun Li
junli1026 at gmail.com
Wed May 8 09:24:07 EEST 2019
Current implemantion for autoratation does not support flip.
That is, if the matrix contains flip info, the API get_rotation
only reflects partial information. This change is for adding
support for hflip (vflip can be achieved by rotation+hflip).
---
fftools/cmdutils.c | 4 ++--
fftools/cmdutils.h | 2 +-
fftools/ffmpeg_filter.c | 31 ++++++++++++++++++++++++++-----
fftools/ffplay.c | 22 ++++++++++++++++++----
libavutil/display.c | 14 ++++++++++++++
libavutil/display.h | 14 ++++++++++++++
libavutil/tests/display.c | 8 ++++++++
tests/ref/fate/display | 4 ++++
8 files changed, 87 insertions(+), 12 deletions(-)
diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c
index 9cfbc45c2b..1235a3dd7b 100644
--- a/fftools/cmdutils.c
+++ b/fftools/cmdutils.c
@@ -2172,13 +2172,13 @@ void *grow_array(void *array, int elem_size, int *size, int new_size)
return array;
}
-double get_rotation(AVStream *st)
+double get_rotation_hflip(AVStream *st, int* hflip)
{
uint8_t* displaymatrix = av_stream_get_side_data(st,
AV_PKT_DATA_DISPLAYMATRIX, NULL);
double theta = 0;
if (displaymatrix)
- theta = -av_display_rotation_get((int32_t*) displaymatrix);
+ theta = -av_display_rotation_hflip_get((int32_t*) displaymatrix, hflip);
theta -= 360*floor(theta/360 + 0.9/360);
diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h
index 6e2e0a2acb..0349d1bea7 100644
--- a/fftools/cmdutils.h
+++ b/fftools/cmdutils.h
@@ -643,6 +643,6 @@ void *grow_array(void *array, int elem_size, int *size, int new_size);
char name[128];\
av_get_channel_layout_string(name, sizeof(name), 0, ch_layout);
-double get_rotation(AVStream *st);
+double get_rotation_hflip(AVStream *st, int* hflip);
#endif /* FFTOOLS_CMDUTILS_H */
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 72838de1e2..b000958015 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -807,22 +807,43 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
last_filter = ifilter->filter;
if (ist->autorotate) {
- double theta = get_rotation(ist->st);
+ int hflip = 0;
+ double theta = get_rotation_hflip(ist->st, &hflip);
- if (fabs(theta - 90) < 1.0) {
+ if (fabs(theta) < 1.0) {
+ if (hflip)
+ ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
+ } else if (fabs(theta - 90) < 1.0) {
ret = insert_filter(&last_filter, &pad_idx, "transpose", "clock");
- } else if (fabs(theta - 180) < 1.0) {
- ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
if (ret < 0)
return ret;
- ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
+ if (hflip)
+ ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
+ } else if (fabs(theta - 180) < 1.0) {
+ if (hflip) { // rotate 180 and hflip equals vflip
+ ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
+ } else {
+ ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
+ if (ret < 0)
+ return ret;
+ ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
+ }
} else if (fabs(theta - 270) < 1.0) {
ret = insert_filter(&last_filter, &pad_idx, "transpose", "cclock");
+ if (ret < 0)
+ return ret;
+ if (hflip)
+ ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
} else if (fabs(theta) > 1.0) {
char rotate_buf[64];
snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
ret = insert_filter(&last_filter, &pad_idx, "rotate", rotate_buf);
+ if (ret < 0)
+ return ret;
+ if (hflip)
+ ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
}
+
if (ret < 0)
return ret;
}
diff --git a/fftools/ffplay.c b/fftools/ffplay.c
index 8f050e16e6..2c77612193 100644
--- a/fftools/ffplay.c
+++ b/fftools/ffplay.c
@@ -1914,19 +1914,33 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
} while (0)
if (autorotate) {
- double theta = get_rotation(is->video_st);
+ int hflip;
+ double theta = get_rotation_hflip(is->video_st, &hflip);
- if (fabs(theta - 90) < 1.0) {
+ if (fabs(theta) < 1.0) {
+ if (hflip)
+ INSERT_FILT("hflip", NULL);
+ } else if (fabs(theta - 90) < 1.0) {
INSERT_FILT("transpose", "clock");
+ if (hflip)
+ INSERT_FILT("hflip", NULL);
} else if (fabs(theta - 180) < 1.0) {
- INSERT_FILT("hflip", NULL);
- INSERT_FILT("vflip", NULL);
+ if (hflip) { // rotate 180 and hflip equals vflip
+ INSERT_FILT("vflip", NULL);
+ } else {
+ INSERT_FILT("hflip", NULL);
+ INSERT_FILT("vflip", NULL);
+ }
} else if (fabs(theta - 270) < 1.0) {
INSERT_FILT("transpose", "cclock");
+ if (hflip)
+ INSERT_FILT("hflip", NULL);
} else if (fabs(theta) > 1.0) {
char rotate_buf[64];
snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
INSERT_FILT("rotate", rotate_buf);
+ if (hflip)
+ INSERT_FILT("hflip", NULL);
}
}
diff --git a/libavutil/display.c b/libavutil/display.c
index a0076e067b..855de4a006 100644
--- a/libavutil/display.c
+++ b/libavutil/display.c
@@ -71,3 +71,17 @@ void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip)
for (i = 0; i < 9; i++)
matrix[i] *= flip[i % 3];
}
+
+double av_display_rotation_hflip_get(const int32_t matrix[9], int *hflip)
+{
+ int32_t m[9];
+ *hflip = 0;
+ memcpy(m, matrix, sizeof(m));
+
+ if (m[0] > 0 && m[4] < 0 || m[0] < 0 && m[4] > 0 ||
+ m[1] > 0 && m[3] > 0 || m[1] < 0 && m[3] < 0) {
+ *hflip = 1;
+ av_display_matrix_flip(m, 1, 0);
+ }
+ return av_display_rotation_get(m);
+}
\ No newline at end of file
diff --git a/libavutil/display.h b/libavutil/display.h
index 515adad795..23d71a0bc5 100644
--- a/libavutil/display.h
+++ b/libavutil/display.h
@@ -106,6 +106,20 @@ void av_display_rotation_set(int32_t matrix[9], double angle);
*/
void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip);
+/**
+ * Extract the rotation component and hflip status of the transformation matrix.
+ *
+ * @param matrix the transformation matrix
+ * @param hflip wille be set to 1 if the matrix need horizontal flipped
+ * @return the angle (in degrees) by which the transformation rotates the frame
+ * counterclockwise. The angle will be in range [-180.0, 180.0],
+ * or NaN if the matrix is singular.
+ *
+ * @note floating point numbers are inherently inexact, so callers are
+ * recommended to round the return value to nearest integer before use.
+ */
+double av_display_rotation_hflip_get(const int32_t matrix[9], int* hflip);
+
/**
* @}
* @}
diff --git a/libavutil/tests/display.c b/libavutil/tests/display.c
index 893ebb5543..65a0971e7b 100644
--- a/libavutil/tests/display.c
+++ b/libavutil/tests/display.c
@@ -35,6 +35,8 @@ static void print_matrix(int32_t matrix[9])
int main(void)
{
int32_t matrix[9];
+ int hflip = 0;
+ double degree;
// Set the matrix to 90 degrees
av_display_rotation_set(matrix, 90);
@@ -56,6 +58,12 @@ int main(void)
print_matrix(matrix);
printf("degrees: %f\n", av_display_rotation_get(matrix));
+ // flip vertical
+ av_display_matrix_flip(matrix, 0, 1);
+ print_matrix(matrix);
+ degree = av_display_rotation_hflip_get(matrix, &hflip);
+ printf("degrees: %f, hflip: %i\n", degree, hflip);
+
return 0;
}
diff --git a/tests/ref/fate/display b/tests/ref/fate/display
index 251e7e0cdf..14b4c7db7c 100644
--- a/tests/ref/fate/display
+++ b/tests/ref/fate/display
@@ -14,3 +14,7 @@ degrees: 135.000000
-46340 -46340 0
0 0 1073741824
degrees: -135.000000
+-46340 -46340 0
+-46340 46340 0
+0 0 1073741824
+degrees: 45.000000, hflip: 1
--
2.17.1
More information about the ffmpeg-devel
mailing list