1 /*
2  * This file is part of MPlayer.
3  *
4  * MPlayer is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * MPlayer is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #include "config.h"
20 
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <limits.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <unistd.h>
30 #include <assert.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 
34 #if defined(__MINGW32__) || defined(__CYGWIN__)
35 #define _UWIN 1  /*disable Non-underscored versions of non-ANSI functions as otherwise int eof would conflict with eof()*/
36 #include <windows.h>
37 #endif
38 
39 #ifndef __MINGW32__
40 #include <sys/ioctl.h>
41 #include <sys/wait.h>
42 #else
43 #define SIGHUP  1       /* hangup */
44 #define SIGQUIT 3       /* quit */
45 #define SIGKILL 9       /* kill (cannot be caught or ignored) */
46 #define SIGBUS  10      /* bus error */
47 #define SIGPIPE 13      /* broken pipe */
48 #endif
49 
50 #ifdef HAVE_RTC
51 #ifdef __linux__
52 #include <linux/rtc.h>
53 #else
54 #include <rtc.h>
55 #define RTC_IRQP_SET RTCIO_IRQP_SET
56 #define RTC_PIE_ON   RTCIO_PIE_ON
57 #endif /* __linux__ */
58 #endif /* HAVE_RTC */
59 
60 /*
61  * In Mac OS X the SDL-lib is built upon Cocoa. The easiest way to
62  * make it all work is to use the builtin SDL-bootstrap code, which
63  * will be done automatically by replacing our main() if we include SDL.h.
64  */
65 #if defined(__APPLE__) && defined(CONFIG_SDL)
66 #ifdef CONFIG_SDL_SDL_H
67 #include <SDL/SDL.h>
68 #else
69 #include <SDL.h>
70 #endif
71 #endif
72 
73 #include "gui/interface.h"
74 #include "input/input.h"
75 #include "libao2/audio_out.h"
76 #include "libavutil/avstring.h"
77 #include "libavutil/intreadwrite.h"
78 #include "libmenu/menu.h"
79 #include "libmpcodecs/dec_audio.h"
80 #include "libmpcodecs/dec_video.h"
81 #include "libmpcodecs/mp_image.h"
82 #include "libmpcodecs/vd.h"
83 #include "libmpcodecs/vf.h"
84 #include "libmpdemux/demuxer.h"
85 #include "libmpdemux/stheader.h"
86 #include "sub/font_load.h"
87 #include "sub/sub.h"
88 #include "libvo/video_out.h"
89 #include "stream/cache2.h"
90 #include "stream/stream.h"
91 #include "stream/stream_bd.h"
92 #include "stream/stream_dvdnav.h"
93 #include "stream/stream_radio.h"
94 #include "stream/tv.h"
95 #include "access_mpcontext.h"
96 #include "sub/ass_mp.h"
97 #include "cfg-mplayer-def.h"
98 #include "codec-cfg.h"
99 #include "command.h"
100 #include "edl.h"
101 #include "help_mp.h"
102 #include "m_config.h"
103 #include "m_option.h"
104 #include "m_property.h"
105 #include "m_struct.h"
106 #include "metadata.h"
107 #include "mixer.h"
108 #include "mp_core.h"
109 #include "mp_fifo.h"
110 #include "mp_msg.h"
111 #include "mp_strings.h"
112 #include "mpcommon.h"
113 #include "mplayer.h"
114 #include "osdep/getch2.h"
115 #include "osdep/timer.h"
116 #include "parser-cfg.h"
117 #include "parser-mpcmd.h"
118 #include "path.h"
119 #include "playtree.h"
120 #include "playtreeparser.h"
121 #include "sub/spudec.h"
122 #include "sub/subreader.h"
123 #include "sub/vobsub.h"
124 #include "sub/eosd.h"
125 
126 #include "udp_sync.h"
127 
128 #ifdef CONFIG_X11
129 #include "libvo/x11_common.h"
130 #endif
131 #ifdef CONFIG_DVBIN
132 #include "stream/dvbin.h"
133 #endif
134 #ifdef CONFIG_DVDREAD
135 #include "stream/stream_dvd.h"
136 #endif
137 
138 int slave_mode;
139 int player_idle_mode;
140 int quiet;
141 int enable_mouse_movements;
142 float start_volume = -1;
143 double start_pts   = MP_NOPTS_VALUE;
144 char *heartbeat_cmd;
145 float heartbeat_interval = 30.0;
146 static int max_framesize;
147 
148 int noconsolecontrols;
149 //**************************************************************************//
150 
151 // Not all functions in mplayer.c take the context as an argument yet
152 static MPContext mpctx_s = {
153     .osd_function   = OSD_PLAY,
154     .begin_skip     = MP_NOPTS_VALUE,
155     .play_tree_step = 1,
156     .global_sub_pos = -1,
157     .set_of_sub_pos = -1,
158     .file_format    = DEMUXER_TYPE_UNKNOWN,
159     .loop_times     = -1,
160 #ifdef CONFIG_DVBIN
161     .last_dvb_step  = 1,
162 #endif
163 };
164 
165 static MPContext *mpctx = &mpctx_s;
166 
167 int fixed_vo;
168 
169 // benchmark:
170 double video_time_usage;
171 double vout_time_usage;
172 static double audio_time_usage;
173 static int total_time_usage_start;
174 static int total_frame_cnt;
175 static int drop_frame_cnt; // total number of dropped frames
176 int benchmark;
177 
178 // options:
179 #define DEFAULT_STARTUP_DECODE_RETRY 8
180 int auto_quality;
181 static int output_quality;
182 
183 float playback_speed = 1.0;
184 
185 int use_gui;
186 
187 #ifdef CONFIG_GUI
188 int enqueue;
189 #endif
190 
191 static int list_properties;
192 
193 int osd_level = 1;
194 // if nonzero, hide current OSD contents when GetTimerMS() reaches this
195 unsigned int osd_visible;
196 int osd_duration = 1000;
197 int osd_fractions; // determines how fractions of seconds are displayed
198                    // on OSD
199 
200 int term_osd = 1;
201 static char *term_osd_esc = "\x1b[A\r\x1b[K";
202 static char *playing_msg;
203 // seek:
204 static double seek_to_sec = MP_NOPTS_VALUE;
205 static off_t seek_to_byte;
206 static off_t step_sec;
207 static int loop_seek;
208 
209 static m_time_size_t end_at = { .type = END_AT_NONE, .pos = 0 };
210 
211 // A/V sync:
212 int autosync;        // 30 might be a good default value.
213 
214 // may be changed by GUI:  (FIXME!)
215 float rel_seek_secs;
216 int abs_seek_pos;
217 
218 // codecs:
219 char **audio_codec_list; // override audio codec
220 char **video_codec_list; // override video codec
221 char **audio_fm_list;    // override audio codec family
222 char **video_fm_list;    // override video codec family
223 
224 // streaming:
225 int audio_id  = -1;
226 int video_id  = -1;
227 int dvdsub_id = -1;
228 // this dvdsub_id was selected via slang
229 // use this to allow dvdnav to follow -slang across stream resets,
230 // in particular the subtitle ID for a language changes
231 int dvdsub_lang_id;
232 int vobsub_id = -1;
233 char *audio_lang;
234 char *dvdsub_lang;
235 char *filename;
236 int file_filter = 1;
237 
238 // cache2:
239 int stream_cache_size = -1;
240 #ifdef CONFIG_STREAM_CACHE
241 float stream_cache_min_percent      = 20.0;
242 float stream_cache_seek_min_percent = 50.0;
243 #endif
244 
245 // dump:
246 char *stream_dump_name = "stream.dump";
247 int stream_dump_type;
248 uint64_t stream_dump_count;
249 unsigned stream_dump_start_time;
250 unsigned stream_dump_last_print_time;
251 int capture_dump;
252 
253 // A-V sync:
254 static float default_max_pts_correction = -1;
255 static float max_pts_correction; //default_max_pts_correction;
256 static float c_total;
257 float audio_delay;
258 static int ignore_start;
259 
260 static int softsleep;
261 
262 double force_fps;
263 static int force_srate;
264 static int audio_output_format = AF_FORMAT_UNKNOWN;
265 int frame_dropping;        // option  0=no drop  1= drop vo  2= drop decode
266 static int play_n_frames    = -1;
267 static int play_n_frames_mf = -1;
268 
269 // screen info:
270 char **video_driver_list;
271 char **audio_driver_list;
272 
273 // sub:
274 char *font_name;
275 char *sub_font_name;
276 float font_factor = 0.75;
277 char **sub_name;
278 char **sub_paths;
279 float sub_delay;
280 float sub_fps;
281 int sub_auto = 1;
282 char *vobsub_name;
283 int subcc_enabled;
284 int suboverlap_enabled = 1;
285 
286 char *current_module; // for debugging
287 
288 #ifdef CONFIG_MENU
289 static const vf_info_t *const libmenu_vfs[] = {
290     &vf_info_menu,
291     NULL
292 };
293 static vf_instance_t *vf_menu;
294 int use_menu;
295 static char *menu_cfg;
296 static char *menu_root = "main";
297 #endif
298 
299 #ifdef HAVE_RTC
300 static int nortc = 1;
301 static char *rtc_device;
302 #endif
303 
304 edl_record_ptr edl_records;     ///< EDL entries memory area
305 edl_record_ptr next_edl_record; ///< only for traversing edl_records
306 short edl_decision;             ///< 1 when an EDL operation has been made.
307 short edl_needs_reset;          ///< 1 if we need to reset EDL next pointer
308 short edl_backward;             ///< 1 if we need to skip to the beginning of the next EDL record
309 FILE *edl_fd;                   ///< fd to write to when in -edlout mode.
310 // Number of seconds to add to the seek when jumping out
311 // of EDL scene in backward direction. This is needed to
312 // have some time after the seek to decide what to do next
313 // (next seek, pause,...), otherwise after the seek it will
314 // enter the same scene again and skip forward immediately
315 float edl_backward_delay = 2;
316 int edl_start_pts;              ///< Automatically add/sub this from EDL start/stop pos
317 int use_filedir_conf;
318 int use_filename_title;
319 
320 static unsigned int initialized_flags;
321 
322 int volstep = 3; ///< step size of mixer changes
323 
324 #ifdef CONFIG_CRASH_DEBUG
325 static char *prog_path;
326 static int crash_debug;
327 #endif
328 
329 int allow_playlist_parsing;
330 
331 /* This header requires all the global variable declarations. */
332 #include "cfg-mplayer.h"
333 
mpctx_get_video_out(MPContext * mpctx)334 const void *mpctx_get_video_out(MPContext *mpctx)
335 {
336     return mpctx->video_out;
337 }
338 
mpctx_get_audio_out(MPContext * mpctx)339 const void *mpctx_get_audio_out(MPContext *mpctx)
340 {
341     return mpctx->audio_out;
342 }
343 
mpctx_get_demuxer(MPContext * mpctx)344 void *mpctx_get_demuxer(MPContext *mpctx)
345 {
346     return mpctx->demuxer;
347 }
348 
mpctx_get_playtree_iter(MPContext * mpctx)349 void *mpctx_get_playtree_iter(MPContext *mpctx)
350 {
351     return mpctx->playtree_iter;
352 }
353 
mpctx_get_mixer(MPContext * mpctx)354 void *mpctx_get_mixer(MPContext *mpctx)
355 {
356     return &mpctx->mixer;
357 }
358 
mpctx_get_global_sub_info(MPContext * mpctx,int * size,int * pos)359 void mpctx_get_global_sub_info(MPContext *mpctx, int *size, int *pos)
360 {
361     mp_property_do("sub", M_PROPERTY_GET, pos, mpctx);
362 
363     if (size) *size = mpctx->global_sub_size;
364 }
365 
mpctx_get_osd_function(MPContext * mpctx)366 int mpctx_get_osd_function(MPContext *mpctx)
367 {
368     return mpctx->osd_function;
369 }
370 
mpctx_get_stream(MPContext * mpctx)371 void *mpctx_get_stream(MPContext *mpctx)
372 {
373     return mpctx->stream;
374 }
375 
mpctx_get_afilter(MPContext * mpctx)376 void *mpctx_get_afilter(MPContext *mpctx)
377 {
378     return mpctx->sh_audio ? mpctx->sh_audio->afilter : NULL;
379 }
380 
is_valid_metadata_type(metadata_t type)381 static int is_valid_metadata_type(metadata_t type)
382 {
383     switch (type) {
384     /* check for valid video stream */
385     case META_VIDEO_CODEC:
386     case META_VIDEO_BITRATE:
387     case META_VIDEO_RESOLUTION:
388         if (!mpctx->sh_video)
389             return 0;
390         break;
391 
392     /* check for valid audio stream */
393     case META_AUDIO_CODEC:
394     case META_AUDIO_BITRATE:
395     case META_AUDIO_SAMPLES:
396         if (!mpctx->sh_audio)
397             return 0;
398         break;
399 
400     /* check for valid demuxer */
401     case META_INFO_TITLE:
402     case META_INFO_ARTIST:
403     case META_INFO_ALBUM:
404     case META_INFO_YEAR:
405     case META_INFO_COMMENT:
406     case META_INFO_TRACK:
407     case META_INFO_GENRE:
408         if (!mpctx->demuxer)
409             return 0;
410         break;
411 
412     default:
413         break;
414     }
415 
416     return 1;
417 }
418 
get_demuxer_info(char * tag)419 static char *get_demuxer_info(char *tag)
420 {
421     char **info = mpctx->demuxer->info;
422     int n;
423 
424     if (!info || !tag)
425         return NULL;
426 
427     for (n = 0; info[2 * n] != NULL; n++)
428         if (!av_strcasecmp(info[2 * n], tag))
429             break;
430 
431     return info[2 * n + 1] ? strdup(info[2 * n + 1]) : NULL;
432 }
433 
get_metadata(metadata_t type)434 char *get_metadata(metadata_t type)
435 {
436     sh_audio_t *const sh_audio = mpctx->sh_audio;
437     sh_video_t *const sh_video = mpctx->sh_video;
438 
439     if (!is_valid_metadata_type(type))
440         return NULL;
441 
442     switch (type) {
443     case META_NAME:
444         return strdup(mp_basename(filename));
445 
446     case META_VIDEO_CODEC:
447         if (sh_video->format == 0x10000001)
448             return strdup("mpeg1");
449         else if (sh_video->format == 0x10000002)
450             return strdup("mpeg2");
451         else if (sh_video->format == 0x10000004)
452             return strdup("mpeg4");
453         else if (sh_video->format == 0x10000005)
454             return strdup("h264");
455         else if (sh_video->format >= 0x20202020)
456             return mp_asprintf("%.4s", (char *)&sh_video->format);
457         return mp_asprintf("0x%08X", sh_video->format);
458 
459     case META_VIDEO_BITRATE:
460         return mp_asprintf("%d kbps", (int)(sh_video->i_bps * 8 / 1024));
461 
462     case META_VIDEO_RESOLUTION:
463         return mp_asprintf("%d x %d", sh_video->disp_w, sh_video->disp_h);
464 
465     case META_AUDIO_CODEC:
466         if (sh_audio->codec && sh_audio->codec->name_idx)
467             return strdup(codec_idx2str(sh_audio->codec->name_idx));
468         break;
469 
470     case META_AUDIO_BITRATE:
471         return mp_asprintf("%d kbps", (int)(sh_audio->i_bps * 8 / 1000));
472 
473     case META_AUDIO_SAMPLES:
474         return mp_asprintf("%d Hz, %d ch.", sh_audio->samplerate, sh_audio->channels);
475 
476     /* check for valid demuxer */
477     case META_INFO_TITLE:
478         return get_demuxer_info("Title");
479 
480     case META_INFO_ARTIST:
481         return get_demuxer_info("Artist");
482 
483     case META_INFO_ALBUM:
484         return get_demuxer_info("Album");
485 
486     case META_INFO_YEAR:
487         return get_demuxer_info("Year");
488 
489     case META_INFO_COMMENT:
490         return get_demuxer_info("Comment");
491 
492     case META_INFO_TRACK:
493         return get_demuxer_info("Track");
494 
495     case META_INFO_GENRE:
496         return get_demuxer_info("Genre");
497 
498     default:
499         break;
500     }
501 
502     return NULL;
503 }
504 
print_file_properties(const MPContext * mpctx,const char * filename)505 static void print_file_properties(const MPContext *mpctx, const char *filename)
506 {
507     double video_start_pts = MP_NOPTS_VALUE;
508     mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILENAME=%s\n",
509            filename_recode(filename));
510     mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DEMUXER=%s\n", mpctx->demuxer ? mpctx->demuxer->desc->name : "none");
511     if (mpctx->sh_video) {
512         /* Assume FOURCC if all bytes >= 0x20 (' ') */
513         if (mpctx->sh_video->format >= 0x20202020)
514             mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_FORMAT=%.4s\n", (char *)&mpctx->sh_video->format);
515         else
516             mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_FORMAT=0x%08X\n", mpctx->sh_video->format);
517         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_BITRATE=%d\n",   mpctx->sh_video->i_bps * 8);
518         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_WIDTH=%d\n",     mpctx->sh_video->disp_w);
519         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_HEIGHT=%d\n",    mpctx->sh_video->disp_h);
520         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_FPS=%5.3f\n",    mpctx->sh_video->fps);
521         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_ASPECT=%1.4f\n", mpctx->sh_video->aspect);
522         video_start_pts = ds_get_next_pts(mpctx->d_video);
523     }
524     if (mpctx->sh_audio) {
525         /* Assume FOURCC if all bytes >= 0x20 (' ') */
526         if (mpctx->sh_audio->format >= 0x20202020)
527             mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_FORMAT=%.4s\n", (char *)&mpctx->sh_audio->format);
528         else
529             mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_FORMAT=%d\n", mpctx->sh_audio->format);
530         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_BITRATE=%d\n", mpctx->sh_audio->i_bps * 8);
531         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_RATE=%d\n",    mpctx->sh_audio->samplerate);
532         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_NCH=%d\n",     mpctx->sh_audio->channels);
533         start_pts = ds_get_next_pts(mpctx->d_audio);
534     }
535     if (video_start_pts != MP_NOPTS_VALUE) {
536         if (start_pts == MP_NOPTS_VALUE || !mpctx->sh_audio ||
537             (mpctx->sh_video && video_start_pts < start_pts))
538             start_pts = video_start_pts;
539     }
540     if (start_pts != MP_NOPTS_VALUE)
541         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_START_TIME=%.2f\n", start_pts);
542     else
543         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_START_TIME=unknown\n");
544     mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_LENGTH=%.2f\n", mpctx->demuxer ? demuxer_get_time_length(mpctx->demuxer) : 0);
545     mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SEEKABLE=%d\n",
546            mpctx->stream->seek && (!mpctx->demuxer || mpctx->demuxer->seekable));
547     if (mpctx->demuxer) {
548         if (mpctx->demuxer->num_chapters == 0)
549             stream_control(mpctx->demuxer->stream, STREAM_CTRL_GET_NUM_CHAPTERS, &mpctx->demuxer->num_chapters);
550         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTERS=%d\n", mpctx->demuxer->num_chapters);
551     }
552 }
553 
554 #ifdef CONFIG_DVDNAV
mp_dvdnav_context_free(MPContext * ctx)555 static void mp_dvdnav_context_free(MPContext *ctx)
556 {
557     if (ctx->nav_smpi)
558         free_mp_image(ctx->nav_smpi);
559     ctx->nav_smpi = NULL;
560     free(ctx->nav_buffer);
561     ctx->nav_buffer  = NULL;
562     ctx->nav_start   = NULL;
563     ctx->nav_in_size = 0;
564 }
565 
566 #endif
567 
uninit_player(unsigned int mask)568 void uninit_player(unsigned int mask)
569 {
570     mask &= initialized_flags;
571 
572     mp_msg(MSGT_CPLAYER, MSGL_DBG2, "\n*** uninit(0x%X)\n", mask);
573 
574     if (mask & INITIALIZED_ACODEC) {
575         initialized_flags &= ~INITIALIZED_ACODEC;
576         current_module     = "uninit_acodec";
577         if (mpctx->sh_audio)
578             uninit_audio(mpctx->sh_audio);
579         mpctx->sh_audio      = NULL;
580         mpctx->mixer.afilter = NULL;
581     }
582 
583     if (mask & INITIALIZED_VCODEC) {
584         initialized_flags &= ~INITIALIZED_VCODEC;
585         current_module     = "uninit_vcodec";
586         if (mpctx->sh_video)
587             uninit_video(mpctx->sh_video);
588         mpctx->sh_video = NULL;
589 #ifdef CONFIG_MENU
590         vf_menu = NULL;
591 #endif
592     }
593 
594     if (mask & INITIALIZED_DEMUXER) {
595         initialized_flags &= ~INITIALIZED_DEMUXER;
596         current_module     = "free_demuxer";
597         if (mpctx->demuxer)
598             free_demuxer(mpctx->demuxer);
599         mpctx->demuxer = NULL;
600     }
601 
602     // kill the cache process:
603     if (mask & INITIALIZED_STREAM) {
604         initialized_flags &= ~INITIALIZED_STREAM;
605         current_module     = "uninit_stream";
606         if (mpctx->stream)
607             free_stream(mpctx->stream);
608         mpctx->stream = NULL;
609     }
610 
611     if (mask & INITIALIZED_VO) {
612         initialized_flags &= ~INITIALIZED_VO;
613         current_module     = "uninit_vo";
614         mpctx->video_out->uninit();
615         mpctx->video_out = NULL;
616 #ifdef CONFIG_DVDNAV
617         mp_dvdnav_context_free(mpctx);
618 #endif
619         if (vo_spudec) {
620             current_module = "uninit_spudec";
621             spudec_free(vo_spudec);
622             vo_spudec = NULL;
623         }
624     }
625 
626     // Must be after libvo uninit, as few vo drivers (svgalib) have tty code.
627     if (mask & INITIALIZED_GETCH2) {
628         initialized_flags &= ~INITIALIZED_GETCH2;
629         current_module     = "uninit_getch2";
630         mp_msg(MSGT_CPLAYER, MSGL_DBG2, "\n[[[uninit getch2]]]\n");
631         // restore terminal:
632         getch2_disable();
633     }
634 
635     if (mask & INITIALIZED_SUBS) {
636         initialized_flags &= ~INITIALIZED_SUBS;
637         if (mpctx->set_of_sub_size > 0) {
638             int i;
639             current_module = "sub_free";
640             for (i = 0; i < mpctx->set_of_sub_size; ++i) {
641                 sub_free(mpctx->set_of_subtitles[i]);
642 #ifdef CONFIG_ASS
643                 if (mpctx->set_of_ass_tracks[i])
644                     ass_free_track(mpctx->set_of_ass_tracks[i]);
645 #endif
646             }
647             mpctx->set_of_sub_size = 0;
648         }
649         vo_sub_last = vo_sub = NULL;
650         subdata     = NULL;
651 #ifdef CONFIG_ASS
652         ass_track = NULL;
653         if (ass_library)
654             ass_clear_fonts(ass_library);
655 #endif
656     }
657 
658     if (mask & INITIALIZED_VOBSUB) {
659         initialized_flags &= ~INITIALIZED_VOBSUB;
660         current_module     = "uninit_vobsub";
661         if (vo_vobsub)
662             vobsub_close(vo_vobsub);
663         vo_vobsub = NULL;
664     }
665 
666     if (mask & INITIALIZED_AO) {
667         initialized_flags &= ~INITIALIZED_AO;
668         current_module     = "uninit_ao";
669         if (mpctx->edl_muted)
670             mixer_mute(&mpctx->mixer);
671         if (mpctx->audio_out)
672             mpctx->audio_out->uninit(mpctx->eof ? 0 : 1);
673         mpctx->audio_out = NULL;
674     }
675 
676 #ifdef CONFIG_GUI
677     if (mask & INITIALIZED_GUI) {
678         initialized_flags &= ~INITIALIZED_GUI;
679         current_module     = "uninit_gui";
680         guiDone();
681     }
682 #endif
683 
684     if (mask & INITIALIZED_INPUT) {
685         initialized_flags &= ~INITIALIZED_INPUT;
686         current_module     = "uninit_input";
687         mp_input_uninit();
688 #ifdef CONFIG_MENU
689         if (use_menu)
690             menu_uninit();
691 #endif
692     }
693 
694     current_module = NULL;
695 }
696 
exit_player_with_rc(enum exit_reason how,int rc)697 void exit_player_with_rc(enum exit_reason how, int rc)
698 {
699 #ifdef CONFIG_NETWORKING
700     if (udp_master)
701         send_udp(udp_ip, udp_port, "bye");
702 #endif /* CONFIG_NETWORKING */
703 
704     if (mpctx->user_muted && !mpctx->edl_muted)
705         mixer_mute(&mpctx->mixer);
706     uninit_player(INITIALIZED_ALL);
707 #if defined(__MINGW32__) || defined(__CYGWIN__)
708     timeEndPeriod(1);
709 #endif
710 #ifdef CONFIG_X11
711 #ifdef CONFIG_GUI
712     if (!use_gui)
713 #endif
714     vo_uninit(); // Close the X11 connection (if any is open).
715 #endif
716 
717     common_uninit();
718 
719     current_module = "exit_player";
720 
721     if (mpctx->playtree_iter)
722         play_tree_iter_free(mpctx->playtree_iter);
723     mpctx->playtree_iter = NULL;
724     if (mpctx->playtree)
725         play_tree_free(mpctx->playtree, 1);
726     mpctx->playtree = NULL;
727 
728     free(edl_records); // free mem allocated for EDL
729     edl_records = NULL;
730     switch (how) {
731     case EXIT_QUIT:
732         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_ExitingHow, MSGTR_Exit_quit);
733         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_EXIT=QUIT\n");
734         break;
735     case EXIT_EOF:
736         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_ExitingHow, MSGTR_Exit_eof);
737         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_EXIT=EOF\n");
738         break;
739     case EXIT_ERROR:
740         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_ExitingHow, MSGTR_Exit_error);
741         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_EXIT=ERROR\n");
742         break;
743     default:
744         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_EXIT=NONE\n");
745     }
746     mp_msg(MSGT_CPLAYER, MSGL_DBG2, "max framesize was %d bytes\n", max_framesize);
747 
748     // must be last since e.g. mp_msg uses option values
749     // that will be freed by this.
750     if (mconfig)
751         m_config_free(mconfig);
752     mconfig = NULL;
753 
754     mp_msg_uninit();
755 
756     exit(rc);
757 }
758 
exit_player(enum exit_reason how)759 void exit_player(enum exit_reason how)
760 {
761     exit_player_with_rc(how, 1);
762 }
763 
764 #ifndef __MINGW32__
child_sighandler(int x)765 static void child_sighandler(int x)
766 {
767     pid_t pid;
768     do {
769         pid = waitpid(-1, NULL, WNOHANG);
770     } while (pid > 0);
771     // Without this, we will be called only once at
772     // least on Linux 3.16.
773     signal(SIGCHLD, child_sighandler);
774 }
775 
776 #endif
777 
exit_sighandler(int x)778 static void exit_sighandler(int x)
779 {
780     static int sig_count;
781 #ifdef CONFIG_CRASH_DEBUG
782     if (!crash_debug || x != SIGTRAP)
783 #endif
784     ++sig_count;
785     if (initialized_flags == 0 && sig_count > 1)
786         exit(1);
787     if (sig_count == 5) {
788         /* We're crashing bad and can't uninit cleanly :(
789          * by popular request, we make one last (dirty)
790          * effort to restore the user's
791          * terminal. */
792         getch2_disable();
793         exit(1);
794     }
795     if (sig_count == 6)
796         exit(1);
797     if (sig_count > 6) {
798         // can't stop :(
799 #ifndef __MINGW32__
800         kill(getpid(), SIGKILL);
801 #endif
802     }
803     mp_msg(MSGT_CPLAYER, MSGL_FATAL, "\n" MSGTR_IntBySignal, x,
804            current_module ? current_module : MSGTR_Unknown
805            );
806     mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SIGNAL=%d\n", x);
807     if (sig_count <= 1)
808         switch (x) {
809         case SIGINT:
810         case SIGPIPE:
811         case SIGQUIT:
812         case SIGTERM:
813         case SIGKILL:
814             async_quit_request = 1;
815             return; // killed from keyboard (^C) or killed [-9]
816         case SIGILL:
817 #if CONFIG_RUNTIME_CPUDETECT
818             mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_Exit_SIGILL_RTCpuSel);
819 #else
820             mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_Exit_SIGILL);
821 #endif
822         case SIGFPE:
823         case SIGSEGV:
824             mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_Exit_SIGSEGV_SIGFPE);
825         default:
826             mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_Exit_SIGCRASH);
827 #ifdef CONFIG_CRASH_DEBUG
828             if (crash_debug) {
829                 int gdb_pid;
830                 mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_Forking);
831                 gdb_pid = fork();
832                 mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_Forked);
833                 if (gdb_pid == 0) { // We are the child
834                     char spid[20];
835                     snprintf(spid, sizeof(spid), "%i", getppid());
836                     getch2_disable(); // allow terminal to work properly with gdb
837                     if (execlp("gdb", "gdb", prog_path, spid, "-ex", "bt", NULL) == -1)
838                         mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_CouldntStartGdb);
839                 } else if (gdb_pid < 0)
840                     mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_CouldntFork);
841                 else {
842                     waitpid(gdb_pid, NULL, 0);
843                 }
844                 if (x == SIGTRAP)
845                     return;
846             }
847 #endif
848         }
849     getch2_disable();
850     exit(1);
851 }
852 
parse_cfgfiles(m_config_t * conf)853 static void parse_cfgfiles(m_config_t *conf)
854 {
855     char *conffile;
856     int conffile_fd;
857     if (!disable_system_conf &&
858         m_config_parse_config_file(conf, MPLAYER_CONFDIR "/mplayer.conf", 1) < 0)
859         exit_player(EXIT_NONE);
860     if ((conffile = get_path("")) == NULL) {
861         mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_NoHomeDir);
862     } else {
863 #ifdef __MINGW32__
864         mkdir(conffile);
865 #else
866         mkdir(conffile, 0777);
867 #endif
868         free(conffile);
869         if ((conffile = get_path("config")) == NULL) {
870             mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_GetpathProblem);
871         } else {
872             if ((conffile_fd = open(conffile, O_CREAT | O_EXCL | O_WRONLY, 0666)) != -1) {
873                 mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_CreatingCfgFile, conffile);
874                 write(conffile_fd, default_config, strlen(default_config));
875                 close(conffile_fd);
876             }
877             if (!disable_user_conf &&
878                 m_config_parse_config_file(conf, conffile, 1) < 0)
879                 exit_player(EXIT_NONE);
880             free(conffile);
881         }
882     }
883 }
884 
885 #define PROFILE_CFG_PROTOCOL "protocol."
886 
load_per_protocol_config(m_config_t * conf,const char * const file)887 static void load_per_protocol_config(m_config_t *conf, const char *const file)
888 {
889     char *str;
890     char *protocol;
891     m_profile_t *p;
892 
893     /* does filename actually uses a protocol ? */
894     str = strstr(file, "://");
895     if (!str)
896         return;
897 
898     protocol = av_asprintf("%s%s", PROFILE_CFG_PROTOCOL, file);
899     *strstr(protocol, "://") = 0;
900     p = m_config_get_profile(conf, protocol);
901     if (p) {
902         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_LoadingProtocolProfile, protocol);
903         m_config_set_profile(conf, p);
904     }
905     av_freep(&protocol);
906 }
907 
908 #define PROFILE_CFG_EXTENSION "extension."
909 
load_per_extension_config(m_config_t * conf,const char * const file)910 static void load_per_extension_config(m_config_t *conf, const char *const file)
911 {
912     char *str;
913     char extension[sizeof(PROFILE_CFG_EXTENSION) + 7];
914     m_profile_t *p;
915 
916     /* does filename actually have an extension ? */
917     str = strrchr(filename, '.');
918     if (!str)
919         return;
920 
921     snprintf(extension, sizeof(extension), "%s%s", PROFILE_CFG_EXTENSION, ++str);
922     p = m_config_get_profile(conf, extension);
923     if (p) {
924         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_LoadingExtensionProfile, extension);
925         m_config_set_profile(conf, p);
926     }
927 }
928 
929 #define PROFILE_CFG_VO "vo."
930 #define PROFILE_CFG_AO "ao."
931 
load_per_output_config(m_config_t * conf,char * cfg,char * out)932 static void load_per_output_config(m_config_t *conf, char *cfg, char *out)
933 {
934     m_profile_t *p;
935 
936     char *profile = av_asprintf("%s%s", cfg, out);
937     p = m_config_get_profile(conf, profile);
938     if (p) {
939         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_LoadingExtensionProfile, profile);
940         m_config_set_profile(conf, p);
941     }
942     av_freep(&profile);
943 }
944 
945 /**
946  * @brief Tries to load a config file.
947  * @return 0 if file was not found, 1 otherwise
948  */
try_load_config(m_config_t * conf,const char * file)949 static int try_load_config(m_config_t *conf, const char *file)
950 {
951     struct stat st;
952     if (stat(file, &st))
953         return 0;
954     mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_LoadingConfig, file);
955     m_config_parse_config_file(conf, file, 0);
956     return 1;
957 }
958 
load_per_file_config(m_config_t * conf,const char * const file)959 static void load_per_file_config(m_config_t *conf, const char *const file)
960 {
961     char *confpath;
962     char cfg[PATH_MAX];
963     const char *name;
964 
965     if (strlen(file) > PATH_MAX - 14) {
966         mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_FilenameTooLong);
967         return;
968     }
969     sprintf(cfg, "%s.conf", file);
970 
971     name = mp_basename(cfg);
972     if (use_filedir_conf) {
973         char dircfg[PATH_MAX];
974         strcpy(dircfg, cfg);
975         strcpy(dircfg + (name - cfg), "mplayer.conf");
976         try_load_config(conf, dircfg);
977 
978         if (try_load_config(conf, cfg))
979             return;
980     }
981 
982     if ((confpath = get_path(name)) != NULL) {
983         try_load_config(conf, confpath);
984 
985         free(confpath);
986     }
987 }
988 
load_profile_config(m_config_t * conf,const char * const file)989 static int load_profile_config(m_config_t *conf, const char *const file)
990 {
991     if (file) {
992         load_per_protocol_config(conf, file);
993         load_per_extension_config(conf, file);
994         load_per_file_config(conf, file);
995     }
996 
997     return file != NULL;
998 }
999 
1000 /* When libmpdemux performs a blocking operation (network connection or
1001  * cache filling) if the operation fails we use this function to check
1002  * if it was interrupted by the user.
1003  * The function returns a new value for eof. */
libmpdemux_was_interrupted(int eof)1004 static int libmpdemux_was_interrupted(int eof)
1005 {
1006     mp_cmd_t *cmd;
1007     if ((cmd = mp_input_get_cmd(0, 0, 0)) != NULL) {
1008         switch (cmd->id) {
1009         case MP_CMD_QUIT:
1010             run_command(mpctx, cmd);
1011         case MP_CMD_PLAY_TREE_STEP:
1012             eof = (cmd->args[0].v.i > 0) ? PT_NEXT_ENTRY : PT_PREV_ENTRY;
1013             mpctx->play_tree_step = (cmd->args[0].v.i == 0) ? 1 : cmd->args[0].v.i;
1014             break;
1015         case MP_CMD_PLAY_TREE_UP_STEP:
1016             eof = (cmd->args[0].v.i > 0) ? PT_UP_NEXT : PT_UP_PREV;
1017             break;
1018         case MP_CMD_PLAY_ALT_SRC_STEP:
1019             eof = (cmd->args[0].v.i > 0) ? PT_NEXT_SRC : PT_PREV_SRC;
1020             break;
1021         }
1022         mp_cmd_free(cmd);
1023     }
1024     return eof;
1025 }
1026 
playtree_add_playlist(play_tree_t * entry)1027 static int playtree_add_playlist(play_tree_t *entry)
1028 {
1029     play_tree_add_bpf(entry, filename);
1030 
1031 #ifdef CONFIG_GUI
1032     if (use_gui) {
1033         if (entry) {
1034             guiPlaylist(GUI_PLAYLIST_ADD, entry, mconfig, 0);
1035             play_tree_free_list(entry, 1);
1036         }
1037     } else
1038 #endif
1039     {
1040         if (!entry) {
1041             entry = mpctx->playtree_iter->tree;
1042             if (play_tree_iter_step(mpctx->playtree_iter, 1, 0) != PLAY_TREE_ITER_ENTRY)
1043                 return PT_NEXT_ENTRY;
1044             // Loop with a single file
1045             if (mpctx->playtree_iter->tree == entry &&
1046                 play_tree_iter_up_step(mpctx->playtree_iter, 1, 0) != PLAY_TREE_ITER_ENTRY)
1047                 return PT_NEXT_ENTRY;
1048             play_tree_remove(entry, 1, 1);
1049             return PT_NEXT_SRC;
1050         }
1051         play_tree_insert_entry(mpctx->playtree_iter->tree, entry);
1052         play_tree_set_params_from(entry, mpctx->playtree_iter->tree);
1053         entry = mpctx->playtree_iter->tree;
1054         if (play_tree_iter_step(mpctx->playtree_iter, 1, 0) != PLAY_TREE_ITER_ENTRY)
1055             return PT_NEXT_ENTRY;
1056         play_tree_remove(entry, 1, 1);
1057     }
1058     return PT_NEXT_SRC;
1059 }
1060 
add_subtitles(char * filename,float fps,int noerr)1061 void add_subtitles(char *filename, float fps, int noerr)
1062 {
1063     sub_data *subd;
1064 #ifdef CONFIG_ASS
1065     ASS_Track *asst = 0;
1066 #endif
1067 
1068     if (filename == NULL || mpctx->set_of_sub_size >= MAX_SUBTITLE_FILES)
1069         return;
1070 
1071     enca_sub_cp = NULL;
1072     subd = sub_read_file(filename, fps);
1073 #ifdef CONFIG_ASS
1074     if (ass_enabled)
1075 #ifdef CONFIG_ICONV
1076         asst = ass_read_stream(ass_library, filename, (enca_sub_cp ? enca_sub_cp : sub_cp));
1077 #else
1078         asst = ass_read_stream(ass_library, filename, 0);
1079 #endif
1080     if (ass_enabled && subd && !asst)
1081         asst = ass_read_subdata(ass_library, subd, fps);
1082 
1083     if (!asst && !subd)
1084 #else
1085     if (!subd)
1086 #endif
1087         mp_msg(MSGT_CPLAYER, noerr ? MSGL_WARN : MSGL_ERR, MSGTR_CantLoadSub,
1088                filename_recode(filename));
1089 
1090 #ifdef CONFIG_ASS
1091     if (!asst && !subd)
1092         return;
1093     mpctx->set_of_ass_tracks[mpctx->set_of_sub_size] = asst;
1094 #else
1095     if (!subd)
1096         return;
1097 #endif
1098     mpctx->set_of_subtitles[mpctx->set_of_sub_size] = subd;
1099     mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILE_SUB_ID=%d\n", mpctx->set_of_sub_size);
1100     mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILE_SUB_FILENAME=%s\n",
1101            filename_recode(filename));
1102     ++mpctx->set_of_sub_size;
1103     mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_AddedSubtitleFile, mpctx->set_of_sub_size,
1104            filename_recode(filename));
1105 }
1106 
add_vob_subtitle(const char * vobname,const char * const ifo,int force,void * spu)1107 static int add_vob_subtitle(const char *vobname, const char *const ifo, int force, void *spu)
1108 {
1109     if (!vobname)
1110         return 0;
1111 
1112     assert(!vo_vobsub);
1113 
1114     vo_vobsub = vobsub_open(vobname, ifo, force, spu);
1115 
1116     if (!vo_vobsub && force)
1117         mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_CantLoadSub,
1118                filename_recode(vobname));
1119 
1120     return !!vo_vobsub;
1121 }
1122 
1123 // FIXME: if/when the GUI calls this, global sub numbering gets (potentially) broken.
update_set_of_subtitles(void)1124 void update_set_of_subtitles(void)
1125 {
1126     // subdata was changed, set_of_sub... have to be updated.
1127     sub_data **const set_of_subtitles = mpctx->set_of_subtitles;
1128     int i;
1129     if (mpctx->set_of_sub_size > 0 && subdata == NULL) { // *subdata was deleted
1130         for (i = mpctx->set_of_sub_pos + 1; i < mpctx->set_of_sub_size; ++i)
1131             set_of_subtitles[i - 1] = set_of_subtitles[i];
1132         set_of_subtitles[mpctx->set_of_sub_size - 1] = NULL;
1133         --mpctx->set_of_sub_size;
1134         --mpctx->sub_counts[SUB_SOURCE_SUBS];
1135         if (mpctx->set_of_sub_size > 0)
1136             subdata = set_of_subtitles[mpctx->set_of_sub_pos = 0];
1137     } else if (mpctx->set_of_sub_size > 0 && subdata != NULL) { // *subdata was changed
1138         set_of_subtitles[mpctx->set_of_sub_pos] = subdata;
1139     } else if (mpctx->set_of_sub_size <= 0 && subdata != NULL) { // *subdata was added
1140         set_of_subtitles[mpctx->set_of_sub_pos = mpctx->set_of_sub_size] = subdata;
1141         ++mpctx->set_of_sub_size;
1142         ++mpctx->sub_counts[SUB_SOURCE_SUBS];
1143     }
1144 }
1145 
1146 /**
1147  * @brief Append a formatted string.
1148  * @param buf buffer to print into
1149  * @param pos position of terminating 0 in buf
1150  * @param len maximum number of characters in buf, not including terminating 0
1151  * @param format printf format string
1152  */
saddf(char * buf,unsigned * pos,int len,const char * format,...)1153 static void saddf(char *buf, unsigned *pos, int len, const char *format, ...)
1154 {
1155     va_list va;
1156     va_start(va, format);
1157     *pos += vsnprintf(&buf[*pos], len - *pos, format, va);
1158     va_end(va);
1159     if (*pos >= len) {
1160         buf[len] = 0;
1161         *pos     = len;
1162     }
1163 }
1164 
1165 /**
1166  * @brief Append time in the hh:mm:ss.f format.
1167  * @param buf buffer to print into
1168  * @param pos position of terminating 0 in buf
1169  * @param len maximum number of characters in buf, not including terminating 0
1170  * @param time time value to convert/append
1171  */
sadd_hhmmssf(char * buf,unsigned * pos,int len,float time)1172 static void sadd_hhmmssf(char *buf, unsigned *pos, int len, float time)
1173 {
1174     int64_t tenths = 10 * time;
1175     int f1 = tenths % 10;
1176     int ss = (tenths / 10) % 60;
1177     int mm = (tenths / 600) % 60;
1178     int hh = tenths / 36000;
1179     if (time <= 0) {
1180         saddf(buf, pos, len, "unknown");
1181         return;
1182     }
1183     if (hh > 0)
1184         saddf(buf, pos, len, "%2d:", hh);
1185     if (hh > 0 || mm > 0)
1186         saddf(buf, pos, len, "%02d:", mm);
1187     saddf(buf, pos, len, "%02d.%1d", ss, f1);
1188 }
1189 
1190 /**
1191  * @brief Print the status line.
1192  * @param a_pos audio position
1193  * @param a_v A-V desynchronization
1194  * @param corr amount out A-V synchronization
1195  */
print_status(float a_pos,float a_v,float corr)1196 static void print_status(float a_pos, float a_v, float corr)
1197 {
1198     sh_video_t *const sh_video = mpctx->sh_video;
1199     int width;
1200     char *line;
1201     unsigned pos = 0;
1202     get_screen_size();
1203     if (screen_width > 0)
1204         width = screen_width;
1205     else
1206         width = 80;
1207 #if defined(__MINGW32__) || defined(__CYGWIN__) || defined(__OS2__)
1208     /* Windows command line is broken (MinGW's rxvt works, but we
1209      * should not depend on that). */
1210     width--;
1211 #endif
1212     line = malloc(width + 1); // one additional char for the terminating null
1213 
1214     // Audio time
1215     if (mpctx->sh_audio) {
1216         saddf(line, &pos, width, "A:%6.1f ", a_pos);
1217         if (!sh_video) {
1218             float len = demuxer_get_time_length(mpctx->demuxer);
1219             saddf(line, &pos, width, "(");
1220             sadd_hhmmssf(line, &pos, width, a_pos);
1221             saddf(line, &pos, width, ") of %.1f (", len);
1222             sadd_hhmmssf(line, &pos, width, len);
1223             saddf(line, &pos, width, ") ");
1224         }
1225     }
1226 
1227     // Video time
1228     if (sh_video)
1229         saddf(line, &pos, width, "V:%6.1f ", sh_video->pts);
1230 
1231     // A-V sync
1232     if (mpctx->sh_audio && sh_video)
1233         saddf(line, &pos, width, "A-V:%7.3f ct:%7.3f ", a_v, corr);
1234 
1235     // Video stats
1236     if (sh_video)
1237         saddf(line, &pos, width, "%3d/%3d ",
1238               (int)sh_video->num_frames,
1239               (int)sh_video->num_frames_decoded);
1240 
1241     // CPU usage
1242     if (sh_video) {
1243         if (sh_video->timer > 0.5)
1244             saddf(line, &pos, width, "%2d%% %2d%% %4.1f%% ",
1245                   (int)(100.0 * video_time_usage * playback_speed / (double)sh_video->timer),
1246                   (int)(100.0 * vout_time_usage * playback_speed / (double)sh_video->timer),
1247                   (100.0 * audio_time_usage * playback_speed / (double)sh_video->timer));
1248         else
1249             saddf(line, &pos, width, "??%% ??%% ??,?%% ");
1250     } else if (mpctx->sh_audio) {
1251         if (mpctx->delay > 0.5)
1252             saddf(line, &pos, width, "%4.1f%% ",
1253                   100.0 * audio_time_usage / (double)mpctx->delay);
1254         else
1255             saddf(line, &pos, width, "??,?%% ");
1256     }
1257 
1258     // VO stats
1259     if (sh_video)
1260         saddf(line, &pos, width, "%d %d ", drop_frame_cnt, output_quality);
1261 
1262 #ifdef CONFIG_STREAM_CACHE
1263     // cache stats
1264     if (stream_cache_size > 0)
1265         saddf(line, &pos, width, "%d%% ", cache_fill_status(mpctx->stream));
1266 #endif
1267 
1268     // other
1269     if (playback_speed != 1)
1270         saddf(line, &pos, width, "%4.2fx ", playback_speed);
1271 
1272     // end
1273     if (erase_to_end_of_line) {
1274         line[pos] = 0;
1275         mp_msg(MSGT_STATUSLINE, MSGL_STATUS, "%s%s\r", line, erase_to_end_of_line);
1276     } else {
1277         memset(&line[pos], ' ', width - pos);
1278         line[width] = 0;
1279         mp_msg(MSGT_STATUSLINE, MSGL_STATUS, "%s\r", line);
1280     }
1281     free(line);
1282 }
1283 
stream_dump_progress_start(void)1284 static void stream_dump_progress_start(void)
1285 {
1286     stream_dump_start_time = stream_dump_last_print_time = GetTimerMS();
1287 }
1288 
stream_dump_progress(uint64_t len,stream_t * stream)1289 static void stream_dump_progress(uint64_t len, stream_t *stream)
1290 {
1291     unsigned t = GetTimerMS();
1292     uint64_t start = stream->start_pos;
1293     uint64_t end   = stream->end_pos;
1294     uint64_t pos   = stream->pos;
1295 
1296     stream_dump_count += len;
1297     if (t - stream_dump_last_print_time - 1000 > UINT_MAX / 2)
1298         return;
1299     stream_dump_last_print_time = t;
1300     /* TODO: pretty print sizes; ETA */
1301     if (end > start && pos >= start && pos <= end) {
1302         mp_msg(MSGT_STATUSLINE, MSGL_STATUS, MSGTR_DumpBytesWrittenPercent,
1303                stream_dump_count, 100.0 * (pos - start) / (end - start));
1304     } else {
1305         mp_msg(MSGT_STATUSLINE, MSGL_STATUS, MSGTR_DumpBytesWritten,
1306                stream_dump_count);
1307     }
1308 }
1309 
stream_dump_progress_end(void)1310 static void stream_dump_progress_end(void)
1311 {
1312     mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_DumpBytesWrittenTo,
1313            stream_dump_count, stream_dump_name);
1314 }
1315 
1316 /**
1317  * @brief Build a chain of audio filters that converts the input format.
1318  * to the ao's format, taking into account the current playback_speed.
1319  * @param sh_audio describes the requested input format of the chain.
1320  * @param ao_data describes the requested output format of the chain.
1321  */
build_afilter_chain(sh_audio_t * sh_audio,ao_data_t * ao_data)1322 static int build_afilter_chain(sh_audio_t *sh_audio, ao_data_t *ao_data)
1323 {
1324     int new_srate;
1325     int result;
1326     if (!sh_audio) {
1327         mpctx->mixer.afilter = NULL;
1328         return 0;
1329     }
1330     if (af_control_any_rev(sh_audio->afilter,
1331                            AF_CONTROL_PLAYBACK_SPEED | AF_CONTROL_SET,
1332                            &playback_speed)) {
1333         new_srate = sh_audio->samplerate;
1334     } else {
1335         new_srate = sh_audio->samplerate * playback_speed;
1336         if (new_srate != ao_data->samplerate) {
1337             // limits are taken from libaf/af_resample.c
1338             if (new_srate < 8000)
1339                 new_srate = 8000;
1340             if (new_srate > 192000)
1341                 new_srate = 192000;
1342             playback_speed = (float)new_srate / (float)sh_audio->samplerate;
1343         }
1344     }
1345     result = init_audio_filters(sh_audio, new_srate,
1346                                 &ao_data->samplerate, &ao_data->channels, &ao_data->format);
1347     mpctx->mixer.afilter = sh_audio->afilter;
1348     return result;
1349 }
1350 
1351 typedef struct mp_osd_msg mp_osd_msg_t;
1352 struct mp_osd_msg {
1353     mp_osd_msg_t *prev; ///< Previous message on the stack
1354     char msg[128];      ///< Message text
1355     int id, level, started;
1356     unsigned time;      ///< Display duration in ms
1357 };
1358 
1359 static mp_osd_msg_t *osd_msg_stack; ///< OSD message stack
1360 
1361 /**
1362  * @brief Add a message on the OSD message stack.
1363  *
1364  * If a message with the same id is already present in the stack
1365  * it is pulled on top of the stack, otherwise a new message is created.
1366  */
set_osd_msg(int id,int level,int time,const char * fmt,...)1367 void set_osd_msg(int id, int level, int time, const char *fmt, ...)
1368 {
1369     mp_osd_msg_t *msg, *last = NULL;
1370     va_list va;
1371     int r;
1372 
1373     // look if the id is already in the stack
1374     for (msg = osd_msg_stack; msg && msg->id != id;
1375          last = msg, msg = msg->prev) ;
1376     // not found: alloc it
1377     if (!msg) {
1378         msg           = calloc(1, sizeof(mp_osd_msg_t));
1379         msg->prev     = osd_msg_stack;
1380         osd_msg_stack = msg;
1381     } else if (last) { // found, but it's not on top of the stack
1382         last->prev    = msg->prev;
1383         msg->prev     = osd_msg_stack;
1384         osd_msg_stack = msg;
1385     }
1386     // write the msg
1387     va_start(va, fmt);
1388     r = vsnprintf(msg->msg, 128, fmt, va);
1389     va_end(va);
1390     if (r >= 128)
1391         msg->msg[127] = 0;
1392     // set id and time
1393     msg->id    = id;
1394     msg->level = level;
1395     msg->time  = time;
1396 }
1397 
1398 /**
1399  * @brief Remove a message from the OSD stack.
1400  *
1401  * This function can be used to get rid of a message right away.
1402  */
rm_osd_msg(int id)1403 void rm_osd_msg(int id)
1404 {
1405     mp_osd_msg_t *msg, *last = NULL;
1406 
1407     // Search for the msg
1408     for (msg = osd_msg_stack; msg && msg->id != id;
1409          last = msg, msg = msg->prev) ;
1410     if (!msg)
1411         return;
1412 
1413     // Detach it from the stack and free it
1414     if (last)
1415         last->prev = msg->prev;
1416     else
1417         osd_msg_stack = msg->prev;
1418     free(msg);
1419 }
1420 
1421 /**
1422  * @brief Remove all messages from the OSD stack.
1423  */
clear_osd_msgs(void)1424 static void clear_osd_msgs(void)
1425 {
1426     mp_osd_msg_t *msg = osd_msg_stack, *prev = NULL;
1427     while (msg) {
1428         prev = msg->prev;
1429         free(msg);
1430         msg = prev;
1431     }
1432     osd_msg_stack = NULL;
1433 }
1434 
1435 /**
1436  * @brief Get the current message from the OSD stack.
1437  *
1438  * This function decrements the message timer and destroys the old ones.
1439  * The message that should be displayed is returned (if any).
1440  */
get_osd_msg(void)1441 static mp_osd_msg_t *get_osd_msg(void)
1442 {
1443     mp_osd_msg_t *msg, *prev, *last = NULL;
1444     static unsigned last_update;
1445     unsigned now = GetTimerMS();
1446     unsigned diff;
1447     char hidden_dec_done = 0;
1448 
1449     if (osd_visible) {
1450         // 36000000 means max timed visibility is 1 hour into the future, if
1451         // the difference is greater assume it's wrapped around from below 0
1452         if (osd_visible - now > 36000000) {
1453             osd_visible = 0;
1454             vo_osd_progbar_type = -1; // disable
1455             vo_osd_changed(OSDTYPE_PROGBAR);
1456             if (mpctx->osd_function != OSD_PAUSE)
1457                 mpctx->osd_function = OSD_PLAY;
1458         }
1459     }
1460 
1461     if (!last_update)
1462         last_update = now;
1463     diff = now >= last_update ? now - last_update : 0;
1464 
1465     last_update = now;
1466 
1467     // Look for the first message in the stack with high enough level.
1468     for (msg = osd_msg_stack; msg; last = msg, msg = prev) {
1469         prev = msg->prev;
1470         if (msg->level > osd_level && hidden_dec_done)
1471             continue;
1472         // The message has a high enough level or it is the first hidden one
1473         // in both cases we decrement the timer or kill it.
1474         if (!msg->started || msg->time > diff) {
1475             if (msg->started)
1476                 msg->time -= diff;
1477             else
1478                 msg->started = 1;
1479             // display it
1480             if (msg->level <= osd_level)
1481                 return msg;
1482             hidden_dec_done = 1;
1483             continue;
1484         }
1485         // kill the message
1486         free(msg);
1487         if (last) {
1488             last->prev = prev;
1489             msg = last;
1490         } else {
1491             osd_msg_stack = prev;
1492             msg = NULL;
1493         }
1494     }
1495     // Nothing found
1496     return NULL;
1497 }
1498 
1499 /**
1500  * @brief Display the OSD bar.
1501  *
1502  * Display the OSD bar or fall back on a simple message.
1503  */
set_osd_bar(int type,const char * name,double min,double max,double val)1504 void set_osd_bar(int type, const char *name, double min, double max, double val)
1505 {
1506     if (osd_level < 1)
1507         return;
1508 
1509     if (mpctx->sh_video) {
1510         osd_visible = (GetTimerMS() + osd_duration) | 1;
1511         vo_osd_progbar_type  = type;
1512         vo_osd_progbar_value = 256 * (val - min) / (max - min);
1513         vo_osd_changed(OSDTYPE_PROGBAR);
1514         return;
1515     }
1516 
1517     set_osd_msg(OSD_MSG_BAR, 1, osd_duration, "%s: %d %%",
1518                 name, ROUND(100 * (val - min) / (max - min)));
1519 }
1520 
1521 /**
1522  * @brief Display text subtitles on the OSD.
1523  */
set_osd_subtitle(subtitle * subs)1524 void set_osd_subtitle(subtitle *subs)
1525 {
1526     int i;
1527     vo_sub = subs;
1528     vo_osd_changed(OSDTYPE_SUBTITLE);
1529     if (!mpctx->sh_video) {
1530         // reverse order, since newest set_osd_msg is displayed first
1531         for (i = SUB_MAX_TEXT - 1; i >= 0; i--) {
1532             if (!subs || i >= subs->lines || !subs->text[i])
1533                 rm_osd_msg(OSD_MSG_SUB_BASE + i);
1534             else {
1535                 // HACK: currently display time for each sub line except the last is set to 2 seconds.
1536                 int display_time = i == subs->lines - 1 ? 180000 : 2000;
1537                 set_osd_msg(OSD_MSG_SUB_BASE + i, 1, display_time, "%s", subs->text[i]);
1538             }
1539         }
1540     }
1541 }
1542 
1543 /**
1544  * @brief Update the OSD message line.
1545  *
1546  * This function displays the current message on the vo OSD or on the term.
1547  * If the stack is empty and the OSD level is high enough the timer
1548  * is displayed (only on the vo OSD).
1549  */
update_osd_msg(void)1550 static void update_osd_msg(void)
1551 {
1552     mp_osd_msg_t *msg;
1553     static char osd_text[128] = "";
1554     static char osd_text_timer[128];
1555 
1556     // we need some mem for vo_osd_text
1557     vo_osd_text = (unsigned char *)osd_text;
1558 
1559     // Look if we have a msg
1560     if ((msg = get_osd_msg())) {
1561         if (strcmp(osd_text, msg->msg)) {
1562             strncpy((char *)osd_text, msg->msg, 127);
1563             if (mpctx->sh_video)
1564                 vo_osd_changed(OSDTYPE_OSD);
1565             else if (term_osd)
1566                 mp_msg(MSGT_CPLAYER, MSGL_STATUS, "%s%s\n", term_osd_esc, msg->msg);
1567         }
1568         return;
1569     }
1570 
1571     if (mpctx->sh_video) {
1572         // fallback on the timer
1573         if (osd_level >= 2) {
1574             int len = demuxer_get_time_length(mpctx->demuxer);
1575             int percentage = -1;
1576             char percentage_text[10];
1577             char fractions_text[4];
1578             double pts = demuxer_get_current_time(mpctx->demuxer);
1579             int pts_seconds = pts;
1580 
1581             if (mpctx->osd_show_percentage)
1582                 percentage = demuxer_get_percent_pos(mpctx->demuxer);
1583 
1584             if (percentage >= 0)
1585                 snprintf(percentage_text, 9, " (%d%%)", percentage);
1586             else
1587                 percentage_text[0] = 0;
1588 
1589             if (osd_fractions == 1) {
1590                 // print fractions as sub-second timestamp
1591                 snprintf(fractions_text, sizeof(fractions_text), ".%02d",
1592                          (int)((pts - pts_seconds) * 100) % 100);
1593             } else if (osd_fractions == 2) {
1594                 // print fractions by estimating the frame count within the
1595                 // second
1596 
1597                 // rounding or cutting off numbers after the decimal point
1598                 // causes problems because of float's precision and movies,
1599                 // whose first frame is not exactly at timestamp 0. Therefore,
1600                 // we add 0.2 and cut off at the decimal point, which proved
1601                 // as good heuristic
1602                 snprintf(fractions_text, sizeof(fractions_text), ".%02d",
1603                          (int)((pts - pts_seconds) *
1604                                mpctx->sh_video->fps + 0.2));
1605             } else {
1606                 // do not print fractions
1607                 fractions_text[0] = 0;
1608             }
1609 
1610             if (osd_level == 3)
1611                 snprintf(osd_text_timer, 63,
1612                          "%c %02d:%02d:%02d%s / %02d:%02d:%02d%s",
1613                          mpctx->osd_function, pts_seconds / 3600, (pts_seconds / 60) % 60, pts_seconds % 60,
1614                          fractions_text, len / 3600, (len / 60) % 60, len % 60,
1615                          percentage_text);
1616             else
1617                 snprintf(osd_text_timer, 63, "%c %02d:%02d:%02d%s%s",
1618                          mpctx->osd_function, pts_seconds / 3600, (pts_seconds / 60) % 60,
1619                          pts_seconds % 60, fractions_text, percentage_text);
1620         } else
1621             osd_text_timer[0] = 0;
1622 
1623         // always decrement the percentage timer
1624         if (mpctx->osd_show_percentage)
1625             mpctx->osd_show_percentage--;
1626 
1627         if (strcmp(osd_text, osd_text_timer)) {
1628             strncpy(osd_text, osd_text_timer, 63);
1629             vo_osd_changed(OSDTYPE_OSD);
1630         }
1631         return;
1632     }
1633 
1634     // Clear the term osd line
1635     if (term_osd && osd_text[0]) {
1636         osd_text[0] = 0;
1637         printf("%s\n", term_osd_esc);
1638     }
1639 }
1640 
reinit_audio_chain(void)1641 void reinit_audio_chain(void)
1642 {
1643     if (!mpctx->sh_audio)
1644         return;
1645     if (!(initialized_flags & INITIALIZED_ACODEC)) {
1646         current_module = "init_audio_codec";
1647         mp_msg(MSGT_CPLAYER, MSGL_INFO, "==========================================================================\n");
1648         if (!init_best_audio_codec(mpctx->sh_audio, audio_codec_list, audio_fm_list))
1649             goto init_error;
1650         initialized_flags |= INITIALIZED_ACODEC;
1651         mp_msg(MSGT_CPLAYER, MSGL_INFO, "==========================================================================\n");
1652     }
1653 
1654     if (!(initialized_flags & INITIALIZED_AO)) {
1655         current_module     = "af_preinit";
1656         ao_data.samplerate = force_srate;
1657         ao_data.channels   = 0;
1658         ao_data.format     = audio_output_format;
1659         // first init to detect best values
1660         if (!init_audio_filters(mpctx->sh_audio,  // preliminary init
1661                                 // input:
1662                                 mpctx->sh_audio->samplerate,
1663                                 // output:
1664                                 &ao_data.samplerate, &ao_data.channels, &ao_data.format)) {
1665             mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_AudioFilterChainPreinitError);
1666             exit_player(EXIT_ERROR);
1667         }
1668         current_module   = "ao2_init";
1669         mpctx->audio_out = init_best_audio_out(audio_driver_list,
1670                                                0, // plugin flag
1671                                                ao_data.samplerate,
1672                                                ao_data.channels,
1673                                                ao_data.format, 0);
1674         if (!mpctx->audio_out) {
1675             mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_CannotInitAO);
1676             goto init_error;
1677         }
1678         initialized_flags |= INITIALIZED_AO;
1679         mp_msg(MSGT_CPLAYER, MSGL_INFO, "AO: [%s] %dHz %dch %s (%d bytes per sample)\n",
1680                mpctx->audio_out->info->short_name,
1681                ao_data.samplerate, ao_data.channels,
1682                af_fmt2str_short(ao_data.format),
1683                af_fmt2bits(ao_data.format) / 8);
1684         mp_msg(MSGT_CPLAYER, MSGL_V, "AO: Description: %s\nAO: Author: %s\n",
1685                mpctx->audio_out->info->name, mpctx->audio_out->info->author);
1686         if (strlen(mpctx->audio_out->info->comment) > 0)
1687             mp_msg(MSGT_CPLAYER, MSGL_V, "AO: Comment: %s\n", mpctx->audio_out->info->comment);
1688     }
1689 
1690     // init audio filters:
1691     current_module = "af_init";
1692     if (!build_afilter_chain(mpctx->sh_audio, &ao_data)) {
1693         mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_NoMatchingFilter);
1694         goto init_error;
1695     }
1696     mpctx->mixer.audio_out = mpctx->audio_out;
1697     mpctx->mixer.volstep   = volstep;
1698     return;
1699 
1700 init_error:
1701     uninit_player(INITIALIZED_ACODEC | INITIALIZED_AO); // close codec and possibly AO
1702     mpctx->sh_audio    = mpctx->d_audio->sh = NULL; // -> nosound
1703     mpctx->d_audio->id = -2;
1704 }
1705 
1706 // Return pts value corresponding to the end point of audio written to the
1707 // ao so far.
written_audio_pts(sh_audio_t * sh_audio,demux_stream_t * d_audio)1708 static double written_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio)
1709 {
1710     double buffered_output;
1711     // first calculate the end pts of audio that has been output by decoder
1712     double a_pts = calc_a_pts(sh_audio, d_audio);
1713     // Now a_pts hopefully holds the pts for end of audio from decoder.
1714     // Substract data in buffers between decoder and audio out.
1715 
1716     // Decoded but not filtered
1717     a_pts -= sh_audio->a_buffer_len / (double)sh_audio->o_bps;
1718 
1719     // Data buffered in audio filters, measured in bytes of "missing" output
1720     buffered_output = af_calc_delay(sh_audio->afilter);
1721 
1722     // Data that was ready for ao but was buffered because ao didn't fully
1723     // accept everything to internal buffers yet
1724     buffered_output += sh_audio->a_out_buffer_len;
1725 
1726     // Filters divide audio length by playback_speed, so multiply by it
1727     // to get the length in original units without speedup or slowdown
1728     a_pts -= buffered_output * playback_speed / ao_data.bps;
1729 
1730     return a_pts;
1731 }
1732 
1733 // Return pts value corresponding to currently playing audio.
playing_audio_pts(sh_audio_t * sh_audio,demux_stream_t * d_audio,const ao_functions_t * audio_out)1734 double playing_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio,
1735                          const ao_functions_t *audio_out)
1736 {
1737     return written_audio_pts(sh_audio, d_audio) - playback_speed *
1738            audio_out->get_delay();
1739 }
1740 
is_at_end(MPContext * mpctx,m_time_size_t * end_at,double pts)1741 static int is_at_end(MPContext *mpctx, m_time_size_t *end_at, double pts)
1742 {
1743     switch (end_at->type) {
1744     case END_AT_TIME: return pts != MP_NOPTS_VALUE && end_at->pos <= pts;
1745     case END_AT_SIZE: return end_at->pos <= stream_tell(mpctx->stream);
1746     }
1747     return 0;
1748 }
1749 
check_framedrop(double frame_time)1750 static int check_framedrop(double frame_time)
1751 {
1752     // check for frame-drop:
1753     current_module = "check_framedrop";
1754     if (mpctx->sh_audio && !mpctx->d_audio->eof) {
1755         static int dropped_frames;
1756         float delay = playback_speed * mpctx->audio_out->get_delay();
1757         float d     = delay - mpctx->delay;
1758         ++total_frame_cnt;
1759         // we should avoid dropping too many frames in sequence unless we
1760         // are too late. and we allow 100ms A-V delay here:
1761         if (d < -dropped_frames * frame_time - 0.100 &&
1762             mpctx->osd_function != OSD_PAUSE) {
1763             ++drop_frame_cnt;
1764             ++dropped_frames;
1765             return frame_dropping;
1766         } else
1767             dropped_frames = 0;
1768     }
1769     return 0;
1770 }
1771 
generate_video_frame(sh_video_t * sh_video,demux_stream_t * d_video)1772 static int generate_video_frame(sh_video_t *sh_video, demux_stream_t *d_video)
1773 {
1774     unsigned char *start;
1775     int in_size;
1776     int hit_eof = 0;
1777     double pts;
1778     double endpts;
1779 
1780     while (1) {
1781         int drop_frame = 0;
1782         void *decoded_frame;
1783         current_module = "decode video";
1784         // XXX Time used in this call is not counted in any performance
1785         // timer now, OSD is not updated correctly for filter-added frames
1786         if (vf_output_queued_frame(sh_video->vfilter))
1787             break;
1788         current_module = "video_read_frame";
1789         in_size = ds_get_packet_pts_endpts(d_video, &start, &pts, &endpts);
1790         if (in_size < 0) {
1791             // try to extract last frames in case of decoder lag
1792             in_size = 0;
1793             start   = NULL;
1794             pts     = MP_NOPTS_VALUE;
1795             hit_eof = 1;
1796         } else
1797 	    drop_frame = check_framedrop(sh_video->frametime);
1798         if (in_size > max_framesize)
1799             max_framesize = in_size;
1800         current_module = "decode video";
1801         decoded_frame  = decode_video(sh_video, start, in_size, drop_frame, pts, endpts, NULL);
1802         if (decoded_frame) {
1803             update_subtitles(sh_video, sh_video->pts, mpctx->d_sub, 0);
1804             update_teletext(sh_video, mpctx->demuxer, 0);
1805             update_osd_msg();
1806             current_module = "filter video";
1807             if (filter_video(sh_video, decoded_frame, sh_video->pts, sh_video->endpts))
1808                 break;
1809         } else if (drop_frame)
1810             return -1;
1811         if (hit_eof)
1812             return 0;
1813     }
1814     return 1;
1815 }
1816 
1817 #ifdef HAVE_RTC
1818 int rtc_fd = -1;
1819 #endif
1820 
timing_sleep(float time_frame)1821 static float timing_sleep(float time_frame)
1822 {
1823 #ifdef HAVE_RTC
1824     if (rtc_fd >= 0) {
1825         // -------- RTC -----------
1826         current_module = "sleep_rtc";
1827         while (time_frame > 0.000) {
1828             unsigned long rtc_ts;
1829             if (read(rtc_fd, &rtc_ts, sizeof(rtc_ts)) != sizeof(rtc_ts))
1830                 mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_LinuxRTCReadError, strerror(errno));
1831             time_frame -= GetRelativeTime();
1832         }
1833     } else
1834 #endif
1835     {
1836         // assume kernel HZ=100 for softsleep, works with larger HZ but with
1837         // unnecessarily high CPU usage
1838         float margin = softsleep ? 0.011 : 0;
1839         current_module = "sleep_timer";
1840         while (time_frame > margin) {
1841             usec_sleep(1000000 * (time_frame - margin));
1842             time_frame -= GetRelativeTime();
1843         }
1844         if (softsleep) {
1845             current_module = "sleep_soft";
1846             if (time_frame < 0)
1847                 mp_msg(MSGT_AVSYNC, MSGL_WARN, MSGTR_SoftsleepUnderflow);
1848             while (time_frame > 0)
1849                 time_frame -= GetRelativeTime();  // burn the CPU
1850         }
1851     }
1852     return time_frame;
1853 }
1854 
select_subtitle(MPContext * mpctx)1855 static int select_subtitle(MPContext *mpctx)
1856 {
1857     // find the best sub to use
1858     int id;
1859     int found = 0;
1860     mpctx->global_sub_pos = -1; // no subs by default
1861     if (vobsub_id >= 0) {
1862         // if user asks for a vobsub id, use that first.
1863         id    = vobsub_id;
1864         found = mp_property_do("sub_vob", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK;
1865     }
1866 
1867     if (!found && dvdsub_id >= 0) {
1868         // if user asks for a dvd sub id, use that next.
1869         id    = dvdsub_id;
1870         found = mp_property_do("sub_demux", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK;
1871     }
1872 
1873     if (!found) {
1874         // if there are text subs to use, use those.  (autosubs come last here)
1875         id    = 0;
1876         found = mp_property_do("sub_file", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK;
1877     }
1878 
1879     if (!found && dvdsub_id == -1) {
1880         // finally select subs by language and container hints
1881         if (dvdsub_id == -1 && dvdsub_lang)
1882             dvdsub_id = demuxer_sub_track_by_lang(mpctx->demuxer, dvdsub_lang);
1883         if (dvdsub_id == -1)
1884             dvdsub_id = demuxer_default_sub_track(mpctx->demuxer);
1885         if (dvdsub_id >= 0) {
1886             id    = dvdsub_id;
1887             found = mp_property_do("sub_demux", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK;
1888         }
1889     }
1890     return found;
1891 }
1892 
1893 #ifdef CONFIG_DVDNAV
1894 #ifndef FF_B_TYPE
1895 #define FF_B_TYPE 3
1896 #endif
1897 /**
1898  * @brief Store decoded video image.
1899  */
mp_dvdnav_copy_mpi(mp_image_t * to_mpi,mp_image_t * from_mpi)1900 static mp_image_t *mp_dvdnav_copy_mpi(mp_image_t *to_mpi,
1901                                       mp_image_t *from_mpi)
1902 {
1903     mp_image_t *mpi;
1904 
1905     // do not store B-frames
1906     if (from_mpi->pict_type == FF_B_TYPE)
1907         return to_mpi;
1908 
1909     if (to_mpi &&
1910         to_mpi->w == from_mpi->w &&
1911         to_mpi->h == from_mpi->h &&
1912         to_mpi->imgfmt == from_mpi->imgfmt)
1913         mpi = to_mpi;
1914     else {
1915         if (to_mpi)
1916             free_mp_image(to_mpi);
1917         if (from_mpi->w == 0 || from_mpi->h == 0)
1918             return NULL;
1919         mpi = alloc_mpi(from_mpi->w, from_mpi->h, from_mpi->imgfmt);
1920     }
1921 
1922     copy_mpi(mpi, from_mpi);
1923     return mpi;
1924 }
1925 
mp_dvdnav_reset_stream(MPContext * ctx)1926 static void mp_dvdnav_reset_stream(MPContext *ctx)
1927 {
1928     if (ctx->sh_video) {
1929         // clear video pts
1930         ctx->d_video->pts       = 0.0f;
1931         ctx->sh_video->pts      = 0.0f;
1932         ctx->sh_video->i_pts    = 0.0f;
1933         ctx->sh_video->last_pts = 0.0f;
1934         ctx->sh_video->num_buffered_pts   = 0;
1935         ctx->sh_video->num_frames         = 0;
1936         ctx->sh_video->num_frames_decoded = 0;
1937         ctx->sh_video->timer = 0.0f;
1938         ctx->sh_video->stream_delay = 0.0f;
1939         ctx->sh_video->timer     = 0;
1940         ctx->demuxer->stream_pts = MP_NOPTS_VALUE;
1941     }
1942 
1943     // This is necessary to make video start in sync after
1944     // a still frame. But do not discard pending audio packets,
1945     // that causes issues since this code is also called on
1946     // title changes (which is possibly a bug in itself *sigh*),
1947     // and thus cause tiny audio skips.
1948     ctx->delay   = -audio_delay;
1949     audio_delay = 0.0f;
1950     mpctx->sub_counts[SUB_SOURCE_DEMUX] = mp_dvdnav_number_of_subs(mpctx->stream);
1951     if (dvdsub_lang && dvdsub_id == dvdsub_lang_id) {
1952         dvdsub_lang_id = mp_dvdnav_sid_from_lang(ctx->stream, dvdsub_lang);
1953         if (dvdsub_lang_id != dvdsub_id) {
1954             dvdsub_id = dvdsub_lang_id;
1955             select_subtitle(ctx);
1956         }
1957     }
1958 
1959     // clear all EOF related flags
1960     ctx->d_video->eof = ctx->d_audio->eof = ctx->stream->eof = 0;
1961 }
1962 
1963 /**
1964  * @brief Restore last decoded DVDNAV (still frame).
1965  */
mp_dvdnav_restore_smpi(int * in_size,unsigned char ** start,mp_image_t * decoded_frame)1966 static mp_image_t *mp_dvdnav_restore_smpi(int *in_size,
1967                                           unsigned char **start,
1968                                           mp_image_t *decoded_frame)
1969 {
1970     if (mpctx->stream->type != STREAMTYPE_DVDNAV)
1971         return decoded_frame;
1972 
1973     // a change occurred in dvdnav stream
1974     if (mp_dvdnav_cell_has_changed(mpctx->stream, 0)) {
1975         mp_dvdnav_read_wait(mpctx->stream, 1, 1);
1976         mp_dvdnav_context_free(mpctx);
1977         mp_dvdnav_reset_stream(mpctx);
1978         mp_dvdnav_read_wait(mpctx->stream, 0, 1);
1979         mp_dvdnav_cell_has_changed(mpctx->stream, 1);
1980     }
1981 
1982     if (*in_size < 0) {
1983         float len;
1984 
1985         // display still frame, if any
1986         if (mpctx->nav_smpi && !mpctx->nav_buffer)
1987             decoded_frame = mpctx->nav_smpi;
1988 
1989         // increment video frame: continue playing after still frame
1990         len = demuxer_get_time_length(mpctx->demuxer);
1991         if (mpctx->sh_video->pts >= len &&
1992             mpctx->sh_video->pts > 0.0 && len > 0.0) {
1993             mp_dvdnav_skip_still(mpctx->stream);
1994             mp_dvdnav_skip_wait(mpctx->stream);
1995         }
1996         mpctx->sh_video->pts += 1 / mpctx->sh_video->fps;
1997 
1998         if (mpctx->nav_buffer) {
1999             *start   = mpctx->nav_start;
2000             *in_size = mpctx->nav_in_size;
2001             if (mpctx->nav_start)
2002                 memcpy(*start, mpctx->nav_buffer, mpctx->nav_in_size);
2003         }
2004     }
2005 
2006     return decoded_frame;
2007 }
2008 
2009 /**
2010  * @brief Save last decoded DVDNAV (still frame).
2011  */
mp_dvdnav_save_smpi(int in_size,unsigned char * start,mp_image_t * decoded_frame)2012 static void mp_dvdnav_save_smpi(int in_size,
2013                                 unsigned char *start,
2014                                 mp_image_t *decoded_frame)
2015 {
2016     if (mpctx->stream->type != STREAMTYPE_DVDNAV)
2017         return;
2018 
2019     free(mpctx->nav_buffer);
2020     mpctx->nav_buffer  = NULL;
2021     mpctx->nav_start   = NULL;
2022     mpctx->nav_in_size = -1;
2023 
2024     if (in_size > 0)
2025         mpctx->nav_buffer = malloc(in_size);
2026     if (mpctx->nav_buffer) {
2027         mpctx->nav_start   = start;
2028         mpctx->nav_in_size = in_size;
2029         memcpy(mpctx->nav_buffer, start, in_size);
2030     }
2031 
2032     if (decoded_frame && mpctx->nav_smpi != decoded_frame)
2033         mpctx->nav_smpi = mp_dvdnav_copy_mpi(mpctx->nav_smpi, decoded_frame);
2034 }
2035 
2036 #endif /* CONFIG_DVDNAV */
2037 
adjust_sync_and_print_status(int between_frames,float timing_error)2038 static void adjust_sync_and_print_status(int between_frames, float timing_error)
2039 {
2040     current_module = "av_sync";
2041 
2042     if (mpctx->sh_audio) {
2043         double a_pts, v_pts;
2044 
2045         if (autosync)
2046             /*
2047              * If autosync is enabled, the value for delay must be calculated
2048              * a bit differently.  It is set only to the difference between
2049              * the audio and video timers.  Any attempt to include the real
2050              * or corrected delay causes the pts_correction code below to
2051              * try to correct for the changes in delay which autosync is
2052              * trying to measure.  This keeps the two from competing, but still
2053              * allows the code to correct for PTS drift *only*.  (Using a delay
2054              * value here, even a "corrected" one, would be incompatible with
2055              * autosync mode.)
2056              */
2057             a_pts = written_audio_pts(mpctx->sh_audio, mpctx->d_audio) - mpctx->delay;
2058         else
2059             a_pts = playing_audio_pts(mpctx->sh_audio, mpctx->d_audio, mpctx->audio_out);
2060 
2061         v_pts = mpctx->sh_video->pts;
2062 
2063         {
2064             static int drop_message;
2065             double AV_delay = a_pts - audio_delay - v_pts;
2066             double x;
2067             // not a good idea to do A-V correction with with bogus values
2068             if (a_pts == MP_NOPTS_VALUE || v_pts == MP_NOPTS_VALUE)
2069                 AV_delay = 0;
2070             if (AV_delay > 0.5 && drop_frame_cnt > 50 && drop_message == 0) {
2071                 ++drop_message;
2072                 mp_msg(MSGT_AVSYNC, MSGL_WARN, MSGTR_SystemTooSlow);
2073             }
2074             if (AV_delay > 0.5 && correct_pts && mpctx->delay < -audio_delay - 30) {
2075                 // This case means that we are supposed to stop video for a long
2076                 // time, even though audio is already ahead.
2077                 // This happens e.g. when initial audio pts is 10000, video
2078                 // starts at 0 but suddenly jumps to match audio.
2079                 // This is common in ogg streams.
2080                 // Only check for -correct-pts since this case does not cause
2081                 // issues with -nocorrect-pts.
2082                 mp_msg(MSGT_AVSYNC, MSGL_WARN, "Timing looks severely broken, resetting\n");
2083                 AV_delay = 0;
2084                 timing_error = 0;
2085                 mpctx->delay = -audio_delay;
2086             }
2087             if (autosync)
2088                 x = AV_delay * 0.1f;
2089             else
2090                 /* Do not correct target time for the next frame if this frame
2091                  * was late not because of wrong target time but because the
2092                  * target time could not be met */
2093                 x = (AV_delay + timing_error * playback_speed) * 0.1f;
2094             if (x < -max_pts_correction)
2095                 x = -max_pts_correction;
2096             else if (x > max_pts_correction)
2097                 x = max_pts_correction;
2098             if (default_max_pts_correction >= 0)
2099                 max_pts_correction = default_max_pts_correction;
2100             else
2101                 max_pts_correction = mpctx->sh_video->frametime * 0.10;  // +-10% of time
2102             if (!between_frames) {
2103                 mpctx->delay += x;
2104                 c_total      += x;
2105             }
2106             if (!quiet)
2107                 print_status(a_pts - audio_delay, AV_delay, c_total);
2108         }
2109     } else {
2110         // No audio:
2111 
2112         if (!quiet)
2113             print_status(0, 0, 0);
2114     }
2115 }
2116 
fill_audio_out_buffers(void)2117 static int fill_audio_out_buffers(void)
2118 {
2119     unsigned int t;
2120     double tt;
2121     int playsize;
2122     int playflags = 0;
2123     int audio_eof = 0;
2124     int bytes_to_write;
2125     int timeout = 0;
2126     sh_audio_t *const sh_audio = mpctx->sh_audio;
2127 
2128     current_module = "play_audio";
2129 
2130     while (1) {
2131         int sleep_time;
2132         // all the current uses of ao_data.pts seem to be in aos that handle
2133         // sync completely wrong; there should be no need to use ao_data.pts
2134         // in get_space()
2135         ao_data.pts    = ((mpctx->sh_video ? mpctx->sh_video->timer : 0) + mpctx->delay) * 90000.0;
2136         bytes_to_write = mpctx->audio_out->get_space();
2137         if (mpctx->sh_video || bytes_to_write >= ao_data.outburst)
2138             break;
2139         if (timeout++ > 10) {
2140             mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_AudioDeviceStuck);
2141             break;
2142         }
2143 
2144         // handle audio-only case:
2145         // this is where mplayer sleeps during audio-only playback
2146         // to avoid 100% CPU use
2147         sleep_time = (ao_data.outburst - bytes_to_write) * 1000 / ao_data.bps;
2148         if (sleep_time < 10)
2149             sleep_time = 10;                  // limit to 100 wakeups per second
2150         usec_sleep(sleep_time * 1000);
2151     }
2152 
2153     while (bytes_to_write) {
2154         int res;
2155         playsize = bytes_to_write;
2156         if (playsize > MAX_OUTBURST)
2157             playsize = MAX_OUTBURST;
2158         bytes_to_write -= playsize;
2159 
2160         // Fill buffer if needed:
2161         current_module = "decode_audio";
2162         t = GetTimer();
2163         if (!sh_audio->a_buffer_format_change) {
2164             res = mp_decode_audio(sh_audio, playsize);
2165             sh_audio->a_buffer_format_change = res == -2;
2166         }
2167         if (!sh_audio->a_buffer_format_change && res < 0) // EOF or error
2168             if (mpctx->d_audio->eof) {
2169                 audio_eof = 1;
2170                 if (sh_audio->a_out_buffer_len == 0)
2171                     return 0;
2172             }
2173         t  = GetTimer() - t;
2174         tt = t * 0.000001f;
2175         audio_time_usage += tt;
2176         if (playsize > sh_audio->a_out_buffer_len) {
2177             playsize = sh_audio->a_out_buffer_len;
2178             if (audio_eof || sh_audio->a_buffer_format_change)
2179                 playflags |= AOPLAY_FINAL_CHUNK;
2180         }
2181         if (!playsize)
2182             break;
2183 
2184         // play audio:
2185         current_module = "play_audio";
2186 
2187         // Is this pts value actually useful for the aos that access it?
2188         // They're obviously badly broken in the way they handle av sync;
2189         // would not having access to this make them more broken?
2190         ao_data.pts = ((mpctx->sh_video ? mpctx->sh_video->timer : 0) + mpctx->delay) * 90000.0;
2191         playsize    = mpctx->audio_out->play(sh_audio->a_out_buffer, playsize, playflags);
2192 
2193         if (playsize > 0) {
2194             sh_audio->a_out_buffer_len -= playsize;
2195             memmove(sh_audio->a_out_buffer, &sh_audio->a_out_buffer[playsize],
2196                     sh_audio->a_out_buffer_len);
2197             mpctx->delay += playback_speed * playsize / (double)ao_data.bps;
2198         } else if ((sh_audio->a_buffer_format_change || audio_eof) &&
2199                    mpctx->audio_out->get_delay() < .04) {
2200             // Sanity check to avoid hanging in case current ao doesn't output
2201             // partial chunks and doesn't check for AOPLAY_FINAL_CHUNK
2202             mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_AudioOutputTruncated);
2203             sh_audio->a_out_buffer_len = 0;
2204         }
2205     }
2206     if (sh_audio->a_buffer_format_change && !sh_audio->a_out_buffer_len) {
2207         uninit_player(INITIALIZED_AO);
2208         af_uninit(sh_audio->afilter);
2209         free(sh_audio->afilter);
2210         sh_audio->afilter = NULL;
2211         reinit_audio_chain();
2212         sh_audio->a_buffer_format_change = 0;
2213     }
2214     return 1;
2215 }
2216 
handle_udp_master(double time)2217 static void handle_udp_master(double time)
2218 {
2219 #ifdef CONFIG_NETWORKING
2220     if (udp_master) {
2221         char current_time[256];
2222         snprintf(current_time, sizeof(current_time), "%f", time);
2223         send_udp(udp_ip, udp_port, current_time);
2224     }
2225 #endif /* CONFIG_NETWORKING */
2226 }
2227 
sleep_until_update(float * time_frame,float * aq_sleep_time)2228 static int sleep_until_update(float *time_frame, float *aq_sleep_time)
2229 {
2230     int frame_time_remaining = 0;
2231     current_module = "calc_sleep_time";
2232 
2233 #ifdef CONFIG_NETWORKING
2234     if (udp_slave) {
2235         int udp_master_exited = udp_slave_sync(mpctx);
2236         if (udp_master_exited > 0) {
2237             mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_MasterQuit);
2238             exit_player(EXIT_QUIT);
2239         } else if (udp_master_exited == 0)
2240             return 0;
2241     }
2242 #endif /* CONFIG_NETWORKING */
2243 
2244     *time_frame -= GetRelativeTime(); // reset timer
2245 
2246     if (mpctx->sh_audio && !mpctx->d_audio->eof) {
2247         float delay = mpctx->audio_out->get_delay();
2248         mp_dbg(MSGT_AVSYNC, MSGL_DBG2, "delay=%f\n", delay);
2249 
2250         if (autosync) {
2251             /*
2252              * Adjust this raw delay value by calculating the expected
2253              * delay for this frame and generating a new value which is
2254              * weighted between the two.  The higher autosync is, the
2255              * closer to the delay value gets to that which "-nosound"
2256              * would have used, and the longer it will take for A/V
2257              * sync to settle at the right value (but it eventually will.)
2258              * This settling time is very short for values below 100.
2259              */
2260             float predicted  = mpctx->delay / playback_speed + *time_frame;
2261             float difference = delay - predicted;
2262             delay = predicted + difference / (float)autosync;
2263         }
2264 
2265         *time_frame = delay - mpctx->delay / playback_speed;
2266 
2267         // delay = amount of audio buffered in soundcard/driver
2268         if (delay > 0.25)
2269             delay = 0.25;
2270         else if (delay < 0.10)
2271             delay = 0.10;
2272         if (*time_frame > delay * 0.6) {
2273             // sleep time too big - may cause audio drops (buffer underrun)
2274             frame_time_remaining = 1;
2275             *time_frame = delay * 0.5;
2276         }
2277     } else {
2278         // If we're lagging more than 200 ms behind the right playback rate,
2279         // don't try to "catch up".
2280         // If benchmark is set always output frames as fast as possible
2281         // without sleeping.
2282         if (*time_frame < -0.2 || benchmark)
2283             *time_frame = 0;
2284     }
2285 
2286     *aq_sleep_time += *time_frame;
2287 
2288     //============================== SLEEP: ===================================
2289 
2290     // flag 256 means: libvo driver does its timing (dvb card)
2291     if (!(vo_flags & 256)) {
2292         if (*time_frame > 0.3) {
2293             // Avoid sleeping too long without reacting to user input
2294             usec_sleep(200000);
2295             *time_frame -= GetRelativeTime();
2296             frame_time_remaining = 1;
2297 	} else if (*time_frame > 0.001)
2298             *time_frame = timing_sleep(*time_frame);
2299     }
2300 
2301     handle_udp_master(mpctx->sh_video->pts);
2302 
2303     return frame_time_remaining;
2304 }
2305 
reinit_video_chain(void)2306 int reinit_video_chain(void)
2307 {
2308     sh_video_t *const sh_video = mpctx->sh_video;
2309     double ar = -1.0;
2310     if (!video_read_properties(mpctx->sh_video)) {
2311         mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_CannotReadVideoProperties);
2312         goto err_out;
2313     } else {
2314         mp_msg(MSGT_CPLAYER, MSGL_V, MSGTR_FilefmtFourccSizeFpsFtime,
2315                mpctx->demuxer->file_format, mpctx->sh_video->format, mpctx->sh_video->disp_w, mpctx->sh_video->disp_h,
2316                mpctx->sh_video->fps, mpctx->sh_video->frametime
2317                );
2318 
2319         /* need to set fps here for output encoders to pick it up in their init */
2320         if (force_fps) {
2321             mpctx->sh_video->fps       = force_fps;
2322             mpctx->sh_video->frametime = 1.0f / mpctx->sh_video->fps;
2323         }
2324         vo_fps = mpctx->sh_video->fps;
2325 
2326         if (!mpctx->sh_video->fps && !force_fps && !correct_pts) {
2327             mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_FPSnotspecified);
2328             correct_pts = 1;
2329         }
2330     }
2331     //================== Init VIDEO (codec & libvo) ==========================
2332     if (!fixed_vo || !(initialized_flags & INITIALIZED_VO)) {
2333         current_module = "preinit_libvo";
2334 
2335         //shouldn't we set dvideo->id=-2 when we fail?
2336         vo_config_count = 0;
2337         //if((mpctx->video_out->preinit(vo_subdevice))!=0){
2338         if (!(mpctx->video_out = init_best_video_out(video_driver_list))) {
2339             mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_ErrorInitializingVODevice);
2340             goto err_out;
2341         }
2342         initialized_flags |= INITIALIZED_VO;
2343     }
2344 
2345     if (stream_control(mpctx->demuxer->stream, STREAM_CTRL_GET_ASPECT_RATIO, &ar) != STREAM_UNSUPPORTED)
2346         mpctx->sh_video->stream_aspect = ar;
2347     current_module = "init_video_filters";
2348     {
2349         char *vf_arg[] = { "_oldargs_", (char *)mpctx->video_out, NULL };
2350         sh_video->vfilter = vf_open_filter(NULL, "vo", vf_arg);
2351     }
2352 #ifdef CONFIG_MENU
2353     if (use_menu) {
2354         char *vf_arg[] = { "_oldargs_", menu_root, NULL };
2355         vf_menu = vf_open_plugin(libmenu_vfs, sh_video->vfilter, "menu", vf_arg);
2356         if (!vf_menu) {
2357             mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_CantOpenLibmenuFilterWithThisRootMenu, menu_root);
2358             use_menu = 0;
2359         }
2360     }
2361     if (vf_menu)
2362         sh_video->vfilter = vf_menu;
2363 #endif
2364 
2365 #ifdef CONFIG_ASS
2366     if (ass_enabled) {
2367         int i;
2368         int insert = 1;
2369         if (vf_settings)
2370             for (i = 0; vf_settings[i].name; ++i)
2371                 if (strcmp(vf_settings[i].name, "ass") == 0) {
2372                     insert = 0;
2373                     break;
2374                 }
2375         if (insert) {
2376             char *vf_arg[] = { "auto", "1", NULL };
2377             vf_instance_t *vf_ass = vf_open_filter(sh_video->vfilter, "ass", vf_arg);
2378             if (vf_ass)
2379                 sh_video->vfilter = vf_ass;
2380             else
2381                 mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_ASSCannotAddVideoFilter);
2382         }
2383     }
2384 #endif
2385 
2386     sh_video->vfilter = append_filters(sh_video->vfilter);
2387     eosd_init(sh_video->vfilter);
2388 
2389 #ifdef CONFIG_ASS
2390     if (ass_enabled)
2391         eosd_ass_init(ass_library);
2392 #endif
2393 
2394     current_module = "init_video_codec";
2395 
2396     mp_msg(MSGT_CPLAYER, MSGL_INFO, "==========================================================================\n");
2397     init_best_video_codec(sh_video, video_codec_list, video_fm_list);
2398     mp_msg(MSGT_CPLAYER, MSGL_INFO, "==========================================================================\n");
2399 
2400     if (!sh_video->initialized) {
2401         if (!fixed_vo)
2402             uninit_player(INITIALIZED_VO);
2403         goto err_out;
2404     }
2405 
2406     initialized_flags |= INITIALIZED_VCODEC;
2407 
2408     if (sh_video->codec)
2409         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_CODEC=%s\n", codec_idx2str(sh_video->codec->name_idx));
2410 
2411     sh_video->last_pts = MP_NOPTS_VALUE;
2412     sh_video->num_buffered_pts = 0;
2413     sh_video->next_frame_time  = 0;
2414 
2415     if (auto_quality > 0) {
2416         // Auto quality option enabled
2417         output_quality = get_video_quality_max(sh_video);
2418         if (auto_quality > output_quality)
2419             auto_quality = output_quality;
2420         else
2421             output_quality = auto_quality;
2422         mp_msg(MSGT_CPLAYER, MSGL_V, "AutoQ: setting quality to %d.\n", output_quality);
2423         set_video_quality(sh_video, output_quality);
2424     }
2425 
2426     // ========== Init display (sh_video->disp_w*sh_video->disp_h/out_fmt) ============
2427 
2428     current_module = "init_vo";
2429 
2430     return 1;
2431 
2432 err_out:
2433     mpctx->sh_video = mpctx->sh_video->ds = NULL;
2434     return 0;
2435 }
2436 
advance_timer(double amount)2437 static void advance_timer(double amount)
2438 {
2439     mpctx->sh_video->timer += amount;
2440     if (mpctx->sh_audio)
2441         mpctx->delay -= amount;
2442 }
2443 
update_video(int * blit_frame)2444 static double update_video(int *blit_frame)
2445 {
2446     sh_video_t *const sh_video = mpctx->sh_video;
2447     //--------------------  Decode a frame: -----------------------
2448     double frame_time;
2449     *blit_frame = 0; // Don't blit if we hit EOF
2450     if (!correct_pts) {
2451         unsigned char *start = NULL;
2452         void *decoded_frame  = NULL;
2453         int drop_frame       = 0;
2454         int in_size;
2455         int full_frame;
2456 
2457         do {
2458             int flush;
2459             current_module = "video_read_frame";
2460             frame_time     = sh_video->next_frame_time;
2461             in_size = video_read_frame(sh_video, &sh_video->next_frame_time,
2462                                        &start, force_fps);
2463 #ifdef CONFIG_DVDNAV
2464             // wait, still frame or EOF
2465             if (mpctx->stream->type == STREAMTYPE_DVDNAV && in_size < 0) {
2466                 if (mp_dvdnav_is_eof(mpctx->stream))
2467                     return -1;
2468                 if (mpctx->d_video)
2469                     mpctx->d_video->eof = 0;
2470                 if (mpctx->d_audio)
2471                     mpctx->d_audio->eof = 0;
2472                 mpctx->stream->eof = 0;
2473             }
2474 #endif
2475             flush = in_size < 0 && mpctx->d_video->eof;
2476             if (flush) {
2477                 start = NULL;
2478                 in_size = 0;
2479             }
2480             if (mpctx->stream->type != STREAMTYPE_DVDNAV && in_size < 0)
2481                 return -1;
2482             if (in_size > max_framesize)
2483                 max_framesize = in_size;  // stats
2484             drop_frame     = check_framedrop(frame_time);
2485             current_module = "decode_video";
2486 #ifdef CONFIG_DVDNAV
2487             full_frame    = 1;
2488             decoded_frame = mp_dvdnav_restore_smpi(&in_size, &start, decoded_frame);
2489 #endif
2490             // still frame has been reached, no need to decode
2491             if ((in_size > 0 || flush) && !decoded_frame)
2492             decoded_frame = decode_video(sh_video, start, in_size, drop_frame,
2493                                          sh_video->pts, sh_video->endpts, &full_frame);
2494 
2495             if (flush && !decoded_frame)
2496                 return -1;
2497 
2498             if (full_frame) {
2499                 advance_timer(frame_time);
2500                 // video_read_frame can change fps (e.g. for ASF video)
2501                 vo_fps = sh_video->fps;
2502                 update_subtitles(sh_video, sh_video->pts, mpctx->d_sub, 0);
2503                 update_teletext(sh_video, mpctx->demuxer, 0);
2504                 update_osd_msg();
2505             }
2506 #ifdef CONFIG_DVDNAV
2507             // save back last still frame for future display
2508             mp_dvdnav_save_smpi(in_size, start, decoded_frame);
2509 #endif
2510         } while (!full_frame);
2511 
2512         current_module = "filter_video";
2513         *blit_frame    = (decoded_frame && filter_video(sh_video, decoded_frame,
2514                                                         sh_video->pts, sh_video->endpts));
2515     } else {
2516         int res = generate_video_frame(sh_video, mpctx->d_video);
2517         if (!res)
2518             return -1;
2519         ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter,
2520                                                       VFCTRL_GET_PTS, &sh_video->pts);
2521         ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter,
2522                                                       VFCTRL_GET_ENDPTS, &sh_video->endpts);
2523         if (sh_video->pts == MP_NOPTS_VALUE) {
2524             mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_PtsAfterFiltersMissing);
2525             sh_video->pts = sh_video->last_pts;
2526         }
2527         if (sh_video->last_pts == MP_NOPTS_VALUE)
2528             sh_video->last_pts = sh_video->pts;
2529         else if (sh_video->last_pts > sh_video->pts) {
2530             // make a guess whether this is some kind of discontinuity
2531             // we should jump along with or some wrong timestamps we
2532             // should replace instead
2533             if (sh_video->pts < sh_video->last_pts - 20 * sh_video->frametime)
2534                 sh_video->last_pts = sh_video->pts;
2535             else
2536                 sh_video->pts = sh_video->last_pts + sh_video->frametime;
2537             mp_msg(MSGT_CPLAYER, MSGL_V, "pts value < previous\n");
2538         }
2539         frame_time = sh_video->pts - sh_video->last_pts;
2540         // The first frame should be displayed directly,
2541         // all others should get a default frame_time
2542         if (!frame_time && mpctx->startup_decode_retry == 0)
2543             frame_time = sh_video->frametime;
2544         sh_video->last_pts = sh_video->pts;
2545         advance_timer(frame_time);
2546         *blit_frame = res > 0;
2547     }
2548     return frame_time;
2549 }
2550 
pause_loop(void)2551 static void pause_loop(void)
2552 {
2553     mp_cmd_t *cmd;
2554 #ifdef CONFIG_STREAM_CACHE
2555     int old_cache_fill = stream_cache_size > 0 ? cache_fill_status(mpctx->stream) : 0;
2556 #endif
2557     if (!quiet) {
2558         if (term_osd && !mpctx->sh_video) {
2559             set_osd_msg(OSD_MSG_PAUSE, 1, 0, MSGTR_Paused);
2560             update_osd_msg();
2561         } else
2562             mp_msg(MSGT_CPLAYER, MSGL_STATUS, "\n"MSGTR_Paused "\r");
2563         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_PAUSED\n");
2564     }
2565 #ifdef CONFIG_GUI
2566     if (use_gui)
2567         gui(GUI_SET_STATE, (void *)GUI_PAUSE);
2568 #endif
2569     if (mpctx->video_out && mpctx->sh_video && vo_config_count)
2570         mpctx->video_out->control(VOCTRL_PAUSE, NULL);
2571 
2572     if (mpctx->audio_out && mpctx->sh_audio)
2573         mpctx->audio_out->pause();  // pause audio, keep data if possible
2574 
2575     while ((cmd = mp_input_get_cmd(20, 1, 1)) == NULL || cmd->pausing == 4) {
2576         if (cmd) {
2577             cmd = mp_input_get_cmd(0, 1, 0);
2578             run_command(mpctx, cmd);
2579             mp_cmd_free(cmd);
2580             continue;
2581         }
2582         if (mpctx->sh_video && mpctx->video_out && vo_config_count)
2583             mpctx->video_out->check_events();
2584 #ifdef CONFIG_GUI
2585         if (use_gui) {
2586             gui(GUI_REDRAW, 0);
2587             if (guiInfo.Playing != GUI_PAUSE || (rel_seek_secs || abs_seek_pos))
2588                 break;
2589         }
2590 #endif
2591 #ifdef CONFIG_MENU
2592         if (vf_menu)
2593             vf_menu_pause_update(vf_menu);
2594 #endif
2595 #ifdef CONFIG_STREAM_CACHE
2596         if (!quiet && stream_cache_size > 0) {
2597             int new_cache_fill = cache_fill_status(mpctx->stream);
2598             if (new_cache_fill != old_cache_fill) {
2599                 if (term_osd && !mpctx->sh_video) {
2600                     set_osd_msg(OSD_MSG_PAUSE, 1, 0, MSGTR_Paused " %d%%",
2601                                 new_cache_fill);
2602                     update_osd_msg();
2603                 } else
2604                     mp_msg(MSGT_CPLAYER, MSGL_STATUS, MSGTR_Paused " %d%%\r",
2605                            new_cache_fill);
2606                 old_cache_fill = new_cache_fill;
2607             }
2608         }
2609 #endif
2610         if (mpctx->sh_video)
2611             handle_udp_master(mpctx->sh_video->pts);
2612         usec_sleep(20000);
2613     }
2614     if (cmd && cmd->id == MP_CMD_PAUSE) {
2615         cmd = mp_input_get_cmd(0, 1, 0);
2616         mp_cmd_free(cmd);
2617     }
2618     mpctx->osd_function = OSD_PLAY;
2619     if (mpctx->audio_out && mpctx->sh_audio) {
2620         if (mpctx->eof) // do not play remaining audio if we e.g.  switch to the next file
2621             mpctx->audio_out->reset();
2622         else
2623             mpctx->audio_out->resume();  // resume audio
2624     }
2625     if (mpctx->video_out && mpctx->sh_video && vo_config_count)
2626         mpctx->video_out->control(VOCTRL_RESUME, NULL);  // resume video
2627     (void)GetRelativeTime(); // ignore time that passed during pause
2628 #ifdef CONFIG_GUI
2629     if (use_gui) {
2630         if (guiInfo.Playing == GUI_STOP)
2631             mpctx->eof = 1;
2632         else
2633             gui(GUI_SET_STATE, (void *)GUI_PLAY);
2634     }
2635 #endif
2636 }
2637 
edl_loadfile(void)2638 static void edl_loadfile(void)
2639 {
2640     if (edl_filename) {
2641         if (edl_records) {
2642             free_edl(edl_records);
2643             edl_needs_reset = 1;
2644         }
2645         next_edl_record = edl_records = edl_parse_file();
2646     }
2647 }
2648 
2649 // Execute EDL command for the current position if one exists
edl_update(MPContext * mpctx)2650 static void edl_update(MPContext *mpctx)
2651 {
2652     double pts;
2653     if (!edl_records)
2654         return;
2655 
2656     if (!mpctx->sh_video) {
2657         mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_EdlNOsh_video);
2658         free_edl(edl_records);
2659         next_edl_record = NULL;
2660         edl_records     = NULL;
2661         return;
2662     }
2663 
2664     pts = mpctx->sh_video->pts;
2665     // This indicates that we need to reset next EDL record according
2666     // to new PTS due to seek or other condition
2667     if (edl_needs_reset) {
2668         edl_needs_reset  = 0;
2669         mpctx->edl_muted = 0;
2670         next_edl_record  = edl_records;
2671 
2672         // Find next record, also skip immediately if we are already
2673         // inside any record
2674         while (next_edl_record) {
2675             if (next_edl_record->start_sec > pts)
2676                 break;
2677             if (next_edl_record->stop_sec >= pts) {
2678                 if (edl_backward) {
2679                     mpctx->osd_function = OSD_REW;
2680                     edl_decision  = 1;
2681                     abs_seek_pos  = 0;
2682                     rel_seek_secs = -(pts -
2683                                       next_edl_record->start_sec +
2684                                       edl_backward_delay);
2685                     mp_msg(MSGT_CPLAYER, MSGL_DBG4, "EDL_SKIP: pts [%f], "
2686                                                     "offset [%f], start [%f], stop [%f], length [%f]\n",
2687                            pts, rel_seek_secs,
2688                            next_edl_record->start_sec, next_edl_record->stop_sec,
2689                            next_edl_record->length_sec);
2690                     return;
2691                 }
2692                 break;
2693             }
2694 
2695             if (next_edl_record->action == EDL_MUTE)
2696                 mpctx->edl_muted = !mpctx->edl_muted;
2697 
2698             next_edl_record = next_edl_record->next;
2699         }
2700         if ((mpctx->user_muted | mpctx->edl_muted) != mpctx->mixer.muted)
2701             mixer_mute(&mpctx->mixer);
2702     }
2703 
2704     if (next_edl_record &&
2705         pts >= next_edl_record->start_sec) {
2706         if (next_edl_record->action == EDL_SKIP) {
2707             mpctx->osd_function = OSD_FFW;
2708             edl_decision  = 1;
2709             abs_seek_pos  = 0;
2710             rel_seek_secs = next_edl_record->stop_sec - pts;
2711             mp_msg(MSGT_CPLAYER, MSGL_DBG4, "EDL_SKIP: pts [%f], offset [%f], "
2712                                             "start [%f], stop [%f], length [%f]\n",
2713                    pts, rel_seek_secs,
2714                    next_edl_record->start_sec, next_edl_record->stop_sec,
2715                    next_edl_record->length_sec);
2716         } else if (next_edl_record->action == EDL_MUTE) {
2717             mpctx->edl_muted = !mpctx->edl_muted;
2718             if ((mpctx->user_muted | mpctx->edl_muted) != mpctx->mixer.muted)
2719                 mixer_mute(&mpctx->mixer);
2720             mp_msg(MSGT_CPLAYER, MSGL_DBG4, "EDL_MUTE: [%f]\n",
2721                    next_edl_record->start_sec);
2722         }
2723         next_edl_record = next_edl_record->next;
2724     }
2725 }
2726 
2727 // style & SEEK_ABSOLUTE == 0 means seek relative to current position, == 1 means absolute
2728 // style & SEEK_FACTOR   == 0 means amount in seconds, == 2 means fraction of file length
2729 // return -1 if seek failed (non-seekable stream?), 0 otherwise
seek(MPContext * mpctx,double amount,int style)2730 static int seek(MPContext *mpctx, double amount, int style)
2731 {
2732     current_module = "seek";
2733     if (demux_seek(mpctx->demuxer, amount, audio_delay, style) == 0)
2734         return -1;
2735 
2736     mpctx->startup_decode_retry = DEFAULT_STARTUP_DECODE_RETRY;
2737     if (mpctx->sh_video) {
2738         current_module = "seek_video_reset";
2739         if (vo_config_count)
2740             mpctx->video_out->control(VOCTRL_RESET, NULL);
2741         mpctx->num_buffered_frames = 0;
2742         mpctx->delay           = 0;
2743         mpctx->time_frame      = 0;
2744         // Not all demuxers set d_video->pts during seek, so this value
2745         // (which is used by at least vobsub and edl code below) may
2746         // be completely wrong (probably 0).
2747         mpctx->sh_video->pts = mpctx->d_video->pts;
2748         update_subtitles(mpctx->sh_video, mpctx->sh_video->pts, mpctx->d_sub, 1);
2749         update_teletext(mpctx->sh_video, mpctx->demuxer, 1);
2750     }
2751 
2752     if (mpctx->sh_audio) {
2753         current_module = "seek_audio_reset";
2754         mpctx->audio_out->reset(); // stop audio, throwing away buffered data
2755         if (!mpctx->sh_video)
2756             update_subtitles(NULL, mpctx->sh_audio->pts, mpctx->d_sub, 1);
2757     }
2758 
2759     if (vo_vobsub && mpctx->sh_video) {
2760         current_module = "seek_vobsub_reset";
2761         vobsub_seek(vo_vobsub, mpctx->sh_video->pts);
2762     }
2763 
2764 #ifdef CONFIG_ASS
2765     if (ass_enabled && mpctx->d_sub && mpctx->d_sub->sh && ((sh_sub_t *)mpctx->d_sub->sh)->ass_track)
2766         ass_flush_events(((sh_sub_t *)mpctx->d_sub->sh)->ass_track);
2767 #endif
2768 
2769     if (edl_records) {
2770         edl_needs_reset = 1;
2771         edl_backward    = amount < 0;
2772     }
2773 
2774     c_total = 0;
2775     max_pts_correction = 0.1;
2776     audio_time_usage   = 0;
2777     video_time_usage   = 0;
2778     vout_time_usage    = 0;
2779     drop_frame_cnt     = 0;
2780 
2781     current_module = NULL;
2782     return 0;
2783 }
2784 
2785 /* This preprocessor directive is a hack to generate a mplayer-nomain.o object
2786  * file for some tools to link against. */
2787 #ifndef DISABLE_MAIN
main(int argc,char * argv[])2788 int main(int argc, char *argv[])
2789 {
2790     int opt_exit = 0; // Flag indicating whether MPlayer should exit without playing anything.
2791     int profile_config_loaded;
2792     int i;
2793 
2794     common_preinit(&argc, &argv);
2795 
2796     // Create the config context and register the options
2797     mconfig = m_config_new();
2798     m_config_register_options(mconfig, mplayer_opts);
2799     m_config_register_options(mconfig, common_opts);
2800     mp_input_register_options(mconfig);
2801 
2802     // Preparse the command line
2803     m_config_preparse_command_line(mconfig, argc, argv);
2804 
2805 #ifdef CONFIG_TV
2806     stream_tv_defaults.immediate = 1;
2807 #endif
2808 
2809     if (argc > 1 && argv[1] &&
2810         (!strcmp(argv[1], "-gui") || !strcmp(argv[1], "-nogui"))) {
2811         use_gui = !strcmp(argv[1], "-gui");
2812     } else if (argv[0] && strstr(mp_basename(argv[0]), gmplayer)) {
2813         use_gui = 1;
2814     }
2815 
2816     parse_cfgfiles(mconfig);
2817 
2818 #ifdef CONFIG_GUI
2819     if (use_gui) {
2820         initialized_flags |= INITIALIZED_GUI;
2821         cfg_read();
2822     }
2823 #endif
2824 
2825     mpctx->playtree = m_config_parse_mp_command_line(mconfig, argc, argv);
2826     if (mpctx->playtree == NULL) {
2827         // parse error
2828         opt_exit = 1;
2829     } else
2830         mpctx->playtree = play_tree_cleanup(mpctx->playtree);
2831 
2832     mpctx->playtree_iter = mpctx->playtree ? play_tree_iter_new(mpctx->playtree, mconfig) : NULL;
2833     if (mpctx->playtree_iter && play_tree_iter_step(mpctx->playtree_iter, 0, 0) != PLAY_TREE_ITER_ENTRY) {
2834         play_tree_iter_free(mpctx->playtree_iter);
2835         mpctx->playtree_iter = NULL;
2836     }
2837 
2838     filename = mpctx->playtree_iter ? play_tree_iter_get_file(mpctx->playtree_iter, 1) : NULL;
2839 
2840     print_version("MPlayer");
2841 #if (defined(__MINGW32__) || defined(__CYGWIN__)) && defined(CONFIG_GUI)
2842     void *runningmplayer = FindWindow("MPlayer GUI for Windows", "MPlayer for Windows");
2843     if (runningmplayer && filename && use_gui) {
2844         COPYDATASTRUCT csData;
2845         char file[MAX_PATH];
2846         char *filepart = filename;
2847         if (GetFullPathName(filename, MAX_PATH, file, &filepart)) {
2848             csData.dwData = 0;
2849             csData.cbData = strlen(file) * 2;
2850             csData.lpData = file;
2851             SendMessage(runningmplayer, WM_COPYDATA, (WPARAM)runningmplayer, (LPARAM)&csData);
2852         }
2853     }
2854 #endif
2855     if (!common_init())
2856         exit_player_with_rc(EXIT_NONE, 0);
2857 
2858 #ifndef CONFIG_GUI
2859     if (use_gui) {
2860         mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_NoGui);
2861         use_gui = 0;
2862     }
2863 #else
2864 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
2865     if (use_gui && !vo_init()) {
2866         mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_GuiNeedsX);
2867         use_gui = 0;
2868     }
2869 #endif
2870     if (use_gui && mpctx->playtree_iter) {
2871         char cwd[PATH_MAX + 2];
2872         // Free playtree_iter as it's not used in connection with the GUI.
2873         play_tree_iter_free(mpctx->playtree_iter);
2874         mpctx->playtree_iter = NULL;
2875 
2876         if (getcwd(cwd, PATH_MAX) != (char *)NULL) {
2877             strcat(cwd, "/");
2878             // Prefix relative paths with current working directory
2879             play_tree_add_bpf(mpctx->playtree, cwd);
2880         }
2881         // Import initital playtree into GUI.
2882         guiPlaylist(GUI_PLAYLIST_INIT, mpctx->playtree, mconfig, enqueue);
2883     }
2884 #endif /* CONFIG_GUI */
2885 
2886     if (video_driver_list && strcmp(video_driver_list[0], "help") == 0) {
2887         list_video_out();
2888         opt_exit = 1;
2889     }
2890 
2891     if (audio_driver_list && strcmp(audio_driver_list[0], "help") == 0) {
2892         list_audio_out();
2893         opt_exit = 1;
2894     }
2895 
2896     if (audio_codec_list && strcmp(audio_codec_list[0], "help") == 0) {
2897         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_AvailableAudioCodecs);
2898         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_CODECS\n");
2899         list_codecs(1);
2900         mp_msg(MSGT_FIXME, MSGL_FIXME, "\n");
2901         opt_exit = 1;
2902     }
2903     if (video_codec_list && strcmp(video_codec_list[0], "help") == 0) {
2904         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_AvailableVideoCodecs);
2905         mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_CODECS\n");
2906         list_codecs(0);
2907         mp_msg(MSGT_FIXME, MSGL_FIXME, "\n");
2908         opt_exit = 1;
2909     }
2910     if (video_fm_list && strcmp(video_fm_list[0], "help") == 0) {
2911         vfm_help();
2912         mp_msg(MSGT_FIXME, MSGL_FIXME, "\n");
2913         opt_exit = 1;
2914     }
2915     if (audio_fm_list && strcmp(audio_fm_list[0], "help") == 0) {
2916         afm_help();
2917         mp_msg(MSGT_FIXME, MSGL_FIXME, "\n");
2918         opt_exit = 1;
2919     }
2920     if (af_cfg.list && strcmp(af_cfg.list[0], "help") == 0) {
2921         af_help();
2922         printf("\n");
2923         opt_exit = 1;
2924     }
2925 #ifdef CONFIG_X11
2926     if (vo_fstype_list && strcmp(vo_fstype_list[0], "help") == 0) {
2927         fstype_help();
2928         mp_msg(MSGT_FIXME, MSGL_FIXME, "\n");
2929         opt_exit = 1;
2930     }
2931 #endif
2932     if ((demuxer_name && strcmp(demuxer_name, "help") == 0) ||
2933         (audio_demuxer_name && strcmp(audio_demuxer_name, "help") == 0) ||
2934         (sub_demuxer_name && strcmp(sub_demuxer_name, "help") == 0)) {
2935         demuxer_help();
2936         mp_msg(MSGT_CPLAYER, MSGL_INFO, "\n");
2937         opt_exit = 1;
2938     }
2939     if (list_properties) {
2940         property_print_help();
2941         opt_exit = 1;
2942     }
2943 
2944     if (opt_exit)
2945         exit_player(EXIT_NONE);
2946 
2947     if (!filename && !player_idle_mode && !use_gui) {
2948         // no file/vcd/dvd -> show HELP:
2949         mp_msg(MSGT_CPLAYER, MSGL_INFO, help_text);
2950         exit_player_with_rc(EXIT_NONE, 0);
2951     }
2952 
2953     /* Display what configure line was used */
2954     mp_msg(MSGT_CPLAYER, MSGL_V, "Configuration: " CONFIGURATION "\n");
2955 
2956     // Many users forget to include command line in bugreports...
2957     if (mp_msg_test(MSGT_CPLAYER, MSGL_V)) {
2958         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_CommandLine);
2959         for (i = 1; i < argc; i++)
2960             mp_msg(MSGT_CPLAYER, MSGL_INFO, " '%s'", argv[i]);
2961         mp_msg(MSGT_CPLAYER, MSGL_INFO, "\n");
2962     }
2963 
2964 //------ load global data first ------
2965 
2966 #ifdef HAVE_RTC
2967     if (!nortc) {
2968         // seteuid(0); /* Can't hurt to try to get root here */
2969         if ((rtc_fd = open(rtc_device ? rtc_device : "/dev/rtc", O_RDONLY)) < 0)
2970             mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_RTCDeviceNotOpenable,
2971                    rtc_device ? rtc_device : "/dev/rtc", strerror(errno));
2972         else {
2973             unsigned long irqp = 1024; /* 512 seemed OK. 128 is jerky. */
2974 
2975             if (ioctl(rtc_fd, RTC_IRQP_SET, irqp) < 0) {
2976                 mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_LinuxRTCInitErrorIrqpSet, irqp, strerror(errno));
2977                 mp_msg(MSGT_CPLAYER, MSGL_HINT, MSGTR_IncreaseRTCMaxUserFreq, irqp);
2978                 close(rtc_fd);
2979                 rtc_fd = -1;
2980             } else if (ioctl(rtc_fd, RTC_PIE_ON, 0) < 0) {
2981                 /* variable only by the root */
2982                 mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_LinuxRTCInitErrorPieOn, strerror(errno));
2983                 close(rtc_fd);
2984                 rtc_fd = -1;
2985             } else
2986                 mp_msg(MSGT_CPLAYER, MSGL_V, "Using Linux hardware RTC timing (%ldHz).\n", irqp);
2987         }
2988     }
2989 #ifdef CONFIG_GUI
2990     // breaks DGA and SVGAlib and VESA drivers:  --A'rpi
2991     // and now ? -- Pontscho
2992     if (use_gui)
2993         setuid(getuid());           // strongly test, please check this.
2994 #endif
2995     if (rtc_fd < 0)
2996 #endif /* HAVE_RTC */
2997     mp_msg(MSGT_CPLAYER, MSGL_V, "Using %s timing\n",
2998            softsleep ? "software" : timer_name);
2999 
3000 #ifdef HAVE_TERMCAP
3001     if (!use_gui)
3002         load_termcap(NULL);           // load key-codes
3003 #endif
3004 
3005 // ========== Init keyboard FIFO (connection to libvo) ============
3006 
3007     // Init input system
3008     current_module = "init_input";
3009     mp_input_init();
3010     mp_input_add_key_fd(-1, 0, mplayer_get_key, NULL);
3011     if (slave_mode)
3012         mp_input_add_cmd_fd(0, USE_SELECT, MP_INPUT_SLAVE_CMD_FUNC, NULL);
3013     else if (!noconsolecontrols)
3014         mp_input_add_event_fd(0, getch2);
3015     // Set the libstream interrupt callback
3016     stream_set_interrupt_callback(mp_input_check_interrupt);
3017 
3018 #ifdef CONFIG_MENU
3019     if (use_menu) {
3020         if (menu_cfg && menu_init(mpctx, menu_cfg))
3021             mp_msg(MSGT_CPLAYER, MSGL_V, "Menu initialized: %s\n", menu_cfg);
3022         else {
3023             menu_cfg = get_path("menu.conf");
3024             if (menu_init(mpctx, menu_cfg))
3025                 mp_msg(MSGT_CPLAYER, MSGL_V, "Menu initialized: %s\n", menu_cfg);
3026             else {
3027                 if (menu_init(mpctx, MPLAYER_CONFDIR "/menu.conf"))
3028                     mp_msg(MSGT_CPLAYER, MSGL_V,  "Menu initialized: %s\n", MPLAYER_CONFDIR "/menu.conf");
3029                 else {
3030                     mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_MenuInitFailed);
3031                     use_menu = 0;
3032                 }
3033             }
3034         }
3035     }
3036 #endif
3037 
3038     initialized_flags |= INITIALIZED_INPUT;
3039     current_module     = NULL;
3040 
3041     // Catch signals
3042 #ifndef __MINGW32__
3043     // TODO: use newer POSIX SIG_IGN behaviour instead to
3044     // automatically handle children?
3045     signal(SIGCHLD, child_sighandler);
3046 #endif
3047 
3048 #ifdef CONFIG_CRASH_DEBUG
3049     prog_path = argv[0];
3050 #endif
3051     //========= Catch terminate signals: ================
3052     // terminate requests:
3053     signal(SIGTERM, exit_sighandler); // kill
3054     signal(SIGHUP, exit_sighandler); // kill -HUP  /  xterm closed
3055 
3056     signal(SIGINT, exit_sighandler); // Interrupt from keyboard
3057 
3058     signal(SIGQUIT, exit_sighandler); // Quit from keyboard
3059     signal(SIGPIPE, exit_sighandler); // Some window managers cause this
3060 #ifdef CONFIG_SIGHANDLER
3061     // fatal errors:
3062     signal(SIGBUS, exit_sighandler); // bus error
3063 #ifndef __WINE__                      // hack: the Wine executable will crash else
3064     signal(SIGSEGV, exit_sighandler); // segfault
3065 #endif
3066     signal(SIGILL, exit_sighandler); // illegal instruction
3067     signal(SIGFPE, exit_sighandler); // floating point exc.
3068     signal(SIGABRT, exit_sighandler); // abort()
3069 #ifdef CONFIG_CRASH_DEBUG
3070     if (crash_debug)
3071         signal(SIGTRAP, exit_sighandler);
3072 #endif
3073 #endif
3074 
3075 #ifdef CONFIG_GUI
3076     if (use_gui) {
3077         guiInit();
3078         gui(GUI_SET_CONTEXT, mpctx);
3079         gui(GUI_SET_STATE, (void *)(intptr_t)(filename ? GUI_PLAY : GUI_STOP));
3080     }
3081 #endif
3082 
3083 // ******************* Now, let's see the per-file stuff ********************
3084 
3085 play_next_file:
3086 
3087     // init global sub numbers
3088     mpctx->global_sub_size = 0;
3089     memset(mpctx->sub_counts, 0, sizeof(mpctx->sub_counts));
3090 
3091     profile_config_loaded = load_profile_config(mconfig, filename);
3092 
3093     if (video_driver_list)
3094         load_per_output_config(mconfig, PROFILE_CFG_VO, video_driver_list[0]);
3095     if (audio_driver_list)
3096         load_per_output_config(mconfig, PROFILE_CFG_AO, audio_driver_list[0]);
3097 
3098     // We must enable getch2 here to be able to interrupt network connection
3099     // or cache filling
3100     if (!noconsolecontrols && !slave_mode) {
3101         if (initialized_flags & INITIALIZED_GETCH2)
3102             mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_Getch2InitializedTwice);
3103         else
3104             getch2_enable();  // prepare stdin for hotkeys...
3105         initialized_flags |= INITIALIZED_GETCH2;
3106         mp_msg(MSGT_CPLAYER, MSGL_DBG2, "\n[[[init getch2]]]\n");
3107     }
3108 
3109 // =================== GUI idle loop (STOP state) ===========================
3110 #ifdef CONFIG_GUI
3111     if (use_gui) {
3112         mpctx->file_format = DEMUXER_TYPE_UNKNOWN;
3113         while (guiInfo.Playing != GUI_PLAY) {
3114             mp_cmd_t *cmd;
3115             usec_sleep(20000);
3116             gui(GUI_REDRAW, 0);
3117             if ((cmd = mp_input_get_cmd(0, 0, 0)) != NULL) {
3118                 if (cmd->id == MP_CMD_GUI)
3119                     gui(GUI_RUN_MESSAGE, cmd->args[0].v.s);
3120                 else
3121                     gui(GUI_RUN_COMMAND, (void *)(intptr_t)cmd->id);
3122                 mp_cmd_free(cmd);
3123             }
3124         }
3125         gui(GUI_PREPARE, 0);
3126     }
3127 #endif /* CONFIG_GUI */
3128 
3129     while (player_idle_mode && !filename) {
3130         play_tree_t *entry = NULL;
3131         mp_cmd_t *cmd;
3132         if (mpctx->video_out && vo_config_count)
3133             mpctx->video_out->control(VOCTRL_PAUSE, NULL);
3134         while (!(cmd = mp_input_get_cmd(0, 1, 0))) { // wait for command
3135             if (mpctx->video_out && vo_config_count)
3136                 mpctx->video_out->check_events();
3137             usec_sleep(20000);
3138         }
3139         switch (cmd->id) {
3140         case MP_CMD_LOADFILE:
3141             // prepare a tree entry with the new filename
3142             entry = play_tree_new();
3143             play_tree_add_file(entry, cmd->args[0].v.s);
3144             // The entry is added to the main playtree after the switch().
3145             break;
3146         case MP_CMD_LOADLIST:
3147             entry = parse_playlist_file(cmd->args[0].v.s);
3148             break;
3149         case MP_CMD_QUIT:
3150             exit_player_with_rc(EXIT_QUIT, (cmd->nargs > 0) ? cmd->args[0].v.i : 0);
3151             break;
3152         case MP_CMD_VO_FULLSCREEN:
3153         case MP_CMD_GET_PROPERTY:
3154         case MP_CMD_SET_PROPERTY:
3155         case MP_CMD_STEP_PROPERTY:
3156             run_command(mpctx, cmd);
3157             break;
3158         }
3159         mpctx->osd_function = cmd->pausing ? OSD_PAUSE : OSD_PLAY;
3160 
3161         mp_cmd_free(cmd);
3162 
3163         if (entry) { // user entered a command that gave a valid entry
3164             if (mpctx->playtree) // the playtree is always a node with one child. let's clear it
3165                 play_tree_free_list(mpctx->playtree->child, 1);
3166             else
3167                 mpctx->playtree = play_tree_new();  // .. or make a brand new playtree
3168 
3169             if (!mpctx->playtree)
3170                 continue;               // couldn't make playtree! wait for next command
3171 
3172             play_tree_set_child(mpctx->playtree, entry);
3173 
3174             /* Make iterator start at the top the of tree. */
3175             mpctx->playtree_iter = play_tree_iter_new(mpctx->playtree, mconfig);
3176             if (!mpctx->playtree_iter)
3177                 continue;
3178 
3179             // find the first real item in the tree
3180             if (play_tree_iter_step(mpctx->playtree_iter, 0, 0) != PLAY_TREE_ITER_ENTRY) {
3181                 // no items!
3182                 play_tree_iter_free(mpctx->playtree_iter);
3183                 mpctx->playtree_iter = NULL;
3184                 continue; // wait for next command
3185             }
3186             filename = play_tree_iter_get_file(mpctx->playtree_iter, 1);
3187         }
3188     }
3189 
3190     if (!profile_config_loaded) load_profile_config(mconfig, filename);
3191 //---------------------------------------------------------------------------
3192 
3193     if (mpctx->video_out && vo_config_count)
3194         mpctx->video_out->control(VOCTRL_RESUME, NULL);
3195 
3196     if (filename) {
3197         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_Playing,
3198                filename_recode(filename));
3199         if (use_filename_title && vo_wintitle == NULL)
3200             vo_wintitle = strdup(mp_basename(filename));
3201     }
3202 
3203     edl_loadfile();
3204 
3205     if (edl_output_filename) {
3206         if (edl_fd)
3207             fclose(edl_fd);
3208         if ((edl_fd = fopen(edl_output_filename, "w")) == NULL) {
3209             mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_EdlCantOpenForWrite,
3210                    filename_recode(edl_output_filename));
3211         }
3212     }
3213 
3214 //==================== Open VOB-Sub ============================
3215 
3216     current_module = "vobsub";
3217     load_vob_subtitle(filename, spudec_ifo, &vo_spudec, add_vob_subtitle);
3218     if (vo_vobsub) {
3219         initialized_flags |= INITIALIZED_VOBSUB;
3220         vobsub_set_from_lang(vo_vobsub, dvdsub_lang);
3221         mp_property_do("sub_forced_only", M_PROPERTY_SET, &forced_subs_only, mpctx);
3222 
3223         // setup global sub numbering
3224         mpctx->sub_counts[SUB_SOURCE_VOBSUB] = vobsub_get_indexes_count(vo_vobsub);
3225     }
3226 #ifdef CONFIG_ASS
3227     // must be before demuxer open, since the settings are
3228     // used in generating the ASSTrack
3229     if (ass_enabled && ass_library)
3230         ass_mp_reset_config(ass_library);
3231 #endif
3232 
3233 //============ Open & Sync STREAM --- fork cache2 ====================
3234 
3235     mpctx->stream  = NULL;
3236     mpctx->demuxer = NULL;
3237     if (mpctx->d_audio) {
3238         //free_demuxer_stream(mpctx->d_audio);
3239         mpctx->d_audio = NULL;
3240     }
3241     if (mpctx->d_video) {
3242         //free_demuxer_stream(d_video);
3243         mpctx->d_video = NULL;
3244     }
3245     mpctx->sh_audio = NULL;
3246     mpctx->sh_video = NULL;
3247 
3248     current_module = "open_stream";
3249     mpctx->stream  = open_stream(filename, 0, &mpctx->file_format);
3250     if (!mpctx->stream) { // error...
3251         mpctx->eof = libmpdemux_was_interrupted(PT_NEXT_ENTRY);
3252         goto goto_next_file;
3253     }
3254     initialized_flags |= INITIALIZED_STREAM;
3255 
3256 #ifdef CONFIG_GUI
3257     if (use_gui)
3258         gui(GUI_SET_STREAM, mpctx->stream);
3259 #endif
3260 
3261     if (mpctx->file_format == DEMUXER_TYPE_PLAYLIST) {
3262         play_tree_t *entry;
3263         // Handle playlist
3264         current_module = "handle_playlist";
3265         mp_msg(MSGT_CPLAYER, MSGL_V, "Parsing playlist %s...\n",
3266                filename_recode(filename));
3267         if (allow_playlist_parsing) {
3268             entry      = parse_playtree(mpctx->stream, use_gui);
3269             mpctx->eof = playtree_add_playlist(entry);
3270         } else {
3271             mp_msg(MSGT_CPLAYER, MSGL_ERR, "Playlist parsing disabled for security reasons. Ignoring file.\n");
3272         }
3273         goto goto_next_file;
3274     }
3275     mpctx->stream->start_pos += seek_to_byte;
3276 
3277     if (stream_dump_type == 5) {
3278         unsigned char buf[4096];
3279         int len;
3280         stream_t *os;
3281         current_module = "dumpstream";
3282         stream_reset(mpctx->stream);
3283         stream_seek(mpctx->stream, mpctx->stream->start_pos);
3284         os = open_output_stream(stream_dump_name, NULL);
3285         if (!os) {
3286             mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_CantOpenDumpfile);
3287             exit_player(EXIT_ERROR);
3288         }
3289         if (dvd_chapter > 1) {
3290             int chapter = dvd_chapter - 1;
3291             stream_control(mpctx->stream, STREAM_CTRL_SEEK_TO_CHAPTER, &chapter);
3292         }
3293         stream_dump_progress_start();
3294         while (!mpctx->stream->eof && !async_quit_request) {
3295             double pts;
3296             if (stream_control(mpctx->stream, STREAM_CTRL_GET_CURRENT_TIME, &pts) != STREAM_OK)
3297                 pts = MP_NOPTS_VALUE;
3298             if (is_at_end(mpctx, &end_at, pts))
3299                 break;
3300             len = stream_read(mpctx->stream, buf, 4096);
3301             if (len > 0) {
3302                 if (stream_write_buffer(os, buf, len) != len) {
3303                     mp_msg(MSGT_MENCODER, MSGL_FATAL, MSGTR_ErrorWritingFile, stream_dump_name);
3304                     exit_player(EXIT_ERROR);
3305                 }
3306             }
3307             stream_dump_progress(len, mpctx->stream);
3308             if (dvd_last_chapter > 0) {
3309                 int chapter = -1;
3310                 if (stream_control(mpctx->stream, STREAM_CTRL_GET_CURRENT_CHAPTER,
3311                                    &chapter) == STREAM_OK && chapter + 1 > dvd_last_chapter)
3312                     break;
3313             }
3314         }
3315         if (free_stream(os)) {
3316             mp_msg(MSGT_MENCODER, MSGL_FATAL, MSGTR_ErrorWritingFile, stream_dump_name);
3317             exit_player(EXIT_ERROR);
3318         }
3319         stream_dump_progress_end();
3320         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_CoreDumped);
3321         exit_player_with_rc(EXIT_EOF, 0);
3322     }
3323 
3324     if (mpctx->stream->type == STREAMTYPE_BD) {
3325         if (audio_lang && audio_id == -1)
3326             audio_id = bd_aid_from_lang(mpctx->stream, audio_lang);
3327         if (dvdsub_lang && dvdsub_id == -1)
3328             dvdsub_id = bd_sid_from_lang(mpctx->stream, dvdsub_lang);
3329     }
3330 
3331 #ifdef CONFIG_LIBBLURAY
3332     if (mpctx->stream->type == STREAMTYPE_BLURAY) {
3333         if (audio_lang && audio_id == -1)
3334             audio_id = bluray_id_from_lang(mpctx->stream, stream_ctrl_audio, audio_lang);
3335         if (dvdsub_lang && dvdsub_id == -1)
3336             dvdsub_id = bluray_id_from_lang(mpctx->stream, stream_ctrl_sub, dvdsub_lang);
3337     }
3338 #endif
3339 
3340 #ifdef CONFIG_DVDREAD
3341     if (mpctx->stream->type == STREAMTYPE_DVD) {
3342         current_module = "dvd lang->id";
3343         if (audio_lang && audio_id == -1)
3344             audio_id = dvd_aid_from_lang(mpctx->stream, audio_lang);
3345         if (dvdsub_lang && dvdsub_id == -1)
3346             dvdsub_id = dvd_sid_from_lang(mpctx->stream, dvdsub_lang);
3347         // setup global sub numbering
3348         mpctx->sub_counts[SUB_SOURCE_DEMUX] = dvd_number_of_subs(mpctx->stream);
3349         current_module = NULL;
3350     }
3351 #endif
3352 
3353 #ifdef CONFIG_DVDNAV
3354     if (mpctx->stream->type == STREAMTYPE_DVDNAV) {
3355         current_module = "dvdnav lang->id";
3356         if (audio_lang && audio_id == -1)
3357             audio_id = mp_dvdnav_aid_from_lang(mpctx->stream, audio_lang);
3358         dvdsub_lang_id = -3;
3359         if (dvdsub_lang && dvdsub_id == -1)
3360             dvdsub_lang_id = dvdsub_id = mp_dvdnav_sid_from_lang(mpctx->stream, dvdsub_lang);
3361         // setup global sub numbering
3362         mpctx->sub_counts[SUB_SOURCE_DEMUX] = mp_dvdnav_number_of_subs(mpctx->stream);
3363         current_module = NULL;
3364     }
3365 #endif
3366 
3367 // CACHE2: initial prefill: 20%  later: 5%  (should be set by -cacheopts)
3368 goto_enable_cache:
3369     if (stream_cache_size > 0) {
3370         int res;
3371         current_module = "enable_cache";
3372         res = stream_enable_cache(mpctx->stream, stream_cache_size * 1024ull,
3373                                   stream_cache_size * 1024ull * (stream_cache_min_percent / 100.0),
3374                                   stream_cache_size * 1024ull * (stream_cache_seek_min_percent / 100.0));
3375         if (res == 0)
3376             if ((mpctx->eof = libmpdemux_was_interrupted(PT_NEXT_ENTRY)))
3377                 goto goto_next_file;
3378     }
3379 
3380 //============ Open DEMUXERS --- DETECT file type =======================
3381     current_module = "demux_open";
3382 
3383     mpctx->demuxer = demux_open(mpctx->stream, mpctx->file_format, audio_id, video_id, dvdsub_id, filename);
3384 
3385     // HACK to get MOV Reference Files working
3386     if (mpctx->demuxer && mpctx->demuxer->type == DEMUXER_TYPE_PLAYLIST) {
3387         unsigned char *playlist_entry;
3388         play_tree_t *list = NULL, *entry = NULL;
3389 
3390         current_module = "handle_demux_playlist";
3391         while (ds_get_packet(mpctx->demuxer->video, &playlist_entry) > 0) {
3392             char *temp;
3393             const char *bname;
3394 
3395             mp_msg(MSGT_CPLAYER, MSGL_V, "Adding file %s to element entry.\n",
3396                    filename_recode(playlist_entry));
3397 
3398             bname = mp_basename(playlist_entry);
3399             if ((strlen(bname) > 10) && !strncmp(bname, "qt", 2) && !strncmp(bname + 3, "gateQT", 6))
3400                 continue;
3401 
3402             if (!strcmp(playlist_entry, filename)) // ignoring self-reference
3403                 continue;
3404 
3405             entry = play_tree_new();
3406 
3407             if (filename && !strcmp(mp_basename(playlist_entry), playlist_entry)) { // add reference path of current file
3408                 temp = malloc((strlen(filename) - strlen(mp_basename(filename)) + strlen(playlist_entry) + 1));
3409                 if (temp) {
3410                     strncpy(temp, filename, strlen(filename) - strlen(mp_basename(filename)));
3411                     temp[strlen(filename) - strlen(mp_basename(filename))] = '\0';
3412                     strcat(temp, playlist_entry);
3413                     if (!strcmp(temp, filename)) {
3414                         free(temp);
3415                         continue;
3416                     }
3417                     play_tree_add_file(entry, temp);
3418                     mp_msg(MSGT_CPLAYER, MSGL_V, "Resolving reference to %s.\n", temp);
3419                     free(temp);
3420                 }
3421             } else
3422                 play_tree_add_file(entry, playlist_entry);
3423 
3424             if (!list)
3425                 list = entry;
3426             else
3427                 play_tree_append_entry(list, entry);
3428         }
3429         free_demuxer(mpctx->demuxer);
3430         mpctx->demuxer = NULL;
3431 
3432         if (list) {
3433             entry = play_tree_new();
3434             play_tree_set_child(entry, list);
3435             mpctx->eof = playtree_add_playlist(entry);
3436             goto goto_next_file;
3437         }
3438     }
3439 
3440     if (!mpctx->demuxer)
3441         goto goto_next_file;
3442     if (dvd_chapter > 1) {
3443         float pts;
3444         if (demuxer_seek_chapter(mpctx->demuxer, dvd_chapter - 1, 1, &pts, NULL, NULL) >= 0 && pts > -1.0)
3445             seek(mpctx, pts, SEEK_ABSOLUTE);
3446     }
3447 
3448     initialized_flags |= INITIALIZED_DEMUXER;
3449 
3450 #ifdef CONFIG_ASS
3451     if (ass_enabled && ass_library) {
3452         for (i = 0; i < mpctx->demuxer->num_attachments; ++i) {
3453             demux_attachment_t *att = mpctx->demuxer->attachments + i;
3454             if (extract_embedded_fonts &&
3455                 att->name && att->type && att->data && att->data_size &&
3456                 (strcmp(att->type, "application/x-truetype-font") == 0 ||
3457                  strcmp(att->type, "application/vnd.ms-opentype") == 0 ||
3458                  strcmp(att->type, "application/x-font") == 0))
3459                 ass_add_font(ass_library, att->name, att->data, att->data_size);
3460         }
3461     }
3462 #endif
3463 
3464     current_module = "demux_open2";
3465 
3466     mpctx->d_audio = mpctx->demuxer->audio;
3467     mpctx->d_video = mpctx->demuxer->video;
3468     mpctx->d_sub   = mpctx->demuxer->sub;
3469 
3470     if (ts_prog) {
3471         int tmp = ts_prog;
3472         mp_property_do("switch_program", M_PROPERTY_SET, &tmp, mpctx);
3473     }
3474 
3475     // select video stream
3476     select_video(mpctx->demuxer, video_id);
3477 
3478     // select audio stream
3479     select_audio(mpctx->demuxer, audio_id, audio_lang);
3480 
3481     // DUMP STREAMS:
3482     if ((stream_dump_type) && (stream_dump_type < 4)) {
3483         stream_t *os;
3484         demux_stream_t *ds = NULL;
3485         current_module = "dump";
3486         // select stream to dump
3487         switch (stream_dump_type) {
3488         case 1: ds = mpctx->d_audio; break;
3489         case 2: ds = mpctx->d_video; break;
3490         case 3: ds = mpctx->d_sub;   break;
3491         }
3492         if (!ds) {
3493             mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_DumpSelectedStreamMissing);
3494             exit_player(EXIT_ERROR);
3495         }
3496         // disable other streams:
3497         if (mpctx->d_audio && mpctx->d_audio != ds) {
3498             ds_free_packs(mpctx->d_audio);
3499             select_audio(mpctx->demuxer, -2, NULL);
3500             mpctx->d_audio->id = -2;
3501         }
3502         if (mpctx->d_video && mpctx->d_video != ds) {
3503             ds_free_packs(mpctx->d_video);
3504             select_video(mpctx->demuxer, -2);
3505             mpctx->d_video->id = -2;
3506         }
3507         if (mpctx->d_sub && mpctx->d_sub != ds) {
3508             ds_free_packs(mpctx->d_sub);
3509             mpctx->d_sub->id = -2;
3510         }
3511         // let's dump it!
3512         os = open_output_stream(stream_dump_name, NULL);
3513         if (!os) {
3514             mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_CantOpenDumpfile);
3515             exit_player(EXIT_ERROR);
3516         }
3517         stream_dump_progress_start();
3518 
3519         // force retry in case bad interleaving caused EOF before.
3520         ds->fill_count = 0;
3521         ds->eof = 0;
3522         while (!ds->eof) {
3523             unsigned char *start;
3524             double pts;
3525             int in_size = ds_get_packet_pts(ds, &start, &pts);
3526             if (is_at_end(mpctx, &end_at, pts))
3527                 break;
3528             if ((mpctx->demuxer->file_format == DEMUXER_TYPE_AVI || mpctx->demuxer->file_format == DEMUXER_TYPE_ASF || mpctx->demuxer->file_format == DEMUXER_TYPE_MOV)
3529                 && stream_dump_type == 2)
3530                 stream_write_buffer(os, &in_size, 4);
3531             if (in_size > 0) {
3532                 stream_write_buffer(os, start, in_size);
3533                 stream_dump_progress(in_size, mpctx->stream);
3534             }
3535             if (dvd_last_chapter > 0) {
3536                 int cur_chapter = demuxer_get_current_chapter(mpctx->demuxer);
3537                 if (cur_chapter != -1 && cur_chapter + 1 > dvd_last_chapter)
3538                     break;
3539             }
3540         }
3541         free_stream(os);
3542         stream_dump_progress_end();
3543         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_CoreDumped);
3544         exit_player_with_rc(EXIT_EOF, 0);
3545     }
3546 
3547     mpctx->sh_audio = mpctx->d_audio->sh;
3548     mpctx->sh_video = mpctx->d_video->sh;
3549 
3550     if (mpctx->sh_video) {
3551         current_module = "video_read_properties";
3552         reinit_video_chain();
3553     }
3554 
3555     if (!mpctx->sh_video && !mpctx->sh_audio) {
3556         mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_NoStreamFound);
3557 #ifdef CONFIG_DVBIN
3558         if (mpctx->stream->type == STREAMTYPE_DVB) {
3559             int dir;
3560             int v = mpctx->last_dvb_step;
3561             if (v > 0)
3562                 dir = DVB_CHANNEL_HIGHER;
3563             else
3564                 dir = DVB_CHANNEL_LOWER;
3565 
3566             if (dvb_step_channel(mpctx->stream, dir))
3567                 mpctx->eof = mpctx->dvbin_reopen = 1;
3568         }
3569 #endif
3570         goto goto_next_file; // exit_player(MSGTR_Exit_error);
3571     }
3572 
3573     /* display clip info */
3574     demux_info_print(mpctx->demuxer);
3575 
3576 //================== Read SUBTITLES (DVD & TEXT) ==========================
3577     if (vo_spudec == NULL &&
3578         (mpctx->stream->type == STREAMTYPE_DVD || mpctx->stream->type == STREAMTYPE_DVDNAV)) {
3579         init_vo_spudec(mpctx->stream, mpctx->sh_video, mpctx->d_sub ? mpctx->d_sub->sh : NULL);
3580     }
3581 
3582     if (1 || mpctx->sh_video) {
3583         // after reading video params we should load subtitles because
3584         // we know fps so now we can adjust subtitle time to ~6 seconds AST
3585         // check .sub
3586         double fps = mpctx->sh_video ? mpctx->sh_video->fps : 25;
3587         current_module = "read_subtitles_file";
3588         load_subtitles(filename, fps, add_subtitles);
3589         if (mpctx->set_of_sub_size > 0)
3590             mpctx->sub_counts[SUB_SOURCE_SUBS] = mpctx->set_of_sub_size;
3591         // set even if we have no subs yet, they may be added later
3592         initialized_flags |= INITIALIZED_SUBS;
3593     }
3594 
3595     if (select_subtitle(mpctx) && subdata) {
3596         switch (stream_dump_type) {
3597         case 3: list_sub_file(subdata);                       break;
3598         case 4: dump_mpsub(subdata,    mpctx->sh_video->fps); break;
3599         case 6: dump_srt(subdata,      mpctx->sh_video->fps); break;
3600         case 7: dump_microdvd(subdata, mpctx->sh_video->fps); break;
3601         case 8: dump_jacosub(subdata,  mpctx->sh_video->fps); break;
3602         case 9: dump_sami(subdata,     mpctx->sh_video->fps); break;
3603         }
3604     }
3605 
3606     print_file_properties(mpctx, filename);
3607 
3608     // Adjust EDL positions with start_pts
3609     if (edl_start_pts && start_pts) {
3610         edl_record_ptr edl = edl_records;
3611         while (edl) {
3612             edl->start_sec += start_pts;
3613             edl->stop_sec  += start_pts;
3614             edl = edl->next;
3615         }
3616     }
3617 
3618     if (mpctx->sh_video) {
3619         if (vo_flags & 0x08 && vo_spudec)
3620             spudec_set_hw_spu(vo_spudec, mpctx->video_out);
3621 
3622 #ifdef CONFIG_FREETYPE
3623         force_load_font = 1;
3624 #endif
3625     } else if (!mpctx->sh_audio)
3626         goto goto_next_file;
3627 
3628 //================== MAIN: ==========================
3629     current_module = "main";
3630 
3631     if (playing_msg) {
3632         char *msg = property_expand_string(mpctx, playing_msg);
3633         mp_msg(MSGT_CPLAYER, MSGL_INFO, "%s", msg);
3634         free(msg);
3635     }
3636 
3637     // Disable the term OSD in verbose mode
3638     if (verbose)
3639         term_osd = 0;
3640 
3641     {
3642         mpctx->num_buffered_frames = 0;
3643 
3644         // Make sure old OSD does not stay around,
3645         // e.g. with -fixed-vo and same-resolution files
3646         clear_osd_msgs();
3647         update_osd_msg();
3648 
3649 //================ SETUP AUDIO ==========================
3650 
3651         if (mpctx->sh_audio) {
3652             reinit_audio_chain();
3653             if (mpctx->sh_audio && mpctx->sh_audio->codec)
3654                 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_CODEC=%s\n", codec_idx2str(mpctx->sh_audio->codec->name_idx));
3655             if (mpctx->audio_out)
3656                 mpctx->audio_out->control(AOCONTROL_FILENAME, (void *)(vo_wintitle ? vo_wintitle : mp_basename(filename)));
3657         }
3658 
3659         current_module = "av_init";
3660 
3661         if (mpctx->sh_video) {
3662             mpctx->sh_video->timer = 0;
3663             if (!ignore_start)
3664                 audio_delay += mpctx->sh_video->stream_delay;
3665         }
3666         if (mpctx->sh_audio) {
3667             if (start_volume >= 0)
3668                 mixer_setvolume(&mpctx->mixer, start_volume, start_volume);
3669             if (!ignore_start)
3670                 audio_delay -= mpctx->sh_audio->stream_delay;
3671             mpctx->delay = -audio_delay;
3672         }
3673 
3674         if (!mpctx->sh_audio) {
3675             mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_NoSound);
3676             mp_msg(MSGT_CPLAYER, MSGL_V, "Freeing %d unused audio chunks.\n", mpctx->d_audio->packs);
3677             ds_free_packs(mpctx->d_audio); // free buffered chunks
3678             //mpctx->d_audio->id=-2;         // do not read audio chunks
3679             //uninit_player(INITIALIZED_AO); // close device
3680         }
3681         if (!mpctx->sh_video) {
3682             mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_Video_NoVideo);
3683             mp_msg(MSGT_CPLAYER, MSGL_V, "Freeing %d unused video chunks.\n", mpctx->d_video->packs);
3684             ds_free_packs(mpctx->d_video);
3685             //mpctx->d_video->id = -2;
3686             //if(!fixed_vo) uninit_player(INITIALIZED_VO);
3687         }
3688 
3689         if (!mpctx->sh_video && !mpctx->sh_audio)
3690             goto goto_next_file;
3691 
3692         //if(demuxer->file_format!=DEMUXER_TYPE_AVI) pts_from_bps=0; // it must be 0 for mpeg/asf!
3693         if (force_fps && mpctx->sh_video) {
3694             vo_fps = mpctx->sh_video->fps = force_fps;
3695             mpctx->sh_video->frametime = 1.0f / mpctx->sh_video->fps;
3696             mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_FPSforced, mpctx->sh_video->fps, mpctx->sh_video->frametime);
3697         }
3698 
3699 #ifdef CONFIG_GUI
3700         if (use_gui) {
3701             if (!gui(GUI_SET_VIDEO, mpctx->sh_video))
3702                 goto goto_next_file;
3703             if (mpctx->sh_audio)
3704                 gui(GUI_SET_AUDIO, mpctx->sh_audio);
3705         }
3706 #endif
3707 
3708         mp_input_set_section(NULL);
3709         //TODO: add desired (stream-based) sections here
3710         if (mpctx->stream->type == STREAMTYPE_TV)
3711             mp_input_set_section("tv");
3712         if (mpctx->stream->type == STREAMTYPE_DVDNAV)
3713             mp_input_set_section("dvdnav");
3714 
3715 //==================== START PLAYING =======================
3716 
3717         if (mpctx->loop_times > 1)
3718             mpctx->loop_times--;
3719         else if (mpctx->loop_times == 1)
3720             mpctx->loop_times = -1;
3721 
3722         mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_StartPlaying);
3723 
3724         total_time_usage_start = GetTimer();
3725         audio_time_usage       = 0;
3726         video_time_usage       = 0;
3727         vout_time_usage = 0;
3728         total_frame_cnt = 0;
3729         drop_frame_cnt  = 0;         // fix for multifile fps benchmark
3730         play_n_frames   = play_n_frames_mf;
3731         mpctx->startup_decode_retry = DEFAULT_STARTUP_DECODE_RETRY;
3732 
3733         if (play_n_frames == 0) {
3734             mpctx->eof = PT_NEXT_ENTRY;
3735             goto goto_next_file;
3736         }
3737 
3738         if (seek_to_sec != MP_NOPTS_VALUE) {
3739             seek(mpctx, seek_to_sec, SEEK_ABSOLUTE);
3740             end_at.pos += seek_to_sec;
3741         }
3742 
3743 #ifdef CONFIG_DVDNAV
3744         mp_dvdnav_context_free(mpctx);
3745         if (mpctx->stream->type == STREAMTYPE_DVDNAV) {
3746             mp_dvdnav_read_wait(mpctx->stream, 0, 1);
3747             mp_dvdnav_cell_has_changed(mpctx->stream, 1);
3748         }
3749 #endif
3750 
3751         while (!mpctx->eof) {
3752             float aq_sleep_time = 0;
3753 
3754             if (dvd_last_chapter > 0) {
3755                 int cur_chapter = demuxer_get_current_chapter(mpctx->demuxer);
3756                 if (cur_chapter != -1 && cur_chapter + 1 > dvd_last_chapter)
3757                     goto goto_next_file;
3758             }
3759 
3760             if (!mpctx->sh_audio && mpctx->d_audio->sh) {
3761                 mpctx->sh_audio     = mpctx->d_audio->sh;
3762                 mpctx->sh_audio->ds = mpctx->d_audio;
3763                 reinit_audio_chain();
3764             }
3765             // Note: the video_id != -2 is only there because
3766             // some demuxers do not have support for disabling
3767             // video.
3768             if (video_id != -2 && mpctx->d_video->id != -2 &&
3769                 !mpctx->sh_video && mpctx->d_video->sh) {
3770                 mpctx->sh_video     = mpctx->d_video->sh;
3771                 mpctx->sh_video->ds = mpctx->d_video;
3772                 reinit_video_chain();
3773             }
3774 
3775 /*========================== PLAY AUDIO ============================*/
3776 
3777             if (mpctx->sh_audio)
3778                 if (!fill_audio_out_buffers())
3779                     // at eof, all audio at least written to ao
3780                     if (!mpctx->sh_video)
3781                         mpctx->eof = PT_NEXT_ENTRY;
3782 
3783             if (!mpctx->sh_video) {
3784                 // handle audio-only case:
3785                 double a_pos = 0;
3786                 // sh_audio can be NULL due to video stream switching
3787                 // TODO: handle this better
3788                 if (mpctx->sh_audio)
3789                     a_pos = playing_audio_pts(mpctx->sh_audio, mpctx->d_audio, mpctx->audio_out);
3790 
3791                 if (!quiet)
3792                     print_status(a_pos, 0, 0);
3793 
3794                 if (is_at_end(mpctx, &end_at, a_pos))
3795                     mpctx->eof = PT_NEXT_ENTRY;
3796                 update_subtitles(NULL, a_pos, mpctx->d_sub, 0);
3797                 update_osd_msg();
3798             } else {
3799                 int frame_time_remaining = 0;
3800                 int blit_frame = mpctx->num_buffered_frames > 0;
3801                 // skip timing after seek
3802                 int skip_timing = mpctx->startup_decode_retry > 0;
3803 
3804 /*========================== PLAY VIDEO ============================*/
3805 
3806                 vo_pts = mpctx->sh_video->timer * 90000.0;
3807                 vo_fps = mpctx->sh_video->fps;
3808 
3809                 if (!mpctx->num_buffered_frames) {
3810                     double frame_time = update_video(&blit_frame);
3811                     while (!blit_frame && mpctx->startup_decode_retry > 0) {
3812                         double delay = mpctx->delay;
3813                         // these initial decode failures are probably due to codec delay,
3814                         // ignore them and also their probably nonsense durations
3815                         update_video(&blit_frame);
3816                         mpctx->delay = delay;
3817                         mpctx->startup_decode_retry--;
3818                     }
3819                     mpctx->startup_decode_retry = 0;
3820                     mp_dbg(MSGT_AVSYNC, MSGL_DBG2, "*** ftime=%5.3f ***\n", frame_time);
3821                     if (mpctx->sh_video->vf_initialized < 0) {
3822                         mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_NotInitializeVOPorVO);
3823                         mpctx->eof = 1;
3824                         goto goto_next_file;
3825                     }
3826                     if (frame_time < 0) {
3827                         // try to figure out duration of last frame
3828                         if (correct_pts && mpctx->sh_video->endpts != MP_NOPTS_VALUE &&
3829                             mpctx->sh_video->pts != MP_NOPTS_VALUE &&
3830                             mpctx->sh_video->endpts > mpctx->sh_video->pts) {
3831                             frame_time = mpctx->sh_video->endpts - mpctx->sh_video->pts;
3832                         } else {
3833                             frame_time = mpctx->sh_video->frametime;
3834                         }
3835                         // mark as last frame. Note: needs to be reset on seeking
3836                         mpctx->sh_video->frametime = -1;
3837                         mpctx->sh_video->endpts = MP_NOPTS_VALUE;
3838                     }
3839                     if (frame_time < 0) {
3840                         // if we have no more video, sleep some arbitrary time
3841                         frame_time = 1.0 / 20.0;
3842                         // Ensure vo_pts is updated so that ao_pcm will not hang.
3843                         advance_timer(frame_time);
3844                         // only stop playing when audio is at end as well
3845                         if (!mpctx->sh_audio || (mpctx->d_audio->eof && !ds_fill_buffer(mpctx->d_audio)))
3846                             mpctx->eof = mpctx->time_frame <= 0;
3847                     } else {
3848                         // might return with !eof && !blit_frame if !correct_pts
3849                         mpctx->num_buffered_frames += blit_frame;
3850                         mpctx->time_frame += frame_time / playback_speed; // for nosound
3851                     }
3852                 }
3853 
3854 // ==========================================================================
3855 
3856 //    current_module="draw_osd";
3857 //    if(vo_config_count) mpctx->video_out->draw_osd();
3858 
3859                 current_module = "vo_check_events";
3860                 if (vo_config_count)
3861                     mpctx->video_out->check_events();
3862 
3863 #ifdef CONFIG_X11
3864                 if (stop_xscreensaver) {
3865                     current_module = "stop_xscreensaver";
3866                     xscreensaver_heartbeat();
3867                 }
3868 #endif
3869                 if (heartbeat_cmd) {
3870                     static unsigned last_heartbeat;
3871                     unsigned now = GetTimerMS();
3872                     // compare as unsigned so that any mistakes (overflow etc)
3873                     // trigger a heartbeat, thus resetting the logic.
3874                     if (now - last_heartbeat > (unsigned)(heartbeat_interval * 1000)) {
3875                         last_heartbeat = now;
3876                         system(heartbeat_cmd);
3877                     }
3878                 }
3879 
3880                 if (!skip_timing)
3881                     frame_time_remaining = sleep_until_update(&mpctx->time_frame, &aq_sleep_time);
3882 
3883 //====================== FLIP PAGE (VIDEO BLT): =========================
3884 
3885                 if (!edl_needs_reset) {
3886                     current_module = "flip_page";
3887                     if (!frame_time_remaining && blit_frame) {
3888                         unsigned int t2 = GetTimer();
3889 
3890                         if (vo_config_count)
3891                             mpctx->video_out->flip_page();
3892                         mpctx->num_buffered_frames--;
3893 
3894                         vout_time_usage += (GetTimer() - t2) * 0.000001;
3895                     }
3896                 }
3897 //====================== A-V TIMESTAMP CORRECTION: =========================
3898 
3899                 adjust_sync_and_print_status(frame_time_remaining, mpctx->time_frame);
3900 
3901 //============================ Auto QUALITY ============================
3902 
3903                 /*Output quality adjustments:*/
3904                 if (auto_quality > 0) {
3905                     current_module = "autoq";
3906                     //float total=0.000001f * (GetTimer()-aq_total_time);
3907                     //if(output_quality<auto_quality && aq_sleep_time>0.05f*total)
3908                     if (output_quality < auto_quality && aq_sleep_time > 0)
3909                         ++output_quality;
3910                     else
3911                     //if(output_quality>0 && aq_sleep_time<-0.05f*total)
3912                     if (output_quality > 1 && aq_sleep_time < 0)
3913                         --output_quality;
3914                     else if (output_quality > 0 && aq_sleep_time < -0.050f) // 50ms
3915                         output_quality = 0;
3916                     //printf("total: %8.6f  sleep: %8.6f  q: %d\n",(0.000001f*aq_total_time),aq_sleep_time,output_quality);
3917                     set_video_quality(mpctx->sh_video, output_quality);
3918                 }
3919 
3920                 if (play_n_frames >= 0 && !frame_time_remaining && blit_frame) {
3921                     --play_n_frames;
3922                     if (play_n_frames <= 0)
3923                         mpctx->eof = PT_NEXT_ENTRY;
3924                 }
3925 
3926                 if (!frame_time_remaining && is_at_end(mpctx, &end_at,
3927                                                        mpctx->sh_video->pts))
3928                     mpctx->eof = PT_NEXT_ENTRY;
3929             } // end if(mpctx->sh_video)
3930 
3931 #ifdef CONFIG_DVDNAV
3932             if (mpctx->stream->type == STREAMTYPE_DVDNAV) {
3933                 // do not clobber subtitles
3934                 if (!mp_dvdnav_number_of_subs(mpctx->stream)) {
3935                 nav_highlight_t hl;
3936                 mp_dvdnav_get_highlight(mpctx->stream, &hl);
3937                 if (!vo_spudec || !spudec_apply_palette_crop(vo_spudec, hl.palette, hl.sx, hl.sy, hl.ex, hl.ey)) {
3938                     osd_set_nav_box(hl.sx, hl.sy, hl.ex, hl.ey);
3939                     vo_osd_changed(OSDTYPE_DVDNAV);
3940                 } else {
3941                     osd_set_nav_box(0, 0, 0, 0);
3942                     vo_osd_changed(OSDTYPE_DVDNAV);
3943                     vo_osd_changed(OSDTYPE_SPU);
3944                 }
3945                 }
3946 
3947                 if (mp_dvdnav_stream_has_changed(mpctx->stream)) {
3948                     double ar = -1.0;
3949                     // clear highlight
3950                     if (vo_spudec)
3951                         spudec_apply_palette_crop(vo_spudec, 0, 0, 0, 0, 0);
3952                     osd_set_nav_box(0, 0, 0, 0);
3953                     vo_osd_changed(OSDTYPE_DVDNAV);
3954                     vo_osd_changed(OSDTYPE_SPU);
3955                     if (mpctx->sh_video &&
3956                         stream_control(mpctx->demuxer->stream,
3957                                        STREAM_CTRL_GET_ASPECT_RATIO, &ar)
3958                         != STREAM_UNSUPPORTED)
3959                         mpctx->sh_video->stream_aspect = ar;
3960                 }
3961             }
3962 #endif
3963 
3964 //============================ Handle PAUSE ===============================
3965 
3966             current_module = "pause";
3967 
3968             if (mpctx->osd_function == OSD_PAUSE) {
3969                 mpctx->was_paused = 1;
3970                 pause_loop();
3971             }
3972 
3973             // handle -sstep
3974             if (step_sec > 0) {
3975                 mpctx->osd_function = OSD_FFW;
3976                 rel_seek_secs      += step_sec;
3977             }
3978 
3979             edl_update(mpctx);
3980 
3981 //================= Keyboard events, SEEKing ====================
3982 
3983             current_module = "key_events";
3984 
3985             {
3986                 mp_cmd_t *cmd;
3987                 int brk_cmd = 0;
3988                 while (!brk_cmd && (cmd = mp_input_get_cmd(0, 0, 0)) != NULL) {
3989                     brk_cmd = run_command(mpctx, cmd);
3990                     if (cmd->id == MP_CMD_EDL_LOADFILE) {
3991                         free(edl_filename);
3992                         edl_filename = strdup(cmd->args[0].v.s);
3993                         if (edl_filename)
3994                             edl_loadfile();
3995                         else
3996                             mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_EdlOutOfMemFile,
3997                                    cmd->args[0].v.s);
3998                     }
3999                     mp_cmd_free(cmd);
4000                     if (brk_cmd == 2)
4001                         goto goto_enable_cache;
4002                 }
4003             }
4004             mpctx->was_paused = 0;
4005 
4006             /* Looping. */
4007             if (mpctx->eof == 1 && mpctx->loop_times >= 0) {
4008                 mp_msg(MSGT_CPLAYER, MSGL_V, "loop_times = %d, eof = %d\n", mpctx->loop_times, mpctx->eof);
4009 
4010                 if (mpctx->loop_times > 1)
4011                     mpctx->loop_times--;
4012                 else if (mpctx->loop_times == 1)
4013                     mpctx->loop_times = -1;
4014                 play_n_frames = play_n_frames_mf;
4015                 mpctx->eof    = 0;
4016                 abs_seek_pos  = SEEK_ABSOLUTE;
4017                 rel_seek_secs = seek_to_sec;
4018                 if (seek_to_sec == MP_NOPTS_VALUE) {
4019                     // the first pts is not necessarily 0
4020                     abs_seek_pos  = SEEK_ABSOLUTE | SEEK_FACTOR;
4021                     rel_seek_secs = 0;
4022                 }
4023                 loop_seek     = 1;
4024             }
4025 
4026             if (rel_seek_secs || abs_seek_pos) {
4027                 if (seek(mpctx, rel_seek_secs, abs_seek_pos) >= 0) {
4028                     // Set OSD:
4029                     if (!loop_seek) {
4030                         if (!edl_decision)
4031                             set_osd_bar(0, "Position", 0, 100, demuxer_get_percent_pos(mpctx->demuxer));
4032                     }
4033                 }
4034 
4035                 // reset last frame marker
4036                 if (mpctx->sh_video && mpctx->sh_video->frametime < 0)
4037                     mpctx->sh_video->frametime = 1.0f / mpctx->sh_video->fps;
4038                 rel_seek_secs = 0;
4039                 abs_seek_pos  = 0;
4040                 loop_seek     = 0;
4041                 edl_decision  = 0;
4042             }
4043 
4044 #ifdef CONFIG_GUI
4045             if (use_gui) {
4046                 if (mpctx->demuxer->file_format == DEMUXER_TYPE_AVI && mpctx->sh_video && mpctx->sh_video->video.dwLength > 2) {
4047                     // get pos from frame number / total frames
4048                     guiInfo.Position = (float)mpctx->d_video->pack_no * 100.0f / mpctx->sh_video->video.dwLength;
4049                 } else {
4050                     guiInfo.Position = demuxer_get_percent_pos(mpctx->demuxer);
4051                 }
4052                 guiInfo.ElapsedTime = -1;
4053                 if (mpctx->sh_video)
4054                     guiInfo.ElapsedTime = mpctx->sh_video->pts;
4055                 if (guiInfo.ElapsedTime < 0 && mpctx->sh_audio)
4056                     guiInfo.ElapsedTime = playing_audio_pts(mpctx->sh_audio, mpctx->d_audio, mpctx->audio_out);
4057                 guiInfo.RunningTime = demuxer_get_time_length(mpctx->demuxer);
4058                 gui(GUI_SET_VOLUME_BALANCE, &mpctx->mixer);
4059                 gui(GUI_REDRAW, 0);
4060                 if (guiInfo.Playing == GUI_STOP)
4061                     break;                  // STOP
4062                 if (guiInfo.Playing == GUI_PAUSE)
4063                     mpctx->osd_function = OSD_PAUSE;
4064                 if (guiInfo.MediumChanged)
4065                     goto goto_next_file;
4066 #ifdef CONFIG_DVDREAD
4067                 if (mpctx->stream->type == STREAMTYPE_DVD) {
4068                     dvd_priv_t *dvdp = mpctx->stream->priv;
4069                     guiInfo.Chapter = dvd_chapter_from_cell(dvdp, guiInfo.Track - 1, dvdp->cur_cell) + 1;
4070                 }
4071 #endif
4072             }
4073 #endif /* CONFIG_GUI */
4074         } // while(!mpctx->eof)
4075 
4076         mp_msg(MSGT_GLOBAL, MSGL_V, "EOF code: %d  \n", mpctx->eof);
4077 
4078 #ifdef CONFIG_DVBIN
4079         if (mpctx->dvbin_reopen) {
4080             mpctx->eof = 0;
4081             uninit_player(INITIALIZED_ALL - (INITIALIZED_GUI | INITIALIZED_STREAM | INITIALIZED_INPUT | INITIALIZED_GETCH2 | (fixed_vo ? INITIALIZED_VO : 0)));
4082             cache_uninit(mpctx->stream);
4083             mpctx->dvbin_reopen = 0;
4084             goto goto_enable_cache;
4085         }
4086 #endif
4087     }
4088 
4089 goto_next_file:  // don't jump here after ao/vo/getch initialization!
4090 
4091     mp_msg(MSGT_CPLAYER, MSGL_INFO, "\n");
4092 
4093     if (benchmark) {
4094         double tot = video_time_usage + vout_time_usage + audio_time_usage;
4095         double total_time_usage;
4096         total_time_usage_start = GetTimer() - total_time_usage_start;
4097         total_time_usage       = (float)total_time_usage_start * 0.000001;
4098         mp_msg(MSGT_CPLAYER, MSGL_INFO, "\nBENCHMARKs: VC:%8.3fs VO:%8.3fs A:%8.3fs Sys:%8.3fs = %8.3fs\n",
4099                video_time_usage, vout_time_usage, audio_time_usage,
4100                total_time_usage - tot, total_time_usage);
4101         if (total_time_usage > 0.0)
4102             mp_msg(MSGT_CPLAYER, MSGL_INFO, "BENCHMARK%%: VC:%8.4f%% VO:%8.4f%% A:%8.4f%% Sys:%8.4f%% = %8.4f%%\n",
4103                    100.0 * video_time_usage         / total_time_usage,
4104                    100.0 * vout_time_usage          / total_time_usage,
4105                    100.0 * audio_time_usage         / total_time_usage,
4106                    100.0 * (total_time_usage - tot) / total_time_usage,
4107                    100.0);
4108         if (total_frame_cnt && frame_dropping)
4109             mp_msg(MSGT_CPLAYER, MSGL_INFO, "BENCHMARKn: disp: %d (%3.2f fps)  drop: %d (%d%%)  total: %d (%3.2f fps)\n",
4110                    total_frame_cnt - drop_frame_cnt,
4111                    (total_time_usage > 0.5) ? ((total_frame_cnt - drop_frame_cnt) / total_time_usage) : 0,
4112                    drop_frame_cnt,
4113                    100 * drop_frame_cnt / total_frame_cnt,
4114                    total_frame_cnt,
4115                    (total_time_usage > 0.5) ? (total_frame_cnt / total_time_usage) : 0);
4116     }
4117 
4118     // time to uninit all, except global stuff:
4119     uninit_player(INITIALIZED_ALL - (INITIALIZED_GUI + INITIALIZED_INPUT + (fixed_vo ? INITIALIZED_VO : 0)));
4120 
4121     if (mpctx->eof == PT_NEXT_ENTRY || mpctx->eof == PT_PREV_ENTRY) {
4122         mpctx->eof = mpctx->eof == PT_NEXT_ENTRY ? 1 : -1;
4123         if (play_tree_iter_step(mpctx->playtree_iter, mpctx->play_tree_step, 0) == PLAY_TREE_ITER_ENTRY) {
4124             mpctx->eof = 1;
4125         } else {
4126             play_tree_iter_free(mpctx->playtree_iter);
4127             mpctx->playtree_iter = NULL;
4128         }
4129         mpctx->play_tree_step = 1;
4130     } else if (mpctx->eof == PT_UP_NEXT || mpctx->eof == PT_UP_PREV) {
4131         mpctx->eof = mpctx->eof == PT_UP_NEXT ? 1 : -1;
4132         if (mpctx->playtree_iter) {
4133             if (play_tree_iter_up_step(mpctx->playtree_iter, mpctx->eof, 0) == PLAY_TREE_ITER_ENTRY) {
4134                 mpctx->eof = 1;
4135             } else {
4136                 play_tree_iter_free(mpctx->playtree_iter);
4137                 mpctx->playtree_iter = NULL;
4138             }
4139         }
4140     } else if (mpctx->eof == PT_STOP) {
4141         play_tree_iter_free(mpctx->playtree_iter);
4142         mpctx->playtree_iter = NULL;
4143     } else { // NEXT PREV SRC
4144         mpctx->eof = mpctx->eof == PT_PREV_SRC ? -1 : 1;
4145     }
4146 
4147     if (mpctx->eof == 0)
4148         mpctx->eof = 1;
4149 
4150     while (mpctx->playtree_iter != NULL) {
4151         filename = play_tree_iter_get_file(mpctx->playtree_iter, mpctx->eof);
4152         if (filename)
4153             break;
4154         if (play_tree_iter_step(mpctx->playtree_iter, mpctx->eof, 0) != PLAY_TREE_ITER_ENTRY) {
4155             play_tree_iter_free(mpctx->playtree_iter);
4156             mpctx->playtree_iter = NULL;
4157         }
4158     }
4159 
4160 #ifdef CONFIG_GUI
4161     if (use_gui)
4162         if (guiInfo.MediumChanged != GUI_MEDIUM_SAME)
4163             gui(GUI_END_PLAY, 0);
4164 #endif
4165 
4166     if (
4167 #ifdef CONFIG_GUI
4168         (use_gui && guiInfo.Playing) ||
4169 #endif
4170                                         mpctx->playtree_iter != NULL || player_idle_mode) {
4171         if (!mpctx->playtree_iter && !use_gui)
4172             filename = NULL;
4173         mpctx->eof = 0;
4174         goto play_next_file;
4175     }
4176 
4177     exit_player_with_rc(EXIT_EOF, 0);
4178     return 1;
4179 }
4180 
4181 #endif /* DISABLE_MAIN */
4182