#include "libavutil/avstring.h"
#include "libavutil/colorspace.h"
+#include "libavutil/display.h"
#include "libavutil/mathematics.h"
#include "libavutil/pixdesc.h"
#include "libavutil/imgutils.h"
#if CONFIG_AVFILTER
static char *vfilters = NULL;
#endif
+static int autorotate = 1;
/* current context */
static int is_full_screen;
char sws_flags_str[128];
char buffersrc_args[256];
int ret;
- AVFilterContext *filt_src = NULL, *filt_out = NULL, *filt_format;
+ AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter;
AVCodecContext *codec = is->video_st->codec;
snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%"PRId64, sws_flags);
"out", NULL, NULL, graph)) < 0)
return ret;
- if ((ret = avfilter_graph_create_filter(&filt_format,
- avfilter_get_by_name("format"),
- "format", "yuv420p", NULL, graph)) < 0)
- return ret;
- if ((ret = avfilter_link(filt_format, 0, filt_out, 0)) < 0)
- return ret;
-
+ 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), \
+ "avplay_" name, arg, NULL, graph); \
+ if (ret < 0) \
+ return ret; \
+ \
+ ret = avfilter_link(filt_ctx, 0, last_filter, 0); \
+ if (ret < 0) \
+ return ret; \
+ \
+ last_filter = filt_ctx; \
+} while (0)
+
+ INSERT_FILT("format", "yuv420p");
+
+ if (autorotate) {
+ uint8_t* displaymatrix = av_stream_get_side_data(is->video_st,
+ AV_PKT_DATA_DISPLAYMATRIX, NULL);
+ if (displaymatrix) {
+ double rot = av_display_rotation_get((int32_t*) displaymatrix);
+ if (rot < -135 || rot > 135) {
+ INSERT_FILT("vflip", NULL);
+ INSERT_FILT("hflip", NULL);
+ } else if (rot < -45) {
+ INSERT_FILT("transpose", "dir=clock");
+ } else if (rot > 45) {
+ INSERT_FILT("transpose", "dir=cclock");
+ }
+ }
+ }
if (vfilters) {
AVFilterInOut *outputs = avfilter_inout_alloc();
outputs->next = NULL;
inputs->name = av_strdup("out");
- inputs->filter_ctx = filt_format;
+ inputs->filter_ctx = last_filter;
inputs->pad_idx = 0;
inputs->next = NULL;
if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0)
return ret;
} else {
- if ((ret = avfilter_link(filt_src, 0, filt_format, 0)) < 0)
+ if ((ret = avfilter_link(filt_src, 0, last_filter, 0)) < 0)
return ret;
}
{ "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
{ "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { opt_default }, "generic catch all option", "" },
{ "i", 0, { NULL }, "avconv compatibility dummy option", ""},
+ { "autorotate", OPT_BOOL, { &autorotate }, "automatically rotate video", "" },
{ NULL, },
};