changeset 19973:02a18c52a42a

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....
author ptt
date Mon, 25 Sep 2006 16:47:56 +0000
parents 6e103c537e6d
children b71fdb42f9dc
files DOCS/man/en/mplayer.1 cfg-common.h cfg-mencoder.h help/help_mp-en.h m_option.c m_option.h mencoder.c mplayer.c
diffstat 8 files changed, 140 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/man/en/mplayer.1	Mon Sep 25 16:16:19 2006 +0000
+++ b/DOCS/man/en/mplayer.1	Mon Sep 25 16:47:56 2006 +0000
@@ -1273,6 +1273,30 @@
 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 @@
 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 <format>
 Can be used to override the audio format tag of the output file.
 .sp 1
--- a/cfg-common.h	Mon Sep 25 16:16:19 2006 +0000
+++ b/cfg-common.h	Mon Sep 25 16:47:56 2006 +0000
@@ -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
--- a/cfg-mencoder.h	Mon Sep 25 16:16:19 2006 +0000
+++ b/cfg-mencoder.h	Mon Sep 25 16:47:56 2006 +0000
@@ -185,8 +185,6 @@
 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},
--- a/help/help_mp-en.h	Mon Sep 25 16:16:19 2006 +0000
+++ b/help/help_mp-en.h	Mon Sep 25 16:47:56 2006 +0000
@@ -201,6 +201,7 @@
 #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
 
--- a/m_option.c	Mon Sep 25 16:16:19 2006 +0000
+++ b/m_option.c	Mon Sep 25 16:47:56 2006 +0000
@@ -1175,6 +1175,78 @@
 };
 
 
+// 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"
--- a/m_option.h	Mon Sep 25 16:16:19 2006 +0000
+++ b/m_option.h	Mon Sep 25 16:47:56 2006 +0000
@@ -28,6 +28,7 @@
 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_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 @@
 #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)
 
 /////////////////////////////////////////////////////////////////////////////////////////////
 
--- a/mencoder.c	Mon Sep 25 16:16:19 2006 +0000
+++ b/mencoder.c	Mon Sep 25 16:47:56 2006 +0000
@@ -252,10 +252,10 @@
 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 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 @@
 	}
 }
 
-parse_end_at();
-
 if (seek_to_sec) {
     int a,b; float d;
 
@@ -1080,7 +1074,7 @@
 	}
 
 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 @@
     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 @@
 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 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) {
--- a/mplayer.c	Mon Sep 25 16:16:19 2006 +0000
+++ b/mplayer.c	Mon Sep 25 16:47:56 2006 +0000
@@ -250,6 +250,8 @@
 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 @@
 
 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 @@
 		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 @@
      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;