mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-26 19:01:44 +02:00
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: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
commit
5b0c7052fb
@ -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.
|
||||
|
65
ffplay.c
65
ffplay.c
@ -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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user