From 928da7a4484938cef38ae682837cf857999e853d Mon Sep 17 00:00:00 2001 From: ptt Date: Mon, 25 Sep 2006 16:47:56 +0000 Subject: [PATCH] after a long time, finally i could add -endpos option to mplayer executable. as oded told me on 1006 02 24, i applied it, blame me if some problem occurs, i hope not, since i tried it for a while.... git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@19979 b3059339-0415-0410-9bf9-f77b7e298cf2 --- DOCS/man/en/mplayer.1 | 44 ++++++++++++++------------ cfg-common.h | 3 ++ cfg-mencoder.h | 2 -- help/help_mp-en.h | 1 + m_option.c | 72 +++++++++++++++++++++++++++++++++++++++++++ m_option.h | 10 ++++++ mencoder.c | 62 ++++--------------------------------- mplayer.c | 27 ++++++++++++++-- 8 files changed, 140 insertions(+), 81 deletions(-) diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1 index 0f419d2379..b976352c42 100644 --- a/DOCS/man/en/mplayer.1 +++ b/DOCS/man/en/mplayer.1 @@ -1273,6 +1273,30 @@ the entries in the given file. See DOCS/\:HTML/\:en/\:edl.html for details on how to use this. . .TP +.B \-endpos <[[hh:]mm:]ss[.ms]|size[b|kb|mb]> (also see \-ss and \-sb) +Stop at given time or byte position. +.br +.I NOTE: +Byte position is enabled only for MEncoder and will not be accurate, as it can +only stop at a frame boundary. +When used in conjunction with \-ss option, \-endpos time will shift forward by +seconds specified with \-ss. +.sp 1 +.I EXAMPLE: +.PD 0 +.RSs +.IPs "\-endpos 56" +Stop at 56 seconds. +.IPs "\-endpos 01:10:00" +Stop at 1 hour 10 minutes. +.IPs "\-ss 10 \-endpos 56" +Stop at 1 minute 6 seconds. +.IPs "\-endpos 100mb" +Encode only 100 MB. +.RE +.PD 1 +. +.TP .B \-forceidx Force index rebuilding. Useful for files with broken index (A/V desync, etc). @@ -6550,26 +6574,6 @@ CBR only, VBR ignores this as it puts each packet in a new chunk. Sets up the audio buffering time interval (default: 0.5s). . .TP -.B \-endpos <[[hh:]mm:]ss[.ms]|size[b|kb|mb]> (also see \-ss and \-sb) -Stop encoding at the given time or byte position. -.br -.I NOTE: -Byte position will not be accurate, as it can only stop at -a frame boundary. -.sp 1 -.I EXAMPLE: -.PD 0 -.RSs -.IPs "\-endpos 56" -Encode only 56 seconds. -.IPs "\-endpos 01:10:00" -Encode only 1 hour 10 minutes. -.IPs "\-endpos 100mb" -Encode only 100 MB. -.RE -.PD 1 -. -.TP .B \-fafmttag Can be used to override the audio format tag of the output file. .sp 1 diff --git a/cfg-common.h b/cfg-common.h index a3e2c736e2..780df38905 100644 --- a/cfg-common.h +++ b/cfg-common.h @@ -93,6 +93,9 @@ {"sb", &seek_to_byte, CONF_TYPE_POSITION, CONF_MIN, 0, 0, NULL}, {"ss", &seek_to_sec, CONF_TYPE_STRING, CONF_MIN, 0, 0, NULL}, + // stop at given position + {"endpos", &end_at, CONF_TYPE_TIME_SIZE, 0, 0, 0, NULL}, + {"edl", &edl_filename, CONF_TYPE_STRING, 0, 0, 0, NULL}, // AVI specific: force non-interleaved mode diff --git a/cfg-mencoder.h b/cfg-mencoder.h index 64b821edc5..71248ad588 100644 --- a/cfg-mencoder.h +++ b/cfg-mencoder.h @@ -185,8 +185,6 @@ extern int write_odml; /* defined in libmpdemux/muxer_avi.c */ m_option_t mencoder_opts[]={ /* name, pointer, type, flags, min, max */ - {"endpos", &end_at_string, CONF_TYPE_STRING, 0, 0, 0, NULL}, - {"frameno-file", &frameno_filename, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL}, {"hr-edl-seek", &edl_seek_type, CONF_TYPE_FLAG, 0, 0, 1, NULL}, diff --git a/help/help_mp-en.h b/help/help_mp-en.h index 0756c3d173..77d3a68d97 100644 --- a/help/help_mp-en.h +++ b/help/help_mp-en.h @@ -201,6 +201,7 @@ static char help_text[]= #define MSGTR_EdloutBadStop "EDL skip canceled, last start > stop\n" #define MSGTR_EdloutStartSkip "EDL skip start, press 'i' again to end block.\n" #define MSGTR_EdloutEndSkip "EDL skip end, line written.\n" +#define MSGTR_MPEndposNoSizeBased "Option -endpos in MPlayer does not yet support size units.\n" // mplayer.c OSD diff --git a/m_option.c b/m_option.c index 7d7e16926c..c5a718fe63 100644 --- a/m_option.c +++ b/m_option.c @@ -1175,6 +1175,78 @@ m_option_type_t m_option_type_afmt = { }; +// Time or size (-endpos) + +static int parse_time_size(m_option_t* opt,char *name, char *param, void* dst, int src) { + + if (dst == NULL) + return 0; + + m_time_size_t* ts = dst; + ts->pos=0; + + char unit[4]; + int a,b; + float d; + double end_at; + + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; + + /* End at size parsing */ + if(sscanf(param, "%lf%3s", &end_at, unit) == 2) { + ts->type = END_AT_SIZE; + if(!strcasecmp(unit, "b")) + ; + else if(!strcasecmp(unit, "kb")) + end_at *= 1024; + else if(!strcasecmp(unit, "mb")) + end_at *= 1024*1024; + else if(!strcasecmp(unit, "gb")) + end_at *= 1024*1024*1024; + else + ts->type = END_AT_NONE; + + if (ts->type == END_AT_SIZE) { + ts->pos = end_at; + return 1; + } + } + + /* End at time parsing. This has to be last because of + * sscanf("%f", ...) below */ + if (sscanf(param, "%d:%d:%f", &a, &b, &d) == 3) + end_at = 3600*a + 60*b + d; + else if (sscanf(param, "%d:%f", &a, &d) == 2) + end_at = 60*a + d; + else if (sscanf(param, "%f", &d) == 1) + end_at = d; + else { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid time or size: '%s'\n", + name,param); + return M_OPT_INVALID; + } + + ts->type = END_AT_TIME; + ts->pos = end_at; + + return 1; +} + +m_option_type_t m_option_type_time_size = { + "Time or size", + "", + sizeof(m_time_size_t), + 0, + parse_time_size, + NULL, + copy_opt, + copy_opt, + NULL, + NULL +}; + + //// Objects (i.e. filters, etc) settings #include "m_struct.h" diff --git a/m_option.h b/m_option.h index 82f67cd3ad..443b5d8d4e 100644 --- a/m_option.h +++ b/m_option.h @@ -28,6 +28,7 @@ extern m_option_type_t m_option_type_double; extern m_option_type_t m_option_type_string; extern m_option_type_t m_option_type_string_list; extern m_option_type_t m_option_type_position; +extern m_option_type_t m_option_type_time_size; extern m_option_type_t m_option_type_print; extern m_option_type_t m_option_type_print_indirect; @@ -59,6 +60,14 @@ typedef m_opt_func_full_t cfg_func_arg_param_t; typedef m_opt_func_param_t cfg_func_param_t; typedef m_opt_func_t cfg_func_t; +#define END_AT_NONE 0 +#define END_AT_TIME 1 +#define END_AT_SIZE 2 +typedef struct { + double pos; + int type; +} m_time_size_t; + /// Extra definition needed for \ref m_option_type_obj_settings_list options. typedef struct { /// Pointer to an array of pointer to some object type description struct. @@ -159,6 +168,7 @@ extern m_obj_params_t m_span_params_def; #define CONF_TYPE_OBJ_PRESETS (&m_option_type_obj_presets) #define CONF_TYPE_CUSTOM_URL (&m_option_type_custom_url) #define CONF_TYPE_OBJ_PARAMS (&m_option_type_obj_params) +#define CONF_TYPE_TIME_SIZE (&m_option_type_time_size) ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/mencoder.c b/mencoder.c index 998d179cc4..865a1b6a94 100644 --- a/mencoder.c +++ b/mencoder.c @@ -252,10 +252,10 @@ static int cfg_include(m_option_t *conf, char *filename){ static char *seek_to_sec=NULL; static off_t seek_to_byte=0; +static m_time_size_t end_at = { .type = END_AT_NONE, .pos = 0 }; + static char * frameno_filename=NULL; -static void parse_end_at(void); -static char * end_at_string=0; //static uint8_t* flip_upside_down(uint8_t* dst, const uint8_t* src, int width, int height); typedef struct { @@ -355,10 +355,6 @@ static float stop_time(demuxer_t* demuxer, muxer_stream_t* mux_v); static int at_eof=0; static int interrupted=0; -enum end_at_type_t {END_AT_NONE, END_AT_TIME, END_AT_SIZE}; -static enum end_at_type_t end_at_type = END_AT_NONE; -static double end_at; - static void exit_sighandler(int x){ at_eof=1; interrupted=2; /* 1 means error */ @@ -1040,8 +1036,6 @@ else { } } -parse_end_at(); - if (seek_to_sec) { int a,b; float d; @@ -1080,7 +1074,7 @@ if(file_format == DEMUXER_TYPE_TV) } play_n_frames=play_n_frames_mf; -if (curfile && end_at_type == END_AT_TIME) end_at += mux_v->timer; +if (curfile && end_at.type == END_AT_TIME) end_at.pos += mux_v->timer; if (edl_records) free_edl(edl_records); next_edl_record = edl_records = NULL; @@ -1099,8 +1093,8 @@ while(!at_eof){ float v_pts=0; int skip_flag=0; // 1=skip -1=duplicate - if((end_at_type == END_AT_SIZE && end_at <= ftello(muxer_f)) || - (end_at_type == END_AT_TIME && end_at < mux_v->timer)) + if((end_at.type == END_AT_SIZE && end_at.pos <= ftello(muxer_f)) || + (end_at.type == END_AT_TIME && end_at.pos < mux_v->timer)) break; if(play_n_frames>=0){ @@ -1590,50 +1584,6 @@ if(stream) free_stream(stream); // kill cache thread return interrupted; } -static void parse_end_at(void) -{ - - end_at_type = END_AT_NONE; - if (!end_at_string) return; - - /* End at size parsing */ - { - char unit[4]; - - end_at_type = END_AT_SIZE; - - if(sscanf(end_at_string, "%lf%3s", &end_at, unit) == 2) { - if(!strcasecmp(unit, "b")) - ; - else if(!strcasecmp(unit, "kb")) - end_at *= 1024; - else if(!strcasecmp(unit, "mb")) - end_at *= 1024*1024; - else - end_at_type = END_AT_NONE; - } - else - end_at_type = END_AT_NONE; - } - - /* End at time parsing. This has to be last because of - * sscanf("%f", ...) below */ - if(end_at_type == END_AT_NONE) - { - int a,b; float d; - - end_at_type = END_AT_TIME; - - if (sscanf(end_at_string, "%d:%d:%f", &a, &b, &d) == 3) - end_at = 3600*a + 60*b + d; - else if (sscanf(end_at_string, "%d:%f", &a, &d) == 2) - end_at = 60*a + d; - else if (sscanf(end_at_string, "%f", &d) == 1) - end_at = d; - else - end_at_type = END_AT_NONE; - } -} #if 0 /* Flip the image in src and store the result in dst. src and dst may overlap. @@ -1659,7 +1609,7 @@ static uint8_t* flip_upside_down(uint8_t* dst, const uint8_t* src, int width, static float stop_time(demuxer_t* demuxer, muxer_stream_t* mux_v) { float timeleft = -1; if (play_n_frames >= 0) timeleft = mux_v->timer + play_n_frames * (double)(mux_v->h.dwScale) / mux_v->h.dwRate; - if (end_at_type == END_AT_TIME && (timeleft > end_at || timeleft == -1)) timeleft = end_at; + if (end_at.type == END_AT_TIME && (timeleft > end_at.pos || timeleft == -1)) timeleft = end_at.pos; if (next_edl_record && demuxer && demuxer->video) { // everything is OK to be checked float tmp = mux_v->timer + next_edl_record->start_sec - demuxer->video->pts; if (timeleft == -1 || timeleft > tmp) { diff --git a/mplayer.c b/mplayer.c index b2ef4bd194..827d222c71 100644 --- a/mplayer.c +++ b/mplayer.c @@ -250,6 +250,8 @@ static off_t step_sec=0; static int loop_times=-1; static int loop_seek=0; +static m_time_size_t end_at = { .type = END_AT_NONE, .pos = 0 }; + // A/V sync: int autosync=0; // 30 might be a good default value. @@ -4050,10 +4052,16 @@ while(sh_audio){ if(!sh_video) { // handle audio-only case: - if(!quiet) { - double a_pos = playing_audio_pts(sh_audio, d_audio, audio_out); + double a_pos=0; + if(!quiet || end_at.type == END_AT_TIME ) + a_pos = playing_audio_pts(sh_audio, d_audio, audio_out); + + if(!quiet) print_status(a_pos, 0, 0); - } + + if(end_at.type == END_AT_TIME && end_at.pos < a_pos) + eof = PT_NEXT_ENTRY; + } else { /*========================== PLAY VIDEO ============================*/ @@ -4296,6 +4304,10 @@ if(time_frame>0.001 && !(vo_flags&256)){ too_slow_frame_cnt++; /* printf ("PANIC: too slow frame (%.3f)!\n", j); */ + // FIXME: add size based support for -endpos + if ( end_at.type == END_AT_TIME && end_at.pos < sh_video->pts ) + eof = PT_NEXT_ENTRY; + if(vo_config_count) video_out->flip_page(); if (play_n_frames >= 0) { --play_n_frames; @@ -5214,6 +5226,15 @@ if(step_sec>0) { seek_to_sec = NULL; } + if (end_at.type != END_AT_NONE) { + if(end_at.type == END_AT_SIZE) { + mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_MPEndposNoSizeBased); + end_at.type = END_AT_NONE; + } else { + end_at.pos += rel_seek_secs; + } + } + /* Looping. */ if(eof==1 && loop_times>=0) { int l = loop_times;