aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClément Bœsch <u@pkh.me>2014-04-18 23:15:54 +0200
committerClément Bœsch <u@pkh.me>2014-05-23 23:30:21 +0200
commit08c51e12b1c3f3e3e68e33eb46be7131df5b3682 (patch)
tree68a3778e428660bb28c298e01951224af7714b27
parente63a17bfdc99441ff25e188d2398bf1a8f1fbb7e (diff)
downloadffmpeg-08c51e12b1c3f3e3e68e33eb46be7131df5b3682.tar.gz
ffplay: support rotated video.
with -f lavfi -i testsrc=s=hd1080 as source: rotate=90*PI/180 vs transpose=clock: 42fps -> 64fps rotate=180*PI/180 vs vflip,hflip: 75fps -> 77fps rotate=270*PI/180 vs transpose=cclock: 43fps -> 63fps
-rwxr-xr-xconfigure2
-rw-r--r--doc/ffplay.texi4
-rw-r--r--ffplay.c51
3 files changed, 48 insertions, 9 deletions
diff --git a/configure b/configure
index 0848fed3e6..36dcd93f19 100755
--- a/configure
+++ b/configure
@@ -2565,7 +2565,7 @@ ffmpeg_select="aformat_filter anull_filter atrim_filter format_filter
setpts_filter trim_filter"
ffplay_deps="avcodec avformat swscale swresample sdl"
ffplay_libs='$sdl_libs'
-ffplay_select="rdft crop_filter"
+ffplay_select="rdft crop_filter transpose_filter hflip_filter vflip_filter rotate_filter"
ffprobe_deps="avcodec avformat"
ffserver_deps="avformat fork sarestart"
ffserver_select="ffm_muxer rtp_protocol rtsp_demuxer"
diff --git a/doc/ffplay.texi b/doc/ffplay.texi
index 3a03d36d04..203085c16d 100644
--- a/doc/ffplay.texi
+++ b/doc/ffplay.texi
@@ -162,6 +162,10 @@ Force a specific video decoder.
@item -scodec @var{codec_name}
Force a specific subtitle decoder.
+
+@item -autorotate
+Automatically rotate the video according to presentation metadata. Set by
+default, use -noautorotate to disable.
@end table
@section While playing
diff --git a/ffplay.c b/ffplay.c
index 9aa87cccf9..fb07d41f99 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -329,6 +329,7 @@ static const char **vfilters_list = NULL;
static int nb_vfilters = 0;
static char *afilters = NULL;
#endif
+static int autorotate = 1;
/* current context */
static int is_full_screen;
@@ -1784,7 +1785,7 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
char sws_flags_str[128];
char buffersrc_args[256];
int ret;
- AVFilterContext *filt_src = NULL, *filt_out = NULL, *filt_crop;
+ AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter = NULL;
AVCodecContext *codec = is->video_st->codec;
AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL);
@@ -1815,16 +1816,49 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
if ((ret = av_opt_set_int_list(filt_out, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0)
goto fail;
+ last_filter = filt_out;
+
+/* Note: this macro adds a filter before the lastly added filter, so the
+ * processing order of the filters is in reverse */
+#define INSERT_FILT(name, arg) do { \
+ AVFilterContext *filt_ctx; \
+ \
+ ret = avfilter_graph_create_filter(&filt_ctx, \
+ avfilter_get_by_name(name), \
+ "ffplay_" name, arg, NULL, graph); \
+ if (ret < 0) \
+ goto fail; \
+ \
+ ret = avfilter_link(filt_ctx, 0, last_filter, 0); \
+ if (ret < 0) \
+ goto fail; \
+ \
+ last_filter = filt_ctx; \
+} while (0)
+
/* SDL YUV code is not handling odd width/height for some driver
* combinations, therefore we crop the picture to an even width/height. */
- if ((ret = avfilter_graph_create_filter(&filt_crop,
- avfilter_get_by_name("crop"),
- "ffplay_crop", "floor(in_w/2)*2:floor(in_h/2)*2", NULL, graph)) < 0)
- goto fail;
- if ((ret = avfilter_link(filt_crop, 0, filt_out, 0)) < 0)
- goto fail;
+ INSERT_FILT("crop", "floor(in_w/2)*2:floor(in_h/2)*2");
+
+ if (autorotate) {
+ AVDictionaryEntry *rotate_tag = av_dict_get(is->video_st->metadata, "rotate", NULL, 0);
+ if (rotate_tag && *rotate_tag->value && strcmp(rotate_tag->value, "0")) {
+ if (!strcmp(rotate_tag->value, "90")) {
+ INSERT_FILT("transpose", "clock");
+ } else if (!strcmp(rotate_tag->value, "180")) {
+ INSERT_FILT("hflip", NULL);
+ INSERT_FILT("vflip", NULL);
+ } else if (!strcmp(rotate_tag->value, "270")) {
+ INSERT_FILT("transpose", "cclock");
+ } else {
+ char rotate_buf[64];
+ snprintf(rotate_buf, sizeof(rotate_buf), "%s*PI/180", rotate_tag->value);
+ INSERT_FILT("rotate", rotate_buf);
+ }
+ }
+ }
- if ((ret = configure_filtergraph(graph, vfilters, filt_src, filt_crop)) < 0)
+ if ((ret = configure_filtergraph(graph, vfilters, filt_src, last_filter)) < 0)
goto fail;
is->in_video_filter = filt_src;
@@ -3564,6 +3598,7 @@ static const OptionDef options[] = {
{ "acodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &audio_codec_name }, "force audio decoder", "decoder_name" },
{ "scodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &subtitle_codec_name }, "force subtitle decoder", "decoder_name" },
{ "vcodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &video_codec_name }, "force video decoder", "decoder_name" },
+ { "autorotate", OPT_BOOL, { &autorotate }, "automatically rotate video", "" },
{ NULL, },
};