summaryrefslogtreecommitdiff
path: root/ffplay.c
diff options
context:
space:
mode:
Diffstat (limited to 'ffplay.c')
-rw-r--r--ffplay.c73
1 files changed, 36 insertions, 37 deletions
diff --git a/ffplay.c b/ffplay.c
index d8dbe449f9..330320780a 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -86,6 +86,9 @@ const int program_birth_year = 2003;
/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
#define AUDIO_DIFF_AVG_NB 20
+/* polls for possible required screen refresh at least this often, should be less than 1/fps */
+#define REFRESH_RATE 0.01
+
/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
/* TODO: We assume that a decoded and resampled frame fits into this buffer */
#define SAMPLE_ARRAY_SIZE (8 * 65536)
@@ -149,7 +152,6 @@ enum {
typedef struct VideoState {
SDL_Thread *read_tid;
SDL_Thread *video_tid;
- SDL_Thread *refresh_tid;
AVInputFormat *iformat;
int no_background;
int abort_request;
@@ -210,6 +212,7 @@ typedef struct VideoState {
int rdft_bits;
FFTSample *rdft_data;
int xpos;
+ double last_vis_time;
SDL_Thread *subtitle_tid;
int subtitle_stream;
@@ -256,7 +259,6 @@ typedef struct VideoState {
FrameBuffer *buffer_pool;
#endif
- int refresh;
int last_video_stream, last_audio_stream, last_subtitle_stream;
SDL_cond *continue_read_thread;
@@ -305,7 +307,7 @@ static enum ShowMode show_mode = SHOW_MODE_NONE;
static const char *audio_codec_name;
static const char *subtitle_codec_name;
static const char *video_codec_name;
-static int rdftspeed = 20;
+double rdftspeed = 0.02;
static int64_t cursor_last_shown;
static int cursor_hidden = 0;
#if CONFIG_AVFILTER
@@ -319,7 +321,6 @@ static int64_t audio_callback_time;
static AVPacket flush_pkt;
#define FF_ALLOC_EVENT (SDL_USEREVENT)
-#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
#define FF_QUIT_EVENT (SDL_USEREVENT + 2)
static SDL_Surface *screen;
@@ -972,7 +973,6 @@ static void stream_close(VideoState *is)
/* XXX: use a special url_shutdown call to abort parse cleanly */
is->abort_request = 1;
SDL_WaitThread(is->read_tid, NULL);
- SDL_WaitThread(is->refresh_tid, NULL);
packet_queue_destroy(&is->videoq);
packet_queue_destroy(&is->audioq);
packet_queue_destroy(&is->subtitleq);
@@ -1077,23 +1077,6 @@ static void video_display(VideoState *is)
video_image_display(is);
}
-static int refresh_thread(void *opaque)
-{
- VideoState *is= opaque;
- while (!is->abort_request) {
- SDL_Event event;
- event.type = FF_REFRESH_EVENT;
- event.user.data1 = opaque;
- if (!is->refresh && (!is->paused || is->force_refresh)) {
- is->refresh = 1;
- SDL_PushEvent(&event);
- }
- //FIXME ideally we should wait the correct time but SDLs event passing is so slow it would be silly
- av_usleep(is->audio_st && is->show_mode != SHOW_MODE_VIDEO ? rdftspeed*1000 : 5000);
- }
- return 0;
-}
-
/* get the current audio clock value */
static double get_audio_clock(VideoState *is)
{
@@ -1300,7 +1283,7 @@ static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial
}
/* called to display each frame */
-static void video_refresh(void *opaque)
+static void video_refresh(void *opaque, double *remaining_time)
{
VideoState *is = opaque;
VideoPicture *vp;
@@ -1311,8 +1294,14 @@ static void video_refresh(void *opaque)
if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime)
check_external_clock_speed(is);
- if (!display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st)
- video_display(is);
+ if (!display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st) {
+ time = av_gettime() / 1000000.0;
+ if (is->force_refresh || is->last_vis_time + rdftspeed < time) {
+ video_display(is);
+ is->last_vis_time = time;
+ }
+ *remaining_time = FFMIN(*remaining_time, is->last_vis_time + rdftspeed - time);
+ }
if (is->video_st) {
if (is->force_refresh)
@@ -1348,8 +1337,10 @@ retry:
delay = compute_target_delay(is->frame_last_duration, is);
time= av_gettime()/1000000.0;
- if (time < is->frame_timer + delay)
+ if (time < is->frame_timer + delay) {
+ *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time);
return;
+ }
if (delay > 0)
is->frame_timer += delay * FFMAX(1, floor((time-is->frame_timer) / delay));
@@ -2667,8 +2658,6 @@ static int read_thread(void *arg)
if (is->show_mode == SHOW_MODE_NONE)
is->show_mode = ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
- is->refresh_tid = SDL_CreateThread(refresh_thread, is);
-
if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
stream_component_open(is, st_index[AVMEDIA_TYPE_SUBTITLE]);
}
@@ -2956,6 +2945,24 @@ static void toggle_audio_display(VideoState *is)
bgcolor, 1);
}
+static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) {
+ int got_event;
+ double remaining_time;
+ do {
+ if (!cursor_hidden && av_gettime() - cursor_last_shown > CURSOR_HIDE_DELAY) {
+ SDL_ShowCursor(0);
+ cursor_hidden = 1;
+ }
+ remaining_time = REFRESH_RATE;
+ if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh))
+ video_refresh(is, &remaining_time);
+ SDL_PumpEvents();
+ got_event = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS);
+ if (!got_event)
+ av_usleep((int64_t)(remaining_time * 1000000.0));
+ } while (!got_event);
+}
+
/* handle an event sent by the GUI */
static void event_loop(VideoState *cur_stream)
{
@@ -2964,7 +2971,7 @@ static void event_loop(VideoState *cur_stream)
for (;;) {
double x;
- SDL_WaitEvent(&event);
+ refresh_loop_wait_event(cur_stream, &event);
switch (event.type) {
case SDL_KEYDOWN:
if (exit_on_keydown) {
@@ -3102,14 +3109,6 @@ static void event_loop(VideoState *cur_stream)
case FF_ALLOC_EVENT:
alloc_picture(event.user.data1);
break;
- case FF_REFRESH_EVENT:
- if (!cursor_hidden && av_gettime() - cursor_last_shown > CURSOR_HIDE_DELAY) {
- SDL_ShowCursor(0);
- cursor_hidden = 1;
- }
- video_refresh(event.user.data1);
- cur_stream->refresh = 0;
- break;
default:
break;
}