From 06c702ec5258bcdd5a5fbf7c879bfc7e2705cbf8 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Fri, 16 Mar 2012 00:57:52 +0200 Subject: terminal output: if audio/video pts is missing, show "???" Change the terminal status line to show "???" instead of a huge negative number if audio or video pts is missing (there was a partial workaround for audio before, but not video or A-V difference). --- mplayer.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/mplayer.c b/mplayer.c index 19d93bf2d8..c228f98d42 100644 --- a/mplayer.c +++ b/mplayer.c @@ -1228,6 +1228,8 @@ static void print_status(struct MPContext *mpctx, double a_pos, bool at_frame) if (mpctx->time_frame > 0) mpctx->last_av_difference += mpctx->time_frame * opts->playback_speed; + if (a_pos == MP_NOPTS_VALUE || mpctx->video_pts == MP_NOPTS_VALUE) + mpctx->last_av_difference = MP_NOPTS_VALUE; if (mpctx->last_av_difference > 0.5 && drop_frame_cnt > 50 && !mpctx->drop_message_shown) { mp_tmsg(MSGT_AVSYNC, MSGL_WARN, SystemTooSlow); @@ -1237,9 +1239,6 @@ static void print_status(struct MPContext *mpctx, double a_pos, bool at_frame) if (opts->quiet) return; - if (a_pos == MP_NOPTS_VALUE) - a_pos = -9; // don't print a huge negative number - int width; char *line; unsigned pos = 0; @@ -1257,8 +1256,11 @@ static void print_status(struct MPContext *mpctx, double a_pos, bool at_frame) // Audio time if (mpctx->sh_audio) { - saddf(line, &pos, width, "A:%6.1f ", a_pos); - if (!sh_video) { + if (a_pos != MP_NOPTS_VALUE) + saddf(line, &pos, width, "A:%6.1f ", a_pos); + else + saddf(line, &pos, width, "A: ??? "); + if (!sh_video && a_pos != MP_NOPTS_VALUE) { float len = get_time_length(mpctx); saddf(line, &pos, width, "("); sadd_hhmmssf(line, &pos, width, a_pos); @@ -1269,13 +1271,22 @@ static void print_status(struct MPContext *mpctx, double a_pos, bool at_frame) } // Video time - if (sh_video) - saddf(line, &pos, width, "V:%6.1f ", mpctx->video_pts); + if (sh_video) { + if (mpctx->video_pts != MP_NOPTS_VALUE) + saddf(line, &pos, width, "V:%6.1f ", mpctx->video_pts); + else + saddf(line, &pos, width, "V: ??? ", mpctx->video_pts); + } // A-V sync - if (mpctx->sh_audio && sh_video) - saddf(line, &pos, width, "A-V:%7.3f ct:%7.3f ", - mpctx->last_av_difference, mpctx->total_avsync_change); + if (mpctx->sh_audio && sh_video) { + if (mpctx->last_av_difference != MP_NOPTS_VALUE) + saddf(line, &pos, width, "A-V:%7.3f ct:%7.3f ", + mpctx->last_av_difference, mpctx->total_avsync_change); + else + saddf(line, &pos, width, "A-V: ??? ct:%7.3f ", + mpctx->total_avsync_change); + } // Video stats if (sh_video) @@ -3358,9 +3369,11 @@ double get_current_time(struct MPContext *mpctx) struct demuxer *demuxer = mpctx->demuxer; if (demuxer->stream_pts != MP_NOPTS_VALUE) return demuxer->stream_pts; - struct sh_video *sh_video = demuxer->video->sh; - if (sh_video) - return mpctx->video_pts; + if (mpctx->sh_video) { + double pts = mpctx->video_pts; + if (pts != MP_NOPTS_VALUE) + return pts; + } double apts = playing_audio_pts(mpctx); if (apts != MP_NOPTS_VALUE) return apts; -- cgit v1.2.3 From 7040968be41cab1a9aa6129afe7c76129c74c2f8 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Thu, 15 Mar 2012 01:24:52 +0200 Subject: core: restructure main play loop, continue audio after video Restructure parts of the code in the main play loop. The main functionality difference is that if a video track ends first, now audio will continue to be played until it ends too. Now the process also wakes up less often if there's no need to update video or audio. This will reduce unnecessary wakeups especially when paused, but may make handling of input events laggier when fd-based notifications are not supported (like most input on Windows). --- libvo/video_out.c | 1 + mplayer.c | 529 +++++++++++++++++++++++++----------------------------- 2 files changed, 247 insertions(+), 283 deletions(-) diff --git a/libvo/video_out.c b/libvo/video_out.c index 9573439882..18ca3e99e9 100644 --- a/libvo/video_out.c +++ b/libvo/video_out.c @@ -376,6 +376,7 @@ void vo_seek_reset(struct vo *vo) { vo_control(vo, VOCTRL_RESET, NULL); vo->frame_loaded = false; + vo->hasframe = false; } void vo_destroy(struct vo *vo) diff --git a/mplayer.c b/mplayer.c index c228f98d42..76c2001c69 100644 --- a/mplayer.c +++ b/mplayer.c @@ -2504,7 +2504,7 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize) return decode_audio(sh_audio, &ao->buffer, playsize); } -static int fill_audio_out_buffers(struct MPContext *mpctx) +static int fill_audio_out_buffers(struct MPContext *mpctx, double endpts) { struct MPOpts *opts = &mpctx->opts; struct ao *ao = mpctx->ao; @@ -2566,8 +2566,7 @@ static int fill_audio_out_buffers(struct MPContext *mpctx) t = GetTimer() - t; tt = t * 0.000001f; audio_time_usage += tt; - if (mpctx->timeline && modifiable_audio_format) { - double endpts = mpctx->timeline[mpctx->timeline_part + 1].start; + if (endpts != MP_NOPTS_VALUE && modifiable_audio_format) { double bytes = (endpts - written_audio_pts(mpctx) + audio_delay) * ao->bps / opts->playback_speed; if (playsize > bytes) { @@ -2609,65 +2608,6 @@ static int fill_audio_out_buffers(struct MPContext *mpctx) return -partial_fill; } -static int sleep_until_near_frame(struct MPContext *mpctx, float *time_frame, - bool sync_to_audio, float *aq_sleep_time) -{ - struct MPOpts *opts = &mpctx->opts; - double audio_limit = 2; - current_module = "calc_sleep_time"; - - if (mpctx->restart_playback) - return 0; - - *time_frame -= get_relative_time(mpctx); // reset timer - - if (sync_to_audio) { - float delay = ao_get_delay(mpctx->ao); - mp_dbg(MSGT_AVSYNC, MSGL_DBG2, "delay=%f\n", delay); - - if (opts->autosync) { - /* - * Adjust this raw delay value by calculating the expected - * delay for this frame and generating a new value which is - * weighted between the two. The higher autosync is, the - * closer to the delay value gets to that which "-nosound" - * would have used, and the longer it will take for A/V - * sync to settle at the right value (but it eventually will.) - * This settling time is very short for values below 100. - */ - float predicted = mpctx->delay / opts->playback_speed + *time_frame; - float difference = delay - predicted; - delay = predicted + difference / (float)opts->autosync; - } - - *time_frame = delay - mpctx->delay / opts->playback_speed; - - // delay = amount of audio buffered in soundcard/driver - delay = FFMIN(delay, 0.5); - delay = FFMAX(delay, 0.1); - audio_limit = delay; - } else { - // If we're lagging more than 200 ms behind the right playback rate, - // don't try to "catch up". - // If benchmark is set always output frames as fast as possible - // without sleeping. - if (*time_frame < -0.2 || opts->benchmark) - *time_frame = 0; - } - - double t = *time_frame - mpctx->video_out->flip_queue_offset; - - if (t <= 0.05) - return 0; - - t -= 0.05; - if (t > audio_limit * 0.6) - t = audio_limit * 0.5; - *aq_sleep_time += t; - mp_input_get_cmd(mpctx->input, t * 1000 + 1, 1); - return 1; -} - int reinit_video_chain(struct MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; @@ -3087,31 +3027,6 @@ void add_step_frame(struct MPContext *mpctx) unpause_player(mpctx); } -static void pause_loop(struct MPContext *mpctx) -{ - mp_cmd_t *cmd; - - update_pause_message(mpctx); - - while ((cmd = mp_input_get_cmd(mpctx->input, 20, 1)) == NULL - || cmd->id == MP_CMD_SET_MOUSE_POS || cmd->pausing == 4) { - if (cmd) { - cmd = mp_input_get_cmd(mpctx->input, 0, 0); - run_command(mpctx, cmd); - mp_cmd_free(cmd); - continue; - } - if (mpctx->sh_video && mpctx->video_out) - vo_check_events(mpctx->video_out); - update_osd_msg(mpctx); - int hack = vo_osd_changed(0); - vo_osd_changed(hack); - if (hack || mpctx->sh_video && mpctx->video_out->want_redraw) - break; - update_pause_message(mpctx); - } -} - static void reinit_decoders(struct MPContext *mpctx) { reinit_video_chain(mpctx); @@ -3131,7 +3046,6 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao) mpctx->sh_video->last_pts = MP_NOPTS_VALUE; mpctx->delay = 0; mpctx->time_frame = 0; - mpctx->restart_playback = true; // Not all demuxers set d_video->pts during seek, so this value // (which is used by at least vobsub code below) may be completely // wrong (probably 0). @@ -3159,6 +3073,7 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao) vobsub_seek(vo_vobsub, mpctx->sh_video->pts); } + mpctx->restart_playback = true; mpctx->hrseek_active = false; mpctx->hrseek_framedrop = false; mpctx->total_avsync_change = 0; @@ -3489,8 +3404,20 @@ int seek_chapter(struct MPContext *mpctx, int chapter, double *seek_pts) static void run_playloop(struct MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; - float aq_sleep_time = 0; bool full_audio_buffers = false; + bool audio_left = false, video_left = false; + double endpts = end_at.type == END_AT_TIME ? end_at.pos : MP_NOPTS_VALUE; + bool end_is_chapter = false; + double sleeptime = 0.5; + bool was_restart = mpctx->restart_playback; + + if (mpctx->timeline) { + double end = mpctx->timeline[mpctx->timeline_part + 1].start; + if (endpts == MP_NOPTS_VALUE || end < endpts) { + endpts = end; + end_is_chapter = true; + } + } if (opts->chapterrange[1] > 0) { int cur_chapter = get_current_chapter(mpctx); @@ -3504,79 +3431,27 @@ static void run_playloop(struct MPContext *mpctx) reinit_audio_chain(mpctx); } - /*========================== PLAY AUDIO ============================*/ - - if (!mpctx->sh_video) - mpctx->restart_playback = false; + if (mpctx->step_frames && !mpctx->sh_video) { + mpctx->step_frames = 0; + pause_player(mpctx); + } if (mpctx->sh_audio && !mpctx->restart_playback) { - int status = fill_audio_out_buffers(mpctx); + int status = fill_audio_out_buffers(mpctx, endpts); full_audio_buffers = status >= 0 && !mpctx->ao->untimed; - if (status == -2) - // at eof, all audio at least written to ao - if (!mpctx->sh_video) - mpctx->stop_play = AT_END_OF_FILE; + // Not at audio stream EOF yet + audio_left = status > -2; } - - if (!mpctx->sh_video) { - if (mpctx->step_frames) { - mpctx->step_frames = 0; - pause_player(mpctx); - } - // handle audio-only case: - double a_pos = 0, a_buf = 0; - // sh_audio can be NULL due to video stream switching - // TODO: handle this better - if (mpctx->sh_audio) { - a_buf = ao_get_delay(mpctx->ao); - a_pos = written_audio_pts(mpctx) - mpctx->opts.playback_speed * - a_buf; - } - - print_status(mpctx, a_pos, false); - - update_subtitles(mpctx, a_pos, mpctx->video_offset, false); - update_osd_msg(mpctx); - if (end_at.type == END_AT_TIME && end_at.pos < a_pos) - mpctx->stop_play = AT_END_OF_FILE; - else if (mpctx->timeline && mpctx->stop_play == AT_END_OF_FILE - && mpctx->timeline_part + 1 < mpctx->num_timeline_parts - && mpctx->sh_audio) { - struct timeline_part *p = mpctx->timeline + mpctx->timeline_part; - if (!opts->gapless_audio && p->source != (p + 1)->source - && a_buf > 0.05) { - mpctx->stop_play = KEEP_PLAYING; - mp_input_get_cmd(mpctx->input, (a_buf - .05) * 1000, true); - } else { - seek(mpctx, (struct seek_params){ .type = MPSEEK_ABSOLUTE, - .amount = (p + 1)->start }, - true); - } - } else if (!mpctx->stop_play) { - int sleep_time = 100; - if (mpctx->sh_audio) { - if (mpctx->ao->untimed) - sleep_time = 0; - else if (full_audio_buffers) - sleep_time = FFMAX(20, a_buf * 1000 - 50); - else - sleep_time = 20; - sleep_time = FFMIN(sleep_time, 100); - } - mp_input_get_cmd(mpctx->input, sleep_time, true); - } - } else { - - /*========================== PLAY VIDEO ============================*/ - + double buffered_audio = -1; + while (mpctx->sh_video) { // never loops, for "break;" only vo_pts = mpctx->sh_video->timer * 90000.0; vo_fps = mpctx->sh_video->fps; - bool blit_frame = mpctx->video_out->frame_loaded; - if (!blit_frame) { + video_left = mpctx->video_out->hasframe; + if (!mpctx->video_out->frame_loaded + && (!mpctx->paused || mpctx->restart_playback)) { double frame_time = update_video(mpctx); - blit_frame = mpctx->video_out->frame_loaded; mp_dbg(MSGT_AVSYNC, MSGL_DBG2, "*** ftime=%5.3f ***\n", frame_time); if (mpctx->sh_video->vf_initialized < 0) { mp_tmsg(MSGT_CPLAYER, MSGL_FATAL, @@ -3585,25 +3460,14 @@ static void run_playloop(struct MPContext *mpctx) mpctx->stop_play = PT_NEXT_ENTRY; return; } - if (frame_time < 0) - mpctx->stop_play = AT_END_OF_FILE; - else if (!mpctx->restart_playback) { + video_left = frame_time >= 0; + if (endpts != MP_NOPTS_VALUE) + video_left &= mpctx->sh_video->pts < endpts; + if (video_left && !mpctx->restart_playback) { mpctx->time_frame += frame_time / opts->playback_speed; adjust_sync(mpctx, frame_time); } } - if (mpctx->timeline) { - struct timeline_part *next = - mpctx->timeline + mpctx->timeline_part + 1; - if (mpctx->sh_video->pts >= next->start - || mpctx->stop_play == AT_END_OF_FILE - && mpctx->timeline_part + 1 < mpctx->num_timeline_parts) { - seek(mpctx, (struct seek_params){ .type = MPSEEK_ABSOLUTE, - .amount = next->start }, - true); - return; - } - } // ================================================================ @@ -3625,78 +3489,116 @@ static void run_playloop(struct MPContext *mpctx) } } - bool frame_time_remaining = sleep_until_near_frame(mpctx, - &mpctx->time_frame, - full_audio_buffers, - &aq_sleep_time); + if (!video_left || (mpctx->paused && !mpctx->restart_playback)) + break; + if (!mpctx->video_out->frame_loaded) { + sleeptime = 0; + break; + } + + mpctx->time_frame -= get_relative_time(mpctx); + if (full_audio_buffers && !mpctx->restart_playback) { + buffered_audio = ao_get_delay(mpctx->ao); + mp_dbg(MSGT_AVSYNC, MSGL_DBG2, "delay=%f\n", buffered_audio); + + if (opts->autosync) { + /* Smooth reported playback position from AO by averaging + * it with the value expected based on previus value and + * time elapsed since then. May help smooth video timing + * with audio output that have inaccurate position reporting. + * This is badly implemented; the behavior of the smoothing + * now undesirably depends on how often this code runs + * (mainly depends on video frame rate). */ + float predicted = (mpctx->delay / opts->playback_speed + + mpctx->time_frame); + float difference = buffered_audio - predicted; + buffered_audio = predicted + difference / opts->autosync; + } + + mpctx->time_frame = (buffered_audio - + mpctx->delay / opts->playback_speed); + } else { + /* If we're more than 200 ms behind the right playback + * position, don't try to speed up display of following + * frames to catch up; continue with default speed from + * the current frame instead. + * If benchmark is set always output frames immediately + * without sleeping. + */ + if (mpctx->time_frame < -0.2 || opts->benchmark) + mpctx->time_frame = 0; + } + + double vsleep = mpctx->time_frame - mpctx->video_out->flip_queue_offset; + if (vsleep > 0.050) { + sleeptime = FFMIN(sleeptime, vsleep - 0.040); + break; + } + sleeptime = 0; //=================== FLIP PAGE (VIDEO BLT): ====================== current_module = "flip_page"; - if (!frame_time_remaining && blit_frame) { - vo_new_frame_imminent(mpctx->video_out); - struct sh_video *sh_video = mpctx->sh_video; - mpctx->video_pts = sh_video->pts; - update_subtitles(mpctx, sh_video->pts, mpctx->video_offset, false); - update_teletext(sh_video, mpctx->demuxer, 0); - update_osd_msg(mpctx); - struct vf_instance *vf = sh_video->vfilter; - mpctx->osd->pts = mpctx->video_pts; - vf->control(vf, VFCTRL_DRAW_EOSD, mpctx->osd); - vf->control(vf, VFCTRL_DRAW_OSD, mpctx->osd); - vo_osd_changed(0); - - mpctx->time_frame -= mpctx->video_out->flip_queue_offset; - aq_sleep_time += mpctx->time_frame; - // flag 256 means: libvo driver does its timing (dvb card) - if (mpctx->time_frame > 0.001 - && !(mpctx->sh_video->output_flags & VFCAP_TIMER)) - mpctx->time_frame = timing_sleep(mpctx, mpctx->time_frame); - mpctx->time_frame += mpctx->video_out->flip_queue_offset; - - unsigned int t2 = GetTimer(); - /* Playing with playback speed it's possible to get pathological - * cases with mpctx->time_frame negative enough to cause an - * overflow in pts_us calculation, thus the FFMAX. */ - double time_frame = FFMAX(mpctx->time_frame, -1); - unsigned int pts_us = mpctx->last_time + time_frame * 1e6; - int duration = -1; - double pts2 = mpctx->video_out->next_pts2; - if (pts2 != MP_NOPTS_VALUE && opts->correct_pts - && !mpctx->restart_playback) { - // expected A/V sync correction is ignored - double diff = (pts2 - mpctx->video_pts); - diff /= opts->playback_speed; - if (mpctx->time_frame < 0) - diff += mpctx->time_frame; - if (diff < 0) - diff = 0; - if (diff > 10) - diff = 10; - duration = diff * 1e6; - } - vo_flip_page(mpctx->video_out, pts_us | 1, duration); - - mpctx->last_vo_flip_duration = (GetTimer() - t2) * 0.000001; - vout_time_usage += mpctx->last_vo_flip_duration; - if (mpctx->video_out->driver->flip_page_timed) { - // No need to adjust sync based on flip speed - mpctx->last_vo_flip_duration = 0; - // For print_status - VO call finishing early is OK for sync - mpctx->time_frame -= get_relative_time(mpctx); - } - if (mpctx->restart_playback) { - mpctx->syncing_audio = true; - if (mpctx->sh_audio) - fill_audio_out_buffers(mpctx); - mpctx->restart_playback = false; - mpctx->time_frame = 0; - get_relative_time(mpctx); - } - print_status(mpctx, MP_NOPTS_VALUE, true); - screenshot_flip(mpctx); - } else - print_status(mpctx, MP_NOPTS_VALUE, false); + vo_new_frame_imminent(mpctx->video_out); + struct sh_video *sh_video = mpctx->sh_video; + mpctx->video_pts = sh_video->pts; + update_subtitles(mpctx, sh_video->pts, mpctx->video_offset, false); + update_teletext(sh_video, mpctx->demuxer, 0); + update_osd_msg(mpctx); + struct vf_instance *vf = sh_video->vfilter; + mpctx->osd->pts = mpctx->video_pts; + vf->control(vf, VFCTRL_DRAW_EOSD, mpctx->osd); + vf->control(vf, VFCTRL_DRAW_OSD, mpctx->osd); + vo_osd_changed(0); + + mpctx->time_frame -= mpctx->video_out->flip_queue_offset; + float aq_sleep_time = mpctx->time_frame; + if (mpctx->time_frame > 0.001 + && !(mpctx->sh_video->output_flags & VFCAP_TIMER)) + mpctx->time_frame = timing_sleep(mpctx, mpctx->time_frame); + mpctx->time_frame += mpctx->video_out->flip_queue_offset; + + unsigned int t2 = GetTimer(); + /* Playing with playback speed it's possible to get pathological + * cases with mpctx->time_frame negative enough to cause an + * overflow in pts_us calculation, thus the FFMAX. */ + double time_frame = FFMAX(mpctx->time_frame, -1); + unsigned int pts_us = mpctx->last_time + time_frame * 1e6; + int duration = -1; + double pts2 = mpctx->video_out->next_pts2; + if (pts2 != MP_NOPTS_VALUE && opts->correct_pts && + !mpctx->restart_playback) { + // expected A/V sync correction is ignored + double diff = (pts2 - mpctx->video_pts); + diff /= opts->playback_speed; + if (mpctx->time_frame < 0) + diff += mpctx->time_frame; + if (diff < 0) + diff = 0; + if (diff > 10) + diff = 10; + duration = diff * 1e6; + } + vo_flip_page(mpctx->video_out, pts_us | 1, duration); + + mpctx->last_vo_flip_duration = (GetTimer() - t2) * 0.000001; + vout_time_usage += mpctx->last_vo_flip_duration; + if (mpctx->video_out->driver->flip_page_timed) { + // No need to adjust sync based on flip speed + mpctx->last_vo_flip_duration = 0; + // For print_status - VO call finishing early is OK for sync + mpctx->time_frame -= get_relative_time(mpctx); + } + if (mpctx->restart_playback) { + mpctx->syncing_audio = true; + if (mpctx->sh_audio) + fill_audio_out_buffers(mpctx, endpts); + mpctx->restart_playback = false; + mpctx->time_frame = 0; + get_relative_time(mpctx); + } + print_status(mpctx, MP_NOPTS_VALUE, true); + screenshot_flip(mpctx); if (opts->auto_quality > 0) { current_module = "autoq"; @@ -3709,25 +3611,18 @@ static void run_playloop(struct MPContext *mpctx) set_video_quality(mpctx->sh_video, output_quality); } - if (!frame_time_remaining && blit_frame) { - if (play_n_frames >= 0) { - --play_n_frames; - if (play_n_frames <= 0) - mpctx->stop_play = PT_NEXT_ENTRY; - } - if (mpctx->step_frames > 0) { - mpctx->step_frames--; - if (mpctx->step_frames == 0) - pause_player(mpctx); - } + if (play_n_frames >= 0) { + --play_n_frames; + if (play_n_frames <= 0) + mpctx->stop_play = PT_NEXT_ENTRY; } - - // FIXME: add size based support for -endpos - if (end_at.type == END_AT_TIME && - !frame_time_remaining && end_at.pos <= mpctx->sh_video->pts) - mpctx->stop_play = PT_NEXT_ENTRY; - - } // end if(mpctx->sh_video) + if (mpctx->step_frames > 0) { + mpctx->step_frames--; + if (mpctx->step_frames == 0) + pause_player(mpctx); + } + break; + } // video #ifdef CONFIG_DVDNAV if (mpctx->stream->type == STREAMTYPE_DVDNAV) { @@ -3753,48 +3648,116 @@ static void run_playloop(struct MPContext *mpctx) } #endif - //================= Keyboard events, SEEKing ==================== + if (mpctx->restart_playback && !video_left) { + if (mpctx->sh_audio) { + int status = fill_audio_out_buffers(mpctx, endpts); + full_audio_buffers = status >= 0 && !mpctx->ao->untimed; + // Not at audio stream EOF yet + audio_left = status > -2; + } + mpctx->restart_playback = false; + } + if (mpctx->sh_audio && buffered_audio == -1) + buffered_audio = mpctx->paused ? 0 : ao_get_delay(mpctx->ao); - current_module = "key_events"; + update_osd_msg(mpctx); + if (mpctx->paused) + update_pause_message(mpctx); + if (!video_left && (!mpctx->paused || was_restart)) { + double a_pos = 0; + if (mpctx->sh_audio) { + a_pos = (written_audio_pts(mpctx) - + mpctx->opts.playback_speed * buffered_audio); + } + print_status(mpctx, a_pos, false); - while (1) { - mp_cmd_t *cmd; - while ((cmd = mp_input_get_cmd(mpctx->input, 0, 1)) != NULL) { - /* Allow running consecutive seek commands to combine them, - * but execute the seek before running other commands. - * If the user seeks continuously (keeps arrow key down) - * try to finish showing a frame from one location before doing - * another seek (which could lead to unchanging display). */ - if (mpctx->seek.type && cmd->id != MP_CMD_SEEK - || mpctx->restart_playback && cmd->id == MP_CMD_SEEK - && GetTimerMS() - mpctx->start_timestamp < 300) - break; - cmd = mp_input_get_cmd(mpctx->input, 0, 0); - run_command(mpctx, cmd); - mp_cmd_free(cmd); - if (mpctx->stop_play) - break; + if (!mpctx->sh_video) + update_subtitles(mpctx, a_pos, mpctx->video_offset, false); + } + + /* It's possible for the user to simultaneously switch both audio + * and video streams to "disabled" at runtime. Handle this by waiting + * rather than immediately stopping playback due to EOF. + * + * When all audio has been written to output driver, stay in the + * main loop handling commands until it has been mostly consumed, + * except in the gapless case, where the next file will be started + * while audio from the current one still remains to be played. + * + * We want this check to trigger if we seeked to this position, + * but not if we paused at it with audio possibly still buffered in + * the AO. There's currently no working way to check buffered audio + * inside AO while paused. Thus the "was_restart" check below, which + * should trigger after seek only, when we know there's no audio + * buffered. + */ + if ((mpctx->sh_audio || mpctx->sh_video) && !audio_left && !video_left + && (opts->gapless_audio || buffered_audio < 0.05) + && (!mpctx->paused || was_restart)) { + if (end_is_chapter) { + seek(mpctx, (struct seek_params){ + .type = MPSEEK_ABSOLUTE, + .amount = mpctx->timeline[mpctx->timeline_part+1].start + }, true); + } else + mpctx->stop_play = AT_END_OF_FILE; + } else if (!mpctx->stop_play) { + double audio_sleep = 9; + if (mpctx->sh_audio && !mpctx->paused) { + if (mpctx->ao->untimed) { + if (!mpctx->sh_video) + audio_sleep = 0; + } else if (full_audio_buffers) { + audio_sleep = buffered_audio - 0.050; + // Keep extra safety margin if the buffers are large + if (audio_sleep > 0.100) + audio_sleep = FFMAX(audio_sleep - 0.200, 0.100); + else + audio_sleep = FFMAX(audio_sleep, 0.020); + } else + audio_sleep = 0.020; } - bool slow_video = mpctx->sh_video && mpctx->video_out->frame_loaded; - if (!(mpctx->paused || slow_video) || mpctx->stop_play - || mpctx->seek.type || mpctx->restart_playback) - break; - if (mpctx->sh_video) { - update_osd_msg(mpctx); + sleeptime = FFMIN(sleeptime, audio_sleep); + if (sleeptime > 0) { + if (!mpctx->sh_video) + goto novideo; int hack = vo_osd_changed(0); vo_osd_changed(hack); if (hack || mpctx->video_out->want_redraw) { if (redraw_osd(mpctx) < 0) { - if (mpctx->paused) + if (mpctx->paused && video_left) add_step_frame(mpctx); - break; + else + goto novideo; } else vo_osd_changed(0); + } else { + novideo: + mp_input_get_cmd(mpctx->input, sleeptime * 1000, true); } } - if (!mpctx->paused) + } + + //================= Keyboard events, SEEKing ==================== + + current_module = "key_events"; + + mp_cmd_t *cmd; + while ((cmd = mp_input_get_cmd(mpctx->input, 0, 1)) != NULL) { + /* Allow running consecutive seek commands to combine them, + * but execute the seek before running other commands. + * If the user seeks continuously (keeps arrow key down) + * try to finish showing a frame from one location before doing + * another seek (which could lead to unchanging display). */ + if (mpctx->seek.type && cmd->id != MP_CMD_SEEK + || mpctx->restart_playback && cmd->id == MP_CMD_SEEK + && GetTimerMS() - mpctx->start_timestamp < 300) + break; + cmd = mp_input_get_cmd(mpctx->input, 0, 0); + run_command(mpctx, cmd); + mp_cmd_free(cmd); + if (mpctx->stop_play) break; - pause_loop(mpctx); } // handle -sstep -- cgit v1.2.3 From 7a699cea2849b2ef3f0a7a0702b74c33327ef8a9 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 26 Dec 2011 01:41:35 +0100 Subject: mixer: reindent/cosmetic changes There should be no real semantic changes. Remove the mixer_setbothvolume macro, as it was unused. --- mixer.c | 204 ++++++++++++++++++++++++++++++++-------------------------------- mixer.h | 5 +- 2 files changed, 103 insertions(+), 106 deletions(-) diff --git a/mixer.c b/mixer.c index d4e794d5f5..0a893cc90b 100644 --- a/mixer.c +++ b/mixer.c @@ -17,163 +17,163 @@ */ #include -#ifndef __MINGW32__ -#include -#endif -#include -#include -#include #include "config.h" #include "libao2/audio_out.h" #include "libaf/af.h" +#include "mp_msg.h" #include "mixer.h" -char * mixer_device=NULL; -char * mixer_channel=NULL; +char *mixer_device = NULL; +char *mixer_channel = NULL; int soft_vol = 0; float soft_vol_max = 110.0; void mixer_getvolume(mixer_t *mixer, float *l, float *r) { - ao_control_vol_t vol; - *l=0; *r=0; - if (mixer->ao) { - if(soft_vol || - CONTROL_OK != ao_control(mixer->ao, AOCONTROL_GET_VOLUME, &vol)) { - if (!mixer->afilter) + *l = 0; + *r = 0; + if (!mixer->ao) return; - else { + + ao_control_vol_t vol; + if (soft_vol || CONTROL_OK != ao_control(mixer->ao, AOCONTROL_GET_VOLUME, + &vol)) { float db_vals[AF_NCH]; if (!af_control_any_rev(mixer->afilter, - AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_GET, db_vals)) - db_vals[0] = db_vals[1] = 1.0; + AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_GET, db_vals)) + db_vals[0] = db_vals[1] = 1.0; else - af_from_dB (2, db_vals, db_vals, 20.0, -200.0, 60.0); + af_from_dB(2, db_vals, db_vals, 20.0, -200.0, 60.0); vol.left = (db_vals[0] / (soft_vol_max / 100.0)) * 100.0; vol.right = (db_vals[1] / (soft_vol_max / 100.0)) * 100.0; - } } - *r=vol.right; - *l=vol.left; - } + *r = vol.right; + *l = vol.left; } void mixer_setvolume(mixer_t *mixer, float l, float r) { - ao_control_vol_t vol; - vol.right=r; vol.left=l; - if (mixer->ao) { - if(soft_vol || - CONTROL_OK != ao_control(mixer->ao, AOCONTROL_SET_VOLUME, &vol)) { - if (!mixer->afilter) + if (!mixer->ao) { + mixer->muted = 0; return; - else { + } + ao_control_vol_t vol; + vol.right = r; + vol.left = l; + if (soft_vol || CONTROL_OK != ao_control(mixer->ao, AOCONTROL_SET_VOLUME, + &vol)) { // af_volume uses values in dB float db_vals[AF_NCH]; int i; db_vals[0] = (l / 100.0) * (soft_vol_max / 100.0); db_vals[1] = (r / 100.0) * (soft_vol_max / 100.0); - for (i = 2; i < AF_NCH; i++) { - db_vals[i] = ((l + r) / 100.0) * (soft_vol_max / 100.0) / 2.0; - } - af_to_dB (AF_NCH, db_vals, db_vals, 20.0); + for (i = 2; i < AF_NCH; i++) + db_vals[i] = ((l + r) / 100.0) * (soft_vol_max / 100.0) / 2.0; + af_to_dB(AF_NCH, db_vals, db_vals, 20.0); if (!af_control_any_rev(mixer->afilter, - AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, db_vals)) { - mp_tmsg(MSGT_GLOBAL, MSGL_INFO, "[Mixer] No hardware mixing, inserting volume filter.\n"); - if (af_add(mixer->afilter, "volume")) { - if (!af_control_any_rev(mixer->afilter, - AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, db_vals)) { - mp_tmsg(MSGT_GLOBAL, MSGL_ERR, "[Mixer] No volume control available.\n"); - return; + AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, db_vals)) { + mp_tmsg(MSGT_GLOBAL, MSGL_INFO, + "[Mixer] No hardware mixing, inserting volume filter.\n"); + if (af_add(mixer->afilter, "volume")) { + if (!af_control_any_rev(mixer->afilter, + AF_CONTROL_VOLUME_LEVEL|AF_CONTROL_SET, db_vals)) { + mp_tmsg(MSGT_GLOBAL, MSGL_ERR, + "[Mixer] No volume control available.\n"); + return; + } } - } - } - } + } } - } - mixer->muted=0; + mixer->muted = 0; } void mixer_incvolume(mixer_t *mixer) { - float mixer_l, mixer_r; - mixer_getvolume(mixer, &mixer_l, &mixer_r); - mixer_l += mixer->volstep; - if ( mixer_l > 100 ) mixer_l = 100; - mixer_r += mixer->volstep; - if ( mixer_r > 100 ) mixer_r = 100; - mixer_setvolume(mixer, mixer_l, mixer_r); + float mixer_l, mixer_r; + mixer_getvolume(mixer, &mixer_l, &mixer_r); + mixer_l += mixer->volstep; + if (mixer_l > 100) + mixer_l = 100; + mixer_r += mixer->volstep; + if (mixer_r > 100) + mixer_r = 100; + mixer_setvolume(mixer, mixer_l, mixer_r); } void mixer_decvolume(mixer_t *mixer) { - float mixer_l, mixer_r; - mixer_getvolume(mixer, &mixer_l, &mixer_r); - mixer_l -= mixer->volstep; - if ( mixer_l < 0 ) mixer_l = 0; - mixer_r -= mixer->volstep; - if ( mixer_r < 0 ) mixer_r = 0; - mixer_setvolume(mixer, mixer_l, mixer_r); + float mixer_l, mixer_r; + mixer_getvolume(mixer, &mixer_l, &mixer_r); + mixer_l -= mixer->volstep; + if (mixer_l < 0) + mixer_l = 0; + mixer_r -= mixer->volstep; + if (mixer_r < 0) + mixer_r = 0; + mixer_setvolume(mixer, mixer_l, mixer_r); } void mixer_getbothvolume(mixer_t *mixer, float *b) { - float mixer_l, mixer_r; - mixer_getvolume(mixer, &mixer_l, &mixer_r); - *b = ( mixer_l + mixer_r ) / 2; + float mixer_l, mixer_r; + mixer_getvolume(mixer, &mixer_l, &mixer_r); + *b = (mixer_l + mixer_r) / 2; } void mixer_mute(mixer_t *mixer) { - if (mixer->muted) mixer_setvolume(mixer, mixer->last_l, mixer->last_r); - else - { - mixer_getvolume(mixer, &mixer->last_l, &mixer->last_r); - mixer_setvolume(mixer, 0, 0); - mixer->muted=1; - } + if (mixer->muted) { + mixer_setvolume(mixer, mixer->last_l, mixer->last_r); + } else { + mixer_getvolume(mixer, &mixer->last_l, &mixer->last_r); + mixer_setvolume(mixer, 0, 0); + mixer->muted = 1; + } } void mixer_getbalance(mixer_t *mixer, float *val) { - *val = 0.f; - if(!mixer->afilter) - return; - af_control_any_rev(mixer->afilter, - AF_CONTROL_PAN_BALANCE | AF_CONTROL_GET, val); + *val = 0.f; + if (!mixer->afilter) + return; + af_control_any_rev(mixer->afilter, AF_CONTROL_PAN_BALANCE | AF_CONTROL_GET, + val); } void mixer_setbalance(mixer_t *mixer, float val) { - float level[AF_NCH]; - int i; - af_control_ext_t arg_ext = { .arg = level }; - af_instance_t* af_pan_balance; - - if(!mixer->afilter) - return; - if (af_control_any_rev(mixer->afilter, - AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &val)) - return; - - if (!(af_pan_balance = af_add(mixer->afilter, "pan"))) { - mp_tmsg(MSGT_GLOBAL, MSGL_ERR, "[Mixer] No balance control available.\n"); - return; - } - - af_init(mixer->afilter); - /* make all other channels pass thru since by default pan blocks all */ - memset(level, 0, sizeof(level)); - for (i = 2; i < AF_NCH; i++) { - arg_ext.ch = i; - level[i] = 1.f; - af_pan_balance->control(af_pan_balance, - AF_CONTROL_PAN_LEVEL | AF_CONTROL_SET, &arg_ext); - level[i] = 0.f; - } + float level[AF_NCH]; + int i; + af_control_ext_t arg_ext = { .arg = level }; + af_instance_t *af_pan_balance; + + if (!mixer->afilter) + return; - af_pan_balance->control(af_pan_balance, - AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &val); + if (af_control_any_rev(mixer->afilter, + AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &val)) + return; + + if (!(af_pan_balance = af_add(mixer->afilter, "pan"))) { + mp_tmsg(MSGT_GLOBAL, MSGL_ERR, + "[Mixer] No balance control available.\n"); + return; + } + + af_init(mixer->afilter); + /* make all other channels pass thru since by default pan blocks all */ + memset(level, 0, sizeof(level)); + for (i = 2; i < AF_NCH; i++) { + arg_ext.ch = i; + level[i] = 1.f; + af_pan_balance->control(af_pan_balance, + AF_CONTROL_PAN_LEVEL | AF_CONTROL_SET, + &arg_ext); + level[i] = 0.f; + } + + af_pan_balance->control(af_pan_balance, + AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &val); } diff --git a/mixer.h b/mixer.h index a524c02b26..d7a88f74df 100644 --- a/mixer.h +++ b/mixer.h @@ -27,7 +27,7 @@ extern char * mixer_channel; extern int soft_vol; extern float soft_vol_max; -typedef struct mixer_s { +typedef struct mixer { struct ao *ao; af_stream_t *afilter; int volstep; @@ -44,7 +44,4 @@ void mixer_mute(mixer_t *mixer); void mixer_getbalance(mixer_t *mixer, float *bal); void mixer_setbalance(mixer_t *mixer, float bal); -//void mixer_setbothvolume(int v); -#define mixer_setbothvolume(m, v) mixer_setvolume(m, v, v) - #endif /* MPLAYER_MIXER_H */ -- cgit v1.2.3 From ec58e5a3848f82681839eaa15d2c6912d92e74ed Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Sat, 21 Jan 2012 09:28:07 +0200 Subject: options: move mixer.h options to struct --- cfg-mplayer.h | 9 ++++----- defaultopts.c | 1 + libao2/audio_out.h | 1 + libao2/audio_out_internal.h | 4 ++++ mixer.c | 23 +++++++++-------------- mixer.h | 9 ++++----- mplayer.c | 3 +++ options.h | 4 ++++ 8 files changed, 30 insertions(+), 24 deletions(-) diff --git a/cfg-mplayer.h b/cfg-mplayer.h index 2f1ba666bb..6a167ece54 100644 --- a/cfg-mplayer.h +++ b/cfg-mplayer.h @@ -728,11 +728,10 @@ const m_option_t mplayer_opts[]={ {"border", &vo_border, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"noborder", &vo_border, CONF_TYPE_FLAG, 0, 1, 0, NULL}, - {"mixer", &mixer_device, CONF_TYPE_STRING, 0, 0, 0, NULL}, - {"mixer-channel", &mixer_channel, CONF_TYPE_STRING, 0, 0, 0, NULL}, - {"softvol", &soft_vol, CONF_TYPE_FLAG, 0, 0, 1, NULL}, - {"nosoftvol", &soft_vol, CONF_TYPE_FLAG, 0, 1, 0, NULL}, - {"softvol-max", &soft_vol_max, CONF_TYPE_FLOAT, CONF_RANGE, 10, 10000, NULL}, + OPT_STRING("mixer", mixer_device, 0), + OPT_STRING("mixer-channel", mixer_channel, 0), + OPT_MAKE_FLAGS("softvol", softvol, 0), + OPT_FLOATRANGE("softvol-max", softvol_max, 0, 10, 10000), {"volstep", &volstep, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL}, {"volume", &start_volume, CONF_TYPE_FLOAT, CONF_RANGE, -1, 10000, NULL}, OPT_MAKE_FLAGS("gapless-audio", gapless_audio, 0), diff --git a/defaultopts.c b/defaultopts.c index 52e63cc489..b6f58b715d 100644 --- a/defaultopts.c +++ b/defaultopts.c @@ -10,6 +10,7 @@ void set_default_mplayer_options(struct MPOpts *opts) .audio_driver_list = NULL, .video_driver_list = NULL, .fixed_vo = 1, + .softvol_max = 110, .ao_buffersize = -1, .monitor_pixel_aspect = 1.0, .vo_panscanrange = 1.0, diff --git a/libao2/audio_out.h b/libao2/audio_out.h index e96e123700..cbd913656b 100644 --- a/libao2/audio_out.h +++ b/libao2/audio_out.h @@ -80,6 +80,7 @@ struct ao { bool untimed; const struct ao_driver *driver; void *priv; + struct MPOpts *opts; }; extern char *ao_subdevice; diff --git a/libao2/audio_out_internal.h b/libao2/audio_out_internal.h index 67bcfa953d..215428fb0e 100644 --- a/libao2/audio_out_internal.h +++ b/libao2/audio_out_internal.h @@ -19,6 +19,8 @@ #ifndef MPLAYER_AUDIO_OUT_INTERNAL_H #define MPLAYER_AUDIO_OUT_INTERNAL_H +#include "options.h" + // prototypes: //static ao_info_t info; static int control(int cmd, void *arg); @@ -33,6 +35,8 @@ static void audio_resume(void); extern struct ao *global_ao; #define ao_data (*global_ao) +#define mixer_channel (global_ao->opts->mixer_channel) +#define mixer_device (global_ao->opts->mixer_device) #define LIBAO_EXTERN(x) const struct ao_driver audio_out_##x = { \ .info = &info, \ diff --git a/mixer.c b/mixer.c index 0a893cc90b..f28fea7b09 100644 --- a/mixer.c +++ b/mixer.c @@ -25,11 +25,6 @@ #include "mixer.h" -char *mixer_device = NULL; -char *mixer_channel = NULL; -int soft_vol = 0; -float soft_vol_max = 110.0; - void mixer_getvolume(mixer_t *mixer, float *l, float *r) { *l = 0; @@ -38,16 +33,16 @@ void mixer_getvolume(mixer_t *mixer, float *l, float *r) return; ao_control_vol_t vol; - if (soft_vol || CONTROL_OK != ao_control(mixer->ao, AOCONTROL_GET_VOLUME, - &vol)) { + if (mixer->softvol || CONTROL_OK != ao_control(mixer->ao, + AOCONTROL_GET_VOLUME, &vol)) { float db_vals[AF_NCH]; if (!af_control_any_rev(mixer->afilter, AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_GET, db_vals)) db_vals[0] = db_vals[1] = 1.0; else af_from_dB(2, db_vals, db_vals, 20.0, -200.0, 60.0); - vol.left = (db_vals[0] / (soft_vol_max / 100.0)) * 100.0; - vol.right = (db_vals[1] / (soft_vol_max / 100.0)) * 100.0; + vol.left = (db_vals[0] / (mixer->softvol_max / 100.0)) * 100.0; + vol.right = (db_vals[1] / (mixer->softvol_max / 100.0)) * 100.0; } *r = vol.right; *l = vol.left; @@ -62,15 +57,15 @@ void mixer_setvolume(mixer_t *mixer, float l, float r) ao_control_vol_t vol; vol.right = r; vol.left = l; - if (soft_vol || CONTROL_OK != ao_control(mixer->ao, AOCONTROL_SET_VOLUME, - &vol)) { + if (mixer->softvol || CONTROL_OK != ao_control(mixer->ao, + AOCONTROL_SET_VOLUME, &vol)) { // af_volume uses values in dB float db_vals[AF_NCH]; int i; - db_vals[0] = (l / 100.0) * (soft_vol_max / 100.0); - db_vals[1] = (r / 100.0) * (soft_vol_max / 100.0); + db_vals[0] = (l / 100.0) * (mixer->softvol_max / 100.0); + db_vals[1] = (r / 100.0) * (mixer->softvol_max / 100.0); for (i = 2; i < AF_NCH; i++) - db_vals[i] = ((l + r) / 100.0) * (soft_vol_max / 100.0) / 2.0; + db_vals[i] = ((l + r) / 100.0) * (mixer->softvol_max / 100.0) / 2.0; af_to_dB(AF_NCH, db_vals, db_vals, 20.0); if (!af_control_any_rev(mixer->afilter, AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, db_vals)) { diff --git a/mixer.h b/mixer.h index d7a88f74df..eaf81c1ba1 100644 --- a/mixer.h +++ b/mixer.h @@ -19,18 +19,17 @@ #ifndef MPLAYER_MIXER_H #define MPLAYER_MIXER_H +#include + #include "libaf/af.h" #include "libao2/audio_out.h" -extern char * mixer_device; -extern char * mixer_channel; -extern int soft_vol; -extern float soft_vol_max; - typedef struct mixer { struct ao *ao; af_stream_t *afilter; int volstep; + bool softvol; + float softvol_max; int muted; float last_l, last_r; } mixer_t; diff --git a/mplayer.c b/mplayer.c index 76c2001c69..7ca2d0303f 100644 --- a/mplayer.c +++ b/mplayer.c @@ -1776,6 +1776,7 @@ void reinit_audio_chain(struct MPContext *mpctx) if (!(mpctx->initialized_flags & INITIALIZED_AO)) { mpctx->initialized_flags |= INITIALIZED_AO; mpctx->ao = ao_create(); + mpctx->ao->opts = opts; mpctx->ao->samplerate = force_srate; mpctx->ao->format = opts->audio_output_format; } @@ -1823,6 +1824,8 @@ void reinit_audio_chain(struct MPContext *mpctx) } mpctx->mixer.ao = ao; mpctx->mixer.volstep = volstep; + mpctx->mixer.softvol = opts->softvol; + mpctx->mixer.softvol_max = opts->softvol_max; mpctx->syncing_audio = true; return; diff --git a/options.h b/options.h index 9f1352d98f..8b8d2f5c3b 100644 --- a/options.h +++ b/options.h @@ -6,6 +6,10 @@ typedef struct MPOpts { char **audio_driver_list; int fixed_vo; int vo_ontop; + char *mixer_device; + char *mixer_channel; + int softvol; + float softvol_max; int gapless_audio; int ao_buffersize; int screen_size_x; -- cgit v1.2.3 From fd50478659e56db84e8564434702cdc8291ac854 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Fri, 16 Mar 2012 08:04:24 +0200 Subject: core: improve sub and audio start after timeline part switch When switching to a timeline part from another file, decoders were reinitialized after doing the demuxer-level seek. This is necessary for audio because some decoders read from the demuxer stream during initialization and the previous stream position before seek could have been at EOF. However, this initialization sequence could lose first subtitles or first part of audio. The problem for subtitles was that the seek itself or audio initialization could already have buffered subtitle packets from the new position, and the way subtitles are reinitialized flushes packet buffers. Thus early subtitles could be lost (even if they were demuxed - unfortunately demuxers may not know about still active subtitles earlier in the file, but that's another issue). Fix this by moving subtitle and video reinitialization before the demuxer seek; they don't have the problems which prevent that for audio. Audio initialization can already decode and buffer some output. However, the seek_reset() call done last would then throw away this buffered output. Work around this by adding an extra flag to seek_reset(). --- mplayer.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/mplayer.c b/mplayer.c index 7ca2d0303f..3803dffe79 100644 --- a/mplayer.c +++ b/mplayer.c @@ -3030,14 +3030,7 @@ void add_step_frame(struct MPContext *mpctx) unpause_player(mpctx); } -static void reinit_decoders(struct MPContext *mpctx) -{ - reinit_video_chain(mpctx); - reinit_audio_chain(mpctx); - mp_property_do("sub", M_PROPERTY_SET, &(int){mpctx->global_sub_pos}, mpctx); -} - -static void seek_reset(struct MPContext *mpctx, bool reset_ao) +static void seek_reset(struct MPContext *mpctx, bool reset_ao, bool reset_ac) { if (mpctx->sh_video) { current_module = "seek_video_reset"; @@ -3059,7 +3052,7 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao) update_teletext(mpctx->sh_video, mpctx->demuxer, 1); } - if (mpctx->sh_audio) { + if (mpctx->sh_audio && reset_ac) { current_module = "seek_audio_reset"; resync_audio_stream(mpctx->sh_audio); if (reset_ao) @@ -3168,13 +3161,19 @@ static int seek(MPContext *mpctx, struct seek_params seek, if (demuxer_amount == -1) { mpctx->stop_play = AT_END_OF_FILE; // Clear audio from current position - if (mpctx->sh_audio) { + if (mpctx->sh_audio && !timeline_fallthrough) { ao_reset(mpctx->ao); mpctx->sh_audio->a_buffer_len = 0; } return -1; } } + if (need_reset) { + reinit_video_chain(mpctx); + mp_property_do("sub", M_PROPERTY_SET, &(int){mpctx->global_sub_pos}, + mpctx); + } + int demuxer_style = 0; switch (seek.type) { case MPSEEK_FACTOR: @@ -3191,12 +3190,19 @@ static int seek(MPContext *mpctx, struct seek_params seek, demuxer_amount -= opts->hr_seek_demuxer_offset; int seekresult = demux_seek(mpctx->demuxer, demuxer_amount, audio_delay, demuxer_style); - if (need_reset) - reinit_decoders(mpctx); - if (seekresult == 0) + if (seekresult == 0) { + if (need_reset) { + reinit_audio_chain(mpctx); + seek_reset(mpctx, !timeline_fallthrough, false); + } return -1; + } - seek_reset(mpctx, !timeline_fallthrough); + if (need_reset) + reinit_audio_chain(mpctx); + /* If we just reinitialized audio it doesn't need to be reset, + * and resetting could lose audio some decoders produce during init. */ + seek_reset(mpctx, !timeline_fallthrough, !need_reset); /* Use the target time as "current position" for further relative * seeks etc until a new video frame has been decoded */ @@ -3384,7 +3390,7 @@ int seek_chapter(struct MPContext *mpctx, int chapter, double *seek_pts) int res = demuxer_seek_chapter(mpctx->demuxer, chapter, seek_pts); if (res >= 0) { if (*seek_pts == -1) - seek_reset(mpctx, true); + seek_reset(mpctx, true, true); else { mpctx->last_chapter_seek = res; mpctx->last_chapter_pts = *seek_pts; -- cgit v1.2.3 From 4f1e4eae993a22eff4561c7c05f723f6c9ff94b8 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Sat, 10 Dec 2011 22:39:43 +0200 Subject: cosmetics: misc minor cleanups The deleted ZRM* things were only relevant to vo_zr, which was deleted earlier. --- Makefile | 4 ++-- libmpcodecs/img_format.c | 3 --- libmpcodecs/img_format.h | 5 ----- libmpcodecs/mp_image.c | 4 +--- libmpdemux/demux_lavf.c | 2 +- libvo/video_out.h | 1 - mp_msg.c | 4 ++-- 7 files changed, 6 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 59cbdc4950..64d94d9bc0 100644 --- a/Makefile +++ b/Makefile @@ -414,12 +414,12 @@ SRCS_COMMON = asxparser.c \ stream/stream_null.c \ stream/url.c \ sub/av_sub.c \ - sub/sub.c \ - sub/sub_cc.c \ sub/dec_sub.c \ sub/find_sub.c \ sub/find_subfiles.c \ sub/spudec.c \ + sub/sub.c \ + sub/sub_cc.c \ sub/subassconvert.c \ sub/subreader.c \ sub/vobsub.c \ diff --git a/libmpcodecs/img_format.c b/libmpcodecs/img_format.c index c4884f3eca..c6d3e82149 100644 --- a/libmpcodecs/img_format.c +++ b/libmpcodecs/img_format.c @@ -102,9 +102,6 @@ const char *vo_format_name(int format) case IMGFMT_YUVP: return "Packed YUVP"; case IMGFMT_UYVP: return "Packed UYVP"; case IMGFMT_MPEGPES: return "Mpeg PES"; - case IMGFMT_ZRMJPEGNI: return "Zoran MJPEG non-interlaced"; - case IMGFMT_ZRMJPEGIT: return "Zoran MJPEG top field first"; - case IMGFMT_ZRMJPEGIB: return "Zoran MJPEG bottom field first"; case IMGFMT_XVMC_MOCO_MPEG2: return "MPEG1/2 Motion Compensation"; case IMGFMT_XVMC_IDCT_MPEG2: return "MPEG1/2 Motion Compensation and IDCT"; case IMGFMT_VDPAU_MPEG1: return "MPEG1 VDPAU acceleration"; diff --git a/libmpcodecs/img_format.h b/libmpcodecs/img_format.h index 3056e29268..d4443af2c9 100644 --- a/libmpcodecs/img_format.h +++ b/libmpcodecs/img_format.h @@ -190,11 +190,6 @@ /* Compressed Formats */ #define IMGFMT_MPEGPES (('M'<<24)|('P'<<16)|('E'<<8)|('S')) #define IMGFMT_MJPEG (('M')|('J'<<8)|('P'<<16)|('G'<<24)) -/* Formats that are understood by zoran chips, we include - * non-interlaced, interlaced top-first, interlaced bottom-first */ -#define IMGFMT_ZRMJPEGNI (('Z'<<24)|('R'<<16)|('N'<<8)|('I')) -#define IMGFMT_ZRMJPEGIT (('Z'<<24)|('R'<<16)|('I'<<8)|('T')) -#define IMGFMT_ZRMJPEGIB (('Z'<<24)|('R'<<16)|('I'<<8)|('B')) // I think that this code could not be used by any other codec/format #define IMGFMT_XVMC 0x1DC70000 diff --git a/libmpcodecs/mp_image.c b/libmpcodecs/mp_image.c index 4683f41174..45426eb673 100644 --- a/libmpcodecs/mp_image.c +++ b/libmpcodecs/mp_image.c @@ -99,9 +99,7 @@ void mp_image_setfmt(mp_image_t* mpi,unsigned int out_fmt){ mpi->flags&=~(MP_IMGFLAG_PLANAR|MP_IMGFLAG_YUV|MP_IMGFLAG_SWAPPED); mpi->imgfmt=out_fmt; // compressed formats - if(out_fmt == IMGFMT_MPEGPES || - out_fmt == IMGFMT_ZRMJPEGNI || out_fmt == IMGFMT_ZRMJPEGIT || out_fmt == IMGFMT_ZRMJPEGIB || - IMGFMT_IS_HWACCEL(out_fmt)){ + if(out_fmt == IMGFMT_MPEGPES || IMGFMT_IS_HWACCEL(out_fmt)){ mpi->bpp=0; return; } diff --git a/libmpdemux/demux_lavf.c b/libmpdemux/demux_lavf.c index 5fb66adb9d..f8311e215c 100644 --- a/libmpdemux/demux_lavf.c +++ b/libmpdemux/demux_lavf.c @@ -517,7 +517,7 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i) AVCodec *avc = avcodec_find_decoder(codec->codec_id); const char *codec_name = avc ? avc->name : "unknown"; if (!avc && *stream_type == 's' && demuxer->s_streams[i]) - codec_name = sh_sub_type2str(((sh_sub_t *)demuxer->s_streams[i])->type); + codec_name = sh_sub_type2str((demuxer->s_streams[i])->type); mp_msg(MSGT_DEMUX, MSGL_INFO, "[lavf] stream %d: %s (%s), -%cid %d", i, stream_type, codec_name, *stream_type, stream_id); if (lang && lang->value && *stream_type != 'v') diff --git a/libvo/video_out.h b/libvo/video_out.h index 554b97d207..3dd3ca8a8d 100644 --- a/libvo/video_out.h +++ b/libvo/video_out.h @@ -378,7 +378,6 @@ struct vo_rect { void calc_src_dst_rects(struct vo *vo, int src_width, int src_height, struct vo_rect *src, struct vo_rect *dst, struct vo_rect *borders, const struct vo_rect *crop); -struct input_ctx; void vo_mouse_movement(struct vo *vo, int posx, int posy); static inline int aspect_scaling(void) diff --git a/mp_msg.c b/mp_msg.c index ac520951ae..7b97d286e4 100644 --- a/mp_msg.c +++ b/mp_msg.c @@ -339,7 +339,7 @@ char *mp_gtext(const char *string) * couple of reasons (locale stuff is badly designed and sucks in * general). * - * First setting the locale, especially LC_CTYPE, changes the + * First, setting the locale, especially LC_CTYPE, changes the * behavior of various C functions and we don't want that - we * want isalpha() for example to always behave like in the C * locale. @@ -361,7 +361,7 @@ char *mp_gtext(const char *string) * affect gettext itself because it supports specifying the * character set directly with bind_textdomain_codeset()). * - * So the only solution (at leat short of trying to work around + * So the only solution (at least short of trying to work around * things possibly producing non-utf-8 output) is to leave all the * locale variables unset. Note that this means it's not possible * to get translated output from any libraries we call if they -- cgit v1.2.3 From a3b4f64df4a3b0023378ed55b36078a484685363 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Tue, 20 Mar 2012 00:53:00 +0200 Subject: cosmetics: vf_vo.c: reformat --- libmpcodecs/vf_vo.c | 209 +++++++++++++++++++++++++++------------------------- 1 file changed, 107 insertions(+), 102 deletions(-) diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c index b855ea86df..0f89d7312f 100644 --- a/libmpcodecs/vf_vo.c +++ b/libmpcodecs/vf_vo.c @@ -33,8 +33,6 @@ #include "sub/ass_mp.h" #include "sub/sub.h" -//===========================================================================// - extern float sub_delay; struct vf_priv_s { @@ -48,47 +46,49 @@ struct vf_priv_s { }; #define video_out (vf->priv->vo) -static int query_format(struct vf_instance *vf, unsigned int fmt); /* forward declaration */ -static void draw_slice(struct vf_instance *vf, unsigned char** src, int* stride, int w,int h, int x, int y); +static int query_format(struct vf_instance *vf, unsigned int fmt); +static void draw_slice(struct vf_instance *vf, unsigned char **src, + int *stride, int w, int h, int x, int y); static int config(struct vf_instance *vf, - int width, int height, int d_width, int d_height, - unsigned int flags, unsigned int outfmt){ + int width, int height, int d_width, int d_height, + unsigned int flags, unsigned int outfmt) +{ - if ((width <= 0) || (height <= 0) || (d_width <= 0) || (d_height <= 0)) - { - mp_msg(MSGT_CPLAYER, MSGL_ERR, "VO: invalid dimensions!\n"); - return 0; + if ((width <= 0) || (height <= 0) || (d_width <= 0) || (d_height <= 0)) { + mp_msg(MSGT_CPLAYER, MSGL_ERR, "VO: invalid dimensions!\n"); + return 0; } const vo_info_t *info = video_out->driver->info; - mp_msg(MSGT_CPLAYER,MSGL_INFO,"VO: [%s] %dx%d => %dx%d %s %s%s%s%s\n",info->short_name, - width, height, - d_width, d_height, - vo_format_name(outfmt), - (flags&VOFLAG_FULLSCREEN)?" [fs]":"", - (flags&VOFLAG_MODESWITCHING)?" [vm]":"", - (flags&VOFLAG_SWSCALE)?" [zoom]":"", - (flags&VOFLAG_FLIPPING)?" [flip]":""); - mp_msg(MSGT_CPLAYER,MSGL_V,"VO: Description: %s\n",info->name); - mp_msg(MSGT_CPLAYER,MSGL_V,"VO: Author: %s\n", info->author); - if(info->comment && strlen(info->comment) > 0) - mp_msg(MSGT_CPLAYER,MSGL_V,"VO: Comment: %s\n", info->comment); + mp_msg(MSGT_CPLAYER, MSGL_INFO, "VO: [%s] %dx%d => %dx%d %s %s%s%s%s\n", + info->short_name, + width, height, + d_width, d_height, + vo_format_name(outfmt), + (flags & VOFLAG_FULLSCREEN) ? " [fs]" : "", + (flags & VOFLAG_MODESWITCHING) ? " [vm]" : "", + (flags & VOFLAG_SWSCALE) ? " [zoom]" : "", + (flags & VOFLAG_FLIPPING) ? " [flip]" : ""); + mp_msg(MSGT_CPLAYER, MSGL_V, "VO: Description: %s\n", info->name); + mp_msg(MSGT_CPLAYER, MSGL_V, "VO: Author: %s\n", info->author); + if (info->comment && strlen(info->comment) > 0) + mp_msg(MSGT_CPLAYER, MSGL_V, "VO: Comment: %s\n", info->comment); // save vo's stride capability for the wanted colorspace: - vf->default_caps=query_format(vf,outfmt); + vf->default_caps = query_format(vf, outfmt); vf->draw_slice = (vf->default_caps & VOCAP_NOSLICES) ? NULL : draw_slice; if (vo_config(video_out, width, height, d_width, d_height, flags, outfmt)) - return 0; + return 0; #ifdef CONFIG_ASS vf->priv->scale_ratio = (double) d_width / d_height * height / width; if (vf->priv->renderer_realaspect) { - mp_ass_configure(vf->priv->renderer_realaspect, vf->opts, width, height, + mp_ass_configure(vf->priv->renderer_realaspect, vf->opts, width, height, vf->default_caps & VFCAP_EOSD_UNSCALED); - mp_ass_configure(vf->priv->renderer_vsfilter, vf->opts, width, height, + mp_ass_configure(vf->priv->renderer_vsfilter, vf->opts, width, height, vf->default_caps & VFCAP_EOSD_UNSCALED); } @@ -99,44 +99,46 @@ static int config(struct vf_instance *vf, return 1; } -static int control(struct vf_instance *vf, int request, void* data) +static int control(struct vf_instance *vf, int request, void *data) { - switch(request){ + switch (request) { case VFCTRL_GET_DEINTERLACE: - { - if(!video_out) return CONTROL_FALSE; // vo not configured? + if (!video_out) + return CONTROL_FALSE; // vo not configured? return vo_control(video_out, VOCTRL_GET_DEINTERLACE, data) == VO_TRUE; - } case VFCTRL_SET_DEINTERLACE: - { - if(!video_out) return CONTROL_FALSE; // vo not configured? + if (!video_out) + return CONTROL_FALSE; // vo not configured? return vo_control(video_out, VOCTRL_SET_DEINTERLACE, data) == VO_TRUE; - } case VFCTRL_GET_YUV_COLORSPACE: return vo_control(video_out, VOCTRL_GET_YUV_COLORSPACE, data) == true; case VFCTRL_SET_YUV_COLORSPACE: return vo_control(video_out, VOCTRL_SET_YUV_COLORSPACE, data) == true; case VFCTRL_DRAW_OSD: - if(!video_out->config_ok) return CONTROL_FALSE; // vo not configured? - vo_draw_osd(video_out, data); - return CONTROL_TRUE; - case VFCTRL_SET_EQUALIZER: - { - vf_equalizer_t *eq=data; - if(!video_out->config_ok) return CONTROL_FALSE; // vo not configured? - struct voctrl_set_equalizer_args param = {eq->item, eq->value}; - return vo_control(video_out, VOCTRL_SET_EQUALIZER, ¶m) == VO_TRUE; + if (!video_out->config_ok) + return CONTROL_FALSE; // vo not configured? + vo_draw_osd(video_out, data); + return CONTROL_TRUE; + case VFCTRL_SET_EQUALIZER: { + vf_equalizer_t *eq = data; + if (!video_out->config_ok) + return CONTROL_FALSE; // vo not configured? + struct voctrl_set_equalizer_args param = { + eq->item, eq->value + }; + return vo_control(video_out, VOCTRL_SET_EQUALIZER, ¶m) == VO_TRUE; } - case VFCTRL_GET_EQUALIZER: - { - vf_equalizer_t *eq=data; - if(!video_out->config_ok) return CONTROL_FALSE; // vo not configured? - struct voctrl_get_equalizer_args param = {eq->item, &eq->value}; - return vo_control(video_out, VOCTRL_GET_EQUALIZER, ¶m) == VO_TRUE; + case VFCTRL_GET_EQUALIZER: { + vf_equalizer_t *eq = data; + if (!video_out->config_ok) + return CONTROL_FALSE; // vo not configured? + struc