Commit 5b0c7052 authored by Michael Niedermayer's avatar Michael Niedermayer

Merge remote-tracking branch 'cus/stable'

* cus/stable:
  ffplay: add support for toggling between multiple video filters with the w key
  ffplay: fix typo in docs
  ffplay: try multiple sample rates if audio open fails
  cmdutils: replace usages of "#ifdef __MINGW32__" with "#ifdef _WIN32" because MSVC only defines _WIN32
  ffplay: fix compilation with Visual Studio
  ffplay: increase AV_SYNC_THRESHOLD_MIN to 0.04
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents 11e49033 a583e2be
......@@ -30,7 +30,7 @@
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#ifdef __MINGW32__
#ifdef _WIN32
#undef main /* We don't want SDL to override our main() */
#endif
......
......@@ -84,6 +84,9 @@ output. In the filtergraph, the input is associated to the label
ffmpeg-filters manual for more information about the filtergraph
syntax.
You can specify this parameter multiple times and cycle through the specified
filtergraphs along with the show modes by pressing the key @key{w}.
@item -af @var{filtergraph}
@var{filtergraph} is a description of the filtergraph to apply to
the input audio.
......@@ -174,7 +177,7 @@ Toggle full screen.
Pause.
@item a
Cycle audio channel in the curret program.
Cycle audio channel in the current program.
@item v
Cycle video channel.
......@@ -186,7 +189,7 @@ Cycle subtitle channel in the current program.
Cycle program.
@item w
Show audio waves.
Cycle video filters or show modes.
@item s
Step to the next frame.
......
......@@ -72,7 +72,7 @@ const int program_birth_year = 2003;
#define SDL_AUDIO_BUFFER_SIZE 1024
/* no AV sync correction is done if below the minimum AV sync threshold */
#define AV_SYNC_THRESHOLD_MIN 0.01
#define AV_SYNC_THRESHOLD_MIN 0.04
/* AV sync correction is done if above the maximum AV sync threshold */
#define AV_SYNC_THRESHOLD_MAX 0.1
/* If a frame duration is longer than this, it will not be duplicated to compensate AV sync */
......@@ -268,6 +268,7 @@ typedef struct VideoState {
int step;
#if CONFIG_AVFILTER
int vfilter_idx;
AVFilterContext *in_video_filter; // the first filter in the video chain
AVFilterContext *out_video_filter; // the last filter in the video chain
AVFilterContext *in_audio_filter; // the first filter in the audio chain
......@@ -324,7 +325,8 @@ double rdftspeed = 0.02;
static int64_t cursor_last_shown;
static int cursor_hidden = 0;
#if CONFIG_AVFILTER
static char *vfilters = NULL;
static const char **vfilters_list = NULL;
static int nb_vfilters = 0;
static char *afilters = NULL;
#endif
......@@ -339,6 +341,15 @@ static AVPacket flush_pkt;
static SDL_Surface *screen;
#if CONFIG_AVFILTER
static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
{
GROW_ARRAY(vfilters_list, nb_vfilters);
vfilters_list[nb_vfilters - 1] = arg;
return 0;
}
#endif
static inline
int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1,
enum AVSampleFormat fmt2, int64_t channel_count2)
......@@ -1051,7 +1062,7 @@ static void do_exit(VideoState *is)
av_lockmgr_register(NULL);
uninit_opts();
#if CONFIG_AVFILTER
av_freep(&vfilters);
av_freep(&vfilters_list);
#endif
avformat_network_deinit();
if (show_status)
......@@ -1919,6 +1930,7 @@ static int video_thread(void *arg)
int last_h = 0;
enum AVPixelFormat last_format = -2;
int last_serial = -1;
int last_vfilter_idx = 0;
#endif
for (;;) {
......@@ -1937,7 +1949,8 @@ static int video_thread(void *arg)
if ( last_w != frame->width
|| last_h != frame->height
|| last_format != frame->format
|| last_serial != serial) {
|| last_serial != serial
|| last_vfilter_idx != is->vfilter_idx) {
av_log(NULL, AV_LOG_DEBUG,
"Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
last_w, last_h,
......@@ -1946,7 +1959,7 @@ static int video_thread(void *arg)
(const char *)av_x_if_null(av_get_pix_fmt_name(frame->format), "none"), serial);
avfilter_graph_free(&graph);
graph = avfilter_graph_alloc();
if ((ret = configure_video_filters(graph, is, vfilters, frame)) < 0) {
if ((ret = configure_video_filters(graph, is, vfilters_list ? vfilters_list[is->vfilter_idx] : NULL, frame)) < 0) {
SDL_Event event;
event.type = FF_QUIT_EVENT;
event.user.data1 = is;
......@@ -1959,6 +1972,7 @@ static int video_thread(void *arg)
last_h = frame->height;
last_format = frame->format;
last_serial = serial;
last_vfilter_idx = is->vfilter_idx;
frame_rate = filt_out->inputs[0]->frame_rate;
}
......@@ -2415,6 +2429,8 @@ static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb
SDL_AudioSpec wanted_spec, spec;
const char *env;
static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000};
int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1;
env = SDL_getenv("SDL_AUDIO_CHANNELS");
if (env) {
......@@ -2425,24 +2441,32 @@ static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb
wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX;
}
wanted_spec.channels = av_get_channel_layout_nb_channels(wanted_channel_layout);
wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout);
wanted_spec.channels = wanted_nb_channels;
wanted_spec.freq = wanted_sample_rate;
if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
av_log(NULL, AV_LOG_ERROR, "Invalid sample rate or channel count!\n");
return -1;
}
while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq)
next_sample_rate_idx--;
wanted_spec.format = AUDIO_S16SYS;
wanted_spec.silence = 0;
wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
wanted_spec.callback = sdl_audio_callback;
wanted_spec.userdata = opaque;
while (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels): %s\n", wanted_spec.channels, SDL_GetError());
av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n",
wanted_spec.channels, wanted_spec.freq, SDL_GetError());
wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)];
if (!wanted_spec.channels) {
av_log(NULL, AV_LOG_ERROR,
"No more channel combinations to try, audio open failed\n");
return -1;
wanted_spec.freq = next_sample_rates[next_sample_rate_idx--];
wanted_spec.channels = wanted_nb_channels;
if (!wanted_spec.freq) {
av_log(NULL, AV_LOG_ERROR,
"No more combinations to try, audio open failed\n");
return -1;
}
}
wanted_channel_layout = av_get_default_channel_layout(wanted_spec.channels);
}
......@@ -2824,7 +2848,10 @@ static int read_thread(void *arg)
if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
AVStream *st = ic->streams[st_index[AVMEDIA_TYPE_VIDEO]];
AVCodecContext *avctx = st->codec;
VideoPicture vp = {.width = avctx->width, .height = avctx->height, .sar = av_guess_sample_aspect_ratio(ic, st, NULL)};
VideoPicture vp = {0};
vp.width = avctx->width;
vp.height = avctx->height;
vp.sar = av_guess_sample_aspect_ratio(ic, st, NULL);
if (vp.width)
set_default_window_size(&vp);
}
......@@ -3250,7 +3277,17 @@ static void event_loop(VideoState *cur_stream)
stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
break;
case SDLK_w:
#if CONFIG_AVFILTER
if (cur_stream->show_mode == SHOW_MODE_VIDEO && cur_stream->vfilter_idx < nb_vfilters - 1) {
if (++cur_stream->vfilter_idx >= nb_vfilters)
cur_stream->vfilter_idx = 0;
} else {
cur_stream->vfilter_idx = 0;
toggle_audio_display(cur_stream);
}
#else
toggle_audio_display(cur_stream);
#endif
break;
case SDLK_PAGEUP:
if (cur_stream->ic->nb_chapters <= 1) {
......@@ -3516,7 +3553,7 @@ static const OptionDef options[] = {
{ "infbuf", OPT_BOOL | OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" },
{ "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" },
#if CONFIG_AVFILTER
{ "vf", OPT_STRING | HAS_ARG, { &vfilters }, "set video filters", "filter_graph" },
{ "vf", OPT_EXPERT | HAS_ARG, { .func_arg = opt_add_vfilter }, "set video filters", "filter_graph" },
{ "af", OPT_STRING | HAS_ARG, { &afilters }, "set audio filters", "filter_graph" },
#endif
{ "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
......@@ -3559,7 +3596,7 @@ void show_help_default(const char *opt, const char *arg)
"v cycle video channel\n"
"t cycle subtitle channel in the current program\n"
"c cycle program\n"
"w show audio waves\n"
"w cycle video filters or show modes\n"
"s activate frame-step mode\n"
"left/right seek backward/forward 10 seconds\n"
"down/up seek backward/forward 1 minute\n"
......@@ -3632,7 +3669,7 @@ int main(int argc, char **argv)
flags &= ~SDL_INIT_AUDIO;
if (display_disable)
SDL_putenv(dummy_videodriver); /* For the event queue, we always need a video driver. */
#if !defined(__MINGW32__) && !defined(__APPLE__)
#if !defined(_WIN32) && !defined(__APPLE__)
flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
#endif
if (SDL_Init (flags)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment