[FFmpeg-cvslog] ffplay: support rotated video.
Clément Bœsch
git at videolan.org
Fri May 23 23:30:30 CEST 2014
ffmpeg | branch: master | Clément Bœsch <u at pkh.me> | Fri Apr 18 23:15:54 2014 +0200| [08c51e12b1c3f3e3e68e33eb46be7131df5b3682] | committer: Clément Bœsch
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
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=08c51e12b1c3f3e3e68e33eb46be7131df5b3682
---
configure | 2 +-
doc/ffplay.texi | 4 ++++
ffplay.c | 51 +++++++++++++++++++++++++++++++++++++++++++--------
3 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/configure b/configure
index 0848fed..36dcd93 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 3a03d36..203085c 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.
+
+ at 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 9aa87cc..fb07d41 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, },
};
More information about the ffmpeg-cvslog
mailing list