diff --git a/ijkmediaplayer/jni/ijkplayer/ffplay_display_thread.c b/ijkmediaplayer/jni/ijkplayer/ffplay_display_thread.c new file mode 100644 index 0000000000000000000000000000000000000000..4618b6f90e70bc05c23b536789c59771143aeea5 --- /dev/null +++ b/ijkmediaplayer/jni/ijkplayer/ffplay_display_thread.c @@ -0,0 +1,199 @@ +/***************************************************************************** + * ffplay_display_thread.c + ***************************************************************************** + * + * copyright (c) 2001 Fabrice Bellard + * copyright (c) 2013 Zhang Rui + * + * This file is part of ijkPlayer. + * + * ijkPlayer is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * ijkPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with ijkPlayer; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "ffplayer.h" + +/* ffplay.c 1297 */ +/* called to display each frame */ +static void video_refresh(void *opaque, double *remaining_time) +{ + FFPlayer *ffp = opaque; + VideoState *is = &ffp->is; + VideoPicture *vp; + double time; + + SubPicture *sp, *sp2; + + if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime) + check_external_clock_speed(is); + + if (!ffp->display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st) { + time = av_gettime() / 1000000.0; + if (is->force_refresh || is->last_vis_time + ffp->rdftspeed < time) { + video_display(is); + is->last_vis_time = time; + } + *remaining_time = FFMIN(*remaining_time, is->last_vis_time + ffp->rdftspeed - time); + } + + if (is->video_st) { + int redisplay = 0; + if (is->force_refresh) + redisplay = pictq_prev_picture(is); +retry: + if (is->pictq_size == 0) { + SDL_LockMutex(is->pictq_mutex); + if (is->frame_last_dropped_pts != AV_NOPTS_VALUE && is->frame_last_dropped_pts > is->frame_last_pts) { + update_video_pts(is, is->frame_last_dropped_pts, is->frame_last_dropped_pos, 0); + is->frame_last_dropped_pts = AV_NOPTS_VALUE; + } + SDL_UnlockMutex(is->pictq_mutex); + // nothing to do, no picture to display in the queue + } else { + double last_duration, duration, delay; + /* dequeue the picture */ + vp = &is->pictq[is->pictq_rindex]; + + if (vp->serial != is->videoq.serial) { + pictq_next_picture(is); + redisplay = 0; + goto retry; + } + + if (is->paused) + goto display; + + /* compute nominal last_duration */ + last_duration = vp->pts - is->frame_last_pts; + if (last_duration > 0 && last_duration < is->max_frame_duration) { + /* if duration of the last frame was sane, update last_duration in video state */ + is->frame_last_duration = last_duration; + } + delay = compute_target_delay(is->frame_last_duration, is); + + time= av_gettime()/1000000.0; + 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)); + + SDL_LockMutex(is->pictq_mutex); + update_video_pts(is, vp->pts, vp->pos, vp->serial); + SDL_UnlockMutex(is->pictq_mutex); + + if (is->pictq_size > 1) { + VideoPicture *nextvp = &is->pictq[(is->pictq_rindex + 1) % VIDEO_PICTURE_QUEUE_SIZE]; + duration = nextvp->pts - vp->pts; + if(!is->step && (redisplay || ffp->framedrop>0 || (ffp->framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) && time > is->frame_timer + duration){ + if (!redisplay) + is->frame_drops_late++; + pictq_next_picture(is); + redisplay = 0; + goto retry; + } + } + + if (is->subtitle_st) { + if (is->subtitle_stream_changed) { + SDL_LockMutex(is->subpq_mutex); + + while (is->subpq_size) { + free_subpicture(&is->subpq[is->subpq_rindex]); + + /* update queue size and signal for next picture */ + if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE) + is->subpq_rindex = 0; + + is->subpq_size--; + } + is->subtitle_stream_changed = 0; + + SDL_CondSignal(is->subpq_cond); + SDL_UnlockMutex(is->subpq_mutex); + } else { + if (is->subpq_size > 0) { + sp = &is->subpq[is->subpq_rindex]; + + if (is->subpq_size > 1) + sp2 = &is->subpq[(is->subpq_rindex + 1) % SUBPICTURE_QUEUE_SIZE]; + else + sp2 = NULL; + + if ((is->video_current_pts > (sp->pts + ((float) sp->sub.end_display_time / 1000))) + || (sp2 && is->video_current_pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000)))) + { + free_subpicture(sp); + + /* update queue size and signal for next picture */ + if (++is->subpq_rindex == SUBPICTURE_QUEUE_SIZE) + is->subpq_rindex = 0; + + SDL_LockMutex(is->subpq_mutex); + is->subpq_size--; + SDL_CondSignal(is->subpq_cond); + SDL_UnlockMutex(is->subpq_mutex); + } + } + } + } + +display: + /* display picture */ + if (!ffp->display_disable && is->show_mode == SHOW_MODE_VIDEO) + video_display(is); + + pictq_next_picture(is); + + if (is->step && !is->paused) + stream_toggle_pause(is); + } + } + is->force_refresh = 0; + if (ffp->show_status) { + static int64_t last_time; + int64_t cur_time; + int aqsize, vqsize, sqsize; + double av_diff; + + cur_time = av_gettime(); + if (!last_time || (cur_time - last_time) >= 30000) { + aqsize = 0; + vqsize = 0; + sqsize = 0; + if (is->audio_st) + aqsize = is->audioq.size; + if (is->video_st) + vqsize = is->videoq.size; + if (is->subtitle_st) + sqsize = is->subtitleq.size; + av_diff = 0; + if (is->audio_st && is->video_st) + av_diff = get_audio_clock(is) - get_video_clock(is); + printf("%7.2f A-V:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r", + get_master_clock(is), + av_diff, + is->frame_drops_early + is->frame_drops_late, + aqsize / 1024, + vqsize / 1024, + sqsize, + is->video_st ? is->video_st->codec->pts_correction_num_faulty_dts : 0, + is->video_st ? is->video_st->codec->pts_correction_num_faulty_pts : 0); + fflush(stdout); + last_time = cur_time; + } + } +} diff --git a/ijkmediaplayer/jni/ijkplayer/ffplayer.h b/ijkmediaplayer/jni/ijkplayer/ffplayer.h index 3bc26cf990ce3eb2adcf95eb21a8e86bf7f2bec3..a7e78c36a8d5fde02d74a968f89c54f2b7abf270 100644 --- a/ijkmediaplayer/jni/ijkplayer/ffplayer.h +++ b/ijkmediaplayer/jni/ijkplayer/ffplayer.h @@ -59,9 +59,7 @@ typedef struct FFPlayer { int subtitle_disable; int wanted_stream[AVMEDIA_TYPE_NB]; int seek_by_bytes; -#if 0 int display_disable; -#endif int show_status; #if 0 int av_sync_type = AV_SYNC_AUDIO_MASTER; @@ -90,8 +88,8 @@ typedef struct FFPlayer { char *audio_codec_name; char *subtitle_codec_name; char *video_codec_name; + double rdftspeed; #if 0 - double rdftspeed = 0.02; int64_t cursor_last_shown; int cursor_hidden = 0; #endif @@ -131,6 +129,7 @@ inline static void ijkff_reset(FFPlayer *ffp) ffp->wanted_stream[AVMEDIA_TYPE_VIDEO] = -1; ffp->wanted_stream[AVMEDIA_TYPE_SUBTITLE] = -1; ffp->seek_by_bytes = -1; + ffp->display_disable = 0; ffp->show_status = 1; ffp->start_time = AV_NOPTS_VALUE; ffp->duration = AV_NOPTS_VALUE; @@ -152,6 +151,7 @@ inline static void ijkff_reset(FFPlayer *ffp) IJKFF_SAFE_FREE(ffp->audio_codec_name); IJKFF_SAFE_FREE(ffp->subtitle_codec_name); IJKFF_SAFE_FREE(ffp->video_codec_name); + ffp->rdftspeed = 0.02; #if CONFIG_AVFILTER ffp->vfilters = NULL; #endif