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
This commit is contained in:
parent
e63a17bfdc
commit
08c51e12b1
2
configure
vendored
2
configure
vendored
@ -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"
|
||||
|
@ -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
|
||||
|
51
ffplay.c
51
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 ((ret = configure_filtergraph(graph, vfilters, filt_src, filt_crop)) < 0)
|
||||
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, 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, },
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user