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