[FFmpeg-devel] [PATCH 3/4] ffmpeg: use display matrix frame side data for autorotation
James Almer
jamrial at gmail.com
Wed Sep 8 21:34:25 EEST 2021
And give it priority over stream side data when present.
Fixes part of ticket #6945.
Signed-off-by: James Almer <jamrial at gmail.com>
---
fftools/cmdutils.c | 4 +---
fftools/cmdutils.h | 2 +-
fftools/ffmpeg.c | 8 ++++++++
fftools/ffmpeg.h | 1 +
fftools/ffmpeg_filter.c | 14 +++++++++++++-
fftools/ffplay.c | 3 ++-
6 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c
index 7e9c4299fa..ed3dcd31f4 100644
--- a/fftools/cmdutils.c
+++ b/fftools/cmdutils.c
@@ -2201,10 +2201,8 @@ void *grow_array(void *array, int elem_size, int *size, int new_size)
return array;
}
-double get_rotation(AVStream *st)
+double get_rotation(int32_t *displaymatrix)
{
- uint8_t* displaymatrix = av_stream_get_side_data(st,
- AV_PKT_DATA_DISPLAYMATRIX, NULL);
double theta = 0;
if (displaymatrix)
theta = -round(av_display_rotation_get((int32_t*) displaymatrix));
diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h
index 9caad01865..30f0b79725 100644
--- a/fftools/cmdutils.h
+++ b/fftools/cmdutils.h
@@ -648,6 +648,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(int32_t *displaymatrix);
#endif /* FFTOOLS_CMDUTILS_H */
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index a9bb9d964d..5365f711e5 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -535,6 +535,7 @@ static void ffmpeg_cleanup(int ret)
av_frame_free(&frame);
}
av_fifo_freep(&ifilter->frame_queue);
+ av_freep(&ifilter->displaymatrix);
if (ist->sub2video.sub_queue) {
while (av_fifo_size(ist->sub2video.sub_queue)) {
AVSubtitle sub;
@@ -2183,6 +2184,7 @@ static int ifilter_has_all_input_formats(FilterGraph *fg)
static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
{
FilterGraph *fg = ifilter->graph;
+ AVFrameSideData *sd;
int need_reinit, ret, i;
/* determine if the parameters for this input changed */
@@ -2207,6 +2209,12 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
(ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data))
need_reinit = 1;
+ if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)) {
+ if (!ifilter->displaymatrix || memcmp(sd->data, ifilter->displaymatrix, sizeof(int32_t) * 9))
+ need_reinit = 1;
+ } else if (ifilter->displaymatrix)
+ need_reinit = 1;
+
if (need_reinit) {
ret = ifilter_parameters_from_frame(ifilter, frame);
if (ret < 0)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 1194bb0cae..30225e9ffe 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -258,6 +258,7 @@ typedef struct InputFilter {
uint64_t channel_layout;
AVBufferRef *hw_frames_ctx;
+ int32_t *displaymatrix;
int eof;
} InputFilter;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 6b7b6ca1b3..a4c2de07da 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -757,7 +757,12 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
last_filter = ifilter->filter;
if (ist->autorotate) {
- double theta = get_rotation(ist->st);
+ int32_t *displaymatrix = ifilter->displaymatrix;
+ double theta;
+
+ if (!displaymatrix)
+ displaymatrix = (int32_t *)av_stream_get_side_data(ist->st, AV_PKT_DATA_DISPLAYMATRIX, NULL);
+ theta = get_rotation(displaymatrix);
if (fabs(theta - 90) < 1.0) {
ret = insert_filter(&last_filter, &pad_idx, "transpose", "clock");
@@ -1127,6 +1132,8 @@ fail:
int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame)
{
+ AVFrameSideData *sd;
+
av_buffer_unref(&ifilter->hw_frames_ctx);
ifilter->format = frame->format;
@@ -1139,6 +1146,11 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame)
ifilter->channels = frame->channels;
ifilter->channel_layout = frame->channel_layout;
+ av_freep(&ifilter->displaymatrix);
+ sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX);
+ if (sd)
+ ifilter->displaymatrix = av_memdup(sd->data, sizeof(int32_t) * 9);
+
if (frame->hw_frames_ctx) {
ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx);
if (!ifilter->hw_frames_ctx)
diff --git a/fftools/ffplay.c b/fftools/ffplay.c
index 46758b9f55..ccea0e4578 100644
--- a/fftools/ffplay.c
+++ b/fftools/ffplay.c
@@ -1925,7 +1925,8 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
} while (0)
if (autorotate) {
- double theta = get_rotation(is->video_st);
+ int32_t *displaymatrix = (int32_t *)av_stream_get_side_data(is->video_st, AV_PKT_DATA_DISPLAYMATRIX, NULL);
+ double theta = get_rotation(displaymatrix);
if (fabs(theta - 90) < 1.0) {
INSERT_FILT("transpose", "clock");
--
2.33.0
More information about the ffmpeg-devel
mailing list