changeset 8531:1aa2c9b460af

Merged EDL 0.5 patch - it's something like Quicktime's edit lists. (skip sections listed in a text file. it also supports creating them) patch by Michael Halcrow <mah69@email.byu.edu>
author arpi
date Mon, 23 Dec 2002 00:33:22 +0000
parents f667ebaec04e
children 9688aa033083
files DOCS/mplayer.1 cfg-common.h cfg-mplayer.h configure edl.h input/input.c input/input.h mplayer.c
diffstat 8 files changed, 249 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/mplayer.1	Sun Dec 22 23:13:26 2002 +0000
+++ b/DOCS/mplayer.1	Mon Dec 23 00:33:22 2002 +0000
@@ -206,6 +206,19 @@
 Use in combination with \-nosound and \-vo null for benchmarking only the
 video codec.
 .TP
+.B \-edl <filename>
+Enables edit decision list actions during playback. Video will be
+skipped over and audio will be muted and unmuted according to the
+entries in the given file. See DOCS/edl.html for details on how to use
+this.
+.TP
+.B \-edlout <filename>
+Creates a new file and writes edit decision list records to that
+file. During playback, when the user hits 'i', an entry to skip over
+the last two seconds of playback will be written to the file. This
+provides a starting point from which the user can fine-tune EDL
+entries later. See DOCS/edl.html for details.
+.TP
 .B \-framedrop (also see \-hardframedrop)
 Skips displaying some frames to maintain A/\:V sync on slow systems.
 Decoding of B frames is also skipped and video filters are not used.
--- a/cfg-common.h	Sun Dec 22 23:13:26 2002 +0000
+++ b/cfg-common.h	Mon Dec 23 00:33:22 2002 +0000
@@ -227,6 +227,11 @@
 
 #include "libmpdemux/tv.h"
 
+#ifdef USE_EDL
+extern char* edl_filename;
+extern char* edl_output_filename;
+#endif
+
 #ifdef USE_TV
 struct config tvopts_conf[]={
 	{"on", &tv_param_on, CONF_TYPE_FLAG, 0, 0, 1, NULL},
--- a/cfg-mplayer.h	Sun Dec 22 23:13:26 2002 +0000
+++ b/cfg-mplayer.h	Mon Dec 23 00:33:22 2002 +0000
@@ -203,6 +203,13 @@
             CONF_TYPE_PRINT, 0, 0, 0, NULL},
 	{"noalsa", "Option -noalsa has been removed, new audio code doesn't need it! Remove it from your config file!\n",
             CONF_TYPE_PRINT, 0, 0, 0, NULL},
+#ifdef USE_EDL
+	{"edl", &edl_filename,  CONF_TYPE_STRING, 0, 0, 0, NULL}, 
+	{"edlout", &edl_output_filename,  CONF_TYPE_STRING, 0, 0, 0, NULL}, 
+#else
+	{"edl", "MPlayer was compiled without EDL support\n", CONF_TYPE_PRINT, 0, 0, 0, NULL},
+	{"edlout", "MPlayer was compiled without EDL support\n", CONF_TYPE_PRINT, 0, 0, 0, NULL},
+#endif
 
 #ifdef HAVE_X11
 	{"display", &mDisplayName, CONF_TYPE_STRING, 0, 0, 0, NULL},
--- a/configure	Sun Dec 22 23:13:26 2002 +0000
+++ b/configure	Mon Dec 23 00:33:22 2002 +0000
@@ -140,6 +140,7 @@
   --disable-tv           disable TV Interface (tv/dvb grabbers) [enable]
   --disable-tv-v4l       disable Video4Linux TV Interface support [autodetect]
   --disable-tv-bsdbt848  disable BSD BT848 Interface support [autodetect]
+  --disable-edl          disable EDL (edit decision list) support [enable]
   --disable-rtc          disable RTC (/dev/rtc) on Linux [autodetect]
   --disable-streaming    disable network streaming support
                          (support for: http/mms/rtp) [enable]
@@ -1003,6 +1004,7 @@
 _tv=yes
 _tv_v4l=auto
 _tv_bsdbt848=auto
+_edl=yes
 _streaming=yes
 _vidix=auto
 _joystick=no
@@ -1153,6 +1155,8 @@
   --disable-alsa)	_alsa=no	;;
   --enable-tv)		_tv=yes		;;
   --disable-tv)		_tv=no		;;
+  --enable-edl)		_edl=yes	;;
+  --disable-edl)	_edl=no		;;
   --enable-tv-bsdbt848)	_tv_bsdbt848=yes	;;
   --disable-tv-bsdbt848)	_tv_bsdbt848=no	;;
   --enable-tv-v4l)	_tv_v4l=yes	;;
@@ -4210,6 +4214,16 @@
 fi
 echores "$_tv"
 
+echocheck "EDL support"
+if test "$_edl" = yes ; then
+  _def_edl='#define USE_EDL'
+  _inputmodules="edl $_inputmodules"
+else
+  _noinputmodules="edl $_noinputmodules"
+  _def_edl='#undef USE_EDL'
+fi
+echores "$_edl"
+
 echocheck "*BSD BrookTree 848 TV interface"
 if test "$_tv_bsdbt848" = auto ; then
  _tv_bsdbt848=no
@@ -5027,6 +5041,9 @@
 /* Enable TV Interface support */
 $_def_tv
 
+/* Enable EDL support */
+$_def_edl
+
 /* Enable Video 4 Linux TV interface support */
 $_def_tv_v4l
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edl.h	Mon Dec 23 00:33:22 2002 +0000
@@ -0,0 +1,25 @@
+// EDL version 0.5
+// Author: Michael Halcrow <mhalcrow@byu.edu>
+
+#ifndef EDLH
+#define EDLH
+
+#define EDL_SKIP 0
+#define EDL_MUTE 1
+
+#define MAX_EDL_ENTRIES 1000
+
+struct edl_record {
+  float start_sec;
+  long start_frame;
+  float stop_sec;
+  long stop_frame;
+  float length_sec;
+  long length_frame;
+  short action;
+  struct edl_record* next;
+};
+
+typedef struct edl_record* edl_record_ptr;
+
+#endif
--- a/input/input.c	Sun Dec 22 23:13:26 2002 +0000
+++ b/input/input.c	Mon Dec 23 00:33:22 2002 +0000
@@ -46,6 +46,9 @@
 
 static mp_cmd_t mp_cmds[] = {
   { MP_CMD_SEEK, "seek", 1, { {MP_CMD_ARG_INT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
+#ifdef USE_EDL
+  { MP_CMD_EDL_MARK, "edl_mark", 0, { {-1,{0}} } },
+#endif
   { MP_CMD_AUDIO_DELAY, "audio_delay", 1, { {MP_CMD_ARG_FLOAT,{0}}, {-1,{0}} } },
   { MP_CMD_QUIT, "quit", 0, { {-1,{0}} } },
   { MP_CMD_PAUSE, "pause", 0, { {-1,{0}} } },
@@ -246,6 +249,9 @@
   { { 't', 0 }, "sub_pos +1" },
   { { 'v', 0 }, "sub_visibility" },
   { { 'j', 0 }, "vobsub_lang" },
+#ifdef USE_EDL
+  { { 'i', 0 }, "edl_mark" },
+#endif
 #ifdef USE_TV
   { { 'h', 0 }, "tv_step_channel 1" },
   { { 'k', 0 }, "tv_step_channel -1" },
--- a/input/input.h	Sun Dec 22 23:13:26 2002 +0000
+++ b/input/input.h	Mon Dec 23 00:33:22 2002 +0000
@@ -37,6 +37,10 @@
 #define MP_CMD_GET_TIME_LENGTH 34
 #define MP_CMD_GET_PERCENT_POS 35
 #define MP_CMD_SUB_STEP 36
+//#define MP_CMD_TV_SET_CHANNEL 37
+#ifdef USE_EDL
+#define MP_CMD_EDL_MARK 38
+#endif
 
 #define MP_CMD_GUI_EVENTS       5000
 #define MP_CMD_GUI_LOADFILE     5001
--- a/mplayer.c	Sun Dec 22 23:13:26 2002 +0000
+++ b/mplayer.c	Mon Dec 23 00:33:22 2002 +0000
@@ -56,6 +56,10 @@
 #include <dvdnav.h>
 #endif
 
+#ifdef USE_EDL
+#include "edl.h"
+#endif
+
 #include "spudec.h"
 #include "vobsub.h"
 
@@ -298,6 +302,16 @@
 static int nortc;
 #endif
 
+#ifdef USE_EDL
+struct edl_record edl_records[ MAX_EDL_ENTRIES ];
+int num_edl_records = 0;
+FILE* edl_fd = NULL;
+edl_record_ptr next_edl_record = NULL;
+static char* edl_filename = NULL;
+static char* edl_output_filename = NULL;
+short edl_decision = 0;
+#endif
+
 static unsigned int inited_flags=0;
 #define INITED_VO 1
 #define INITED_AO 2
@@ -725,6 +739,102 @@
       exit(0);
     }
 
+#ifdef USE_EDL
+ {
+   FILE* fd;
+   char line[ 100 ];
+   float start, stop, duration;
+   int action;
+   int next_edl_array_index = 0;
+   int lineCount = 0;
+   next_edl_record = edl_records;
+   if( edl_filename ) {
+     if( ( fd = fopen( edl_filename, "r" ) ) == NULL ) {
+       printf( "Error opening EDL file [%s]!\n", edl_filename );
+       next_edl_record->next = NULL;
+     } else {
+       while( fgets( line, 99, fd ) != NULL ) {
+	 lineCount++;
+	 if( ( sscanf( line, "%f %f %d", &start, &stop, &action ) ) == 0 ) {
+	   printf( "Invalid EDL line: [%s]\n", line );
+	 } else {
+	   if( next_edl_array_index > 0 ) {
+	     edl_records[ next_edl_array_index-1 ].next = &edl_records[ next_edl_array_index ];
+	     if( start <= edl_records[ next_edl_array_index-1 ].stop_sec ) {
+	       printf( "Invalid EDL line [%d]: [%s]\n", lineCount, line );
+	       printf( "Last stop position was [%f]; next start is [%f]. Entries must be in chronological order and cannot overlap. Discarding EDL entry.\n", edl_records[ next_edl_array_index-1 ].stop_sec, start );
+	       continue;
+	     }
+	   }
+	   if( stop <= start ) {
+	     printf( "Invalid EDL line [%d]: [%s]\n", lineCount, line );
+	     printf( "Stop time must follow start time. Discarding EDL entry.\n" );
+	     continue;
+	   }
+	   edl_records[ next_edl_array_index ].action = action;
+	   if( action == EDL_MUTE ) {
+	     edl_records[ next_edl_array_index ].length_sec = 0;
+	     edl_records[ next_edl_array_index ].start_sec = start;
+	     edl_records[ next_edl_array_index ].stop_sec = start;
+	     next_edl_array_index++;
+	     if( next_edl_array_index >= MAX_EDL_ENTRIES-1 ) {
+	       break;
+	     }
+	     edl_records[ next_edl_array_index-1 ].next = &edl_records[ next_edl_array_index ];
+	     edl_records[ next_edl_array_index ].action = EDL_MUTE;
+	     edl_records[ next_edl_array_index ].length_sec = 0;
+	     edl_records[ next_edl_array_index ].start_sec = stop;
+	     edl_records[ next_edl_array_index ].stop_sec = stop;
+	   } else {
+	     edl_records[ next_edl_array_index ].length_sec = stop - start;
+	     edl_records[ next_edl_array_index ].start_sec = start;
+	     edl_records[ next_edl_array_index ].stop_sec = stop;
+	   }
+	   next_edl_array_index++;
+	   if( next_edl_array_index >= MAX_EDL_ENTRIES-1 ) {
+	     break;
+	   }
+	 }
+       }
+       if( next_edl_array_index > 0 ) {
+	 edl_records[ next_edl_array_index-1 ].next = &edl_records[ next_edl_array_index ];
+       }
+       edl_records[ next_edl_array_index ].start_sec = -1;
+       edl_records[ next_edl_array_index ].next = NULL;
+       num_edl_records = ( next_edl_array_index );
+     }
+     fclose( fd );
+   } else {
+     next_edl_record->next = NULL;
+   }
+   if( edl_output_filename ) {
+     if( edl_filename ) {
+       printf( "Sorry; EDL mode and EDL output mode are mutually exclusive! Disabling all EDL functions.\n" );
+       edl_output_filename = NULL;
+       edl_filename = NULL;
+       next_edl_record->next = NULL;
+     } else {
+       if( ( edl_fd = fopen( edl_output_filename, "w" ) ) == NULL ) {
+	 printf( "Error opening file [%s] for writing!\n" );
+	 edl_output_filename = NULL;
+	 next_edl_record->next = NULL;
+       }
+     }
+   }
+#ifdef DEBUG_EDL
+ {
+   printf( "EDL Records:\n" );
+   if( next_edl_record->next != NULL ) {
+     while( next_edl_record->next != NULL ) {
+       printf( "EDL: start [%f], stop [%f], action [%d]\n", next_edl_record->start_sec, next_edl_record->stop_sec, next_edl_record->action );
+       next_edl_record = next_edl_record->next;
+     }
+     next_edl_record = edl_records;
+   }
+ }
+#endif
+ }
+#endif
 
     if(!filename && !vcd_track && !dvd_title && !dvd_nav && !tv_param_on){
       if(!use_gui){
@@ -1955,6 +2065,32 @@
     dvdnav_stream_sleeping((dvdnav_priv_t*)stream->priv);
 #endif
 
+//================= EDL =========================================
+
+#ifdef USE_EDL
+ if( next_edl_record->next ) { // Are we (still?) doing EDL?
+   if( d_video->pts >= next_edl_record->start_sec ) {
+     if( next_edl_record->action == EDL_SKIP ) {
+       osd_function = OSD_FFW;
+       abs_seek_pos = 0;
+       rel_seek_secs = next_edl_record->length_sec;
+#ifdef DEBUG_EDL
+       printf( "\nEDL_SKIP: start [%f], stop [%f], length [%f]\n", next_edl_record->start_sec, next_edl_record->stop_sec, next_edl_record->length_sec );
+#endif
+       edl_decision = 1;
+       next_edl_record = next_edl_record->next;
+     } else if( next_edl_record->action == EDL_MUTE ) {
+       mixer_mute();
+#ifdef DEBUG_EDL
+       printf( "\nEDL_MUTE: [%f]\n", next_edl_record->start_sec );
+#endif
+       edl_decision = 1;
+       next_edl_record = next_edl_record->next;
+     }
+   }
+ }
+#endif
+
 //================= Keyboard events, SEEKing ====================
 
   current_module="key_events";
@@ -1985,6 +2121,14 @@
 	osd_function= (v > 0) ? OSD_FFW : OSD_REW;
       }
     } break;
+#ifdef USE_EDL
+    case MP_CMD_EDL_MARK:
+      if( edl_fd ) {
+	float v = d_video->pts;
+	fprintf( edl_fd, "%f %f %d\n", v-2, v, 0 );
+      }
+      break;
+#endif
     case MP_CMD_AUDIO_DELAY : {
       float v = cmd->args[0].v.f;
       audio_delay += v;
@@ -2665,12 +2809,18 @@
 #ifdef USE_OSD
         // Set OSD:
       if(osd_level){
-        int len=((demuxer->movi_end-demuxer->movi_start)>>8);
-        if (len>0 && sh_video){
-	   osd_visible=sh_video->fps; // 1 sec
-	   vo_osd_progbar_type=0;
-	   vo_osd_progbar_value=(demuxer->filepos-demuxer->movi_start)/len;
-	   vo_osd_changed(OSDTYPE_PROGBAR);
+#ifdef USE_EDL
+	if( !edl_decision ) {
+#else
+	  if( 1 ) { // Let the compiler optimize this out
+#endif
+	  int len=((demuxer->movi_end-demuxer->movi_start)>>8);
+	  if (len>0 && sh_video){
+	    osd_visible=sh_video->fps; // 1 sec
+	    vo_osd_progbar_type=0;
+	    vo_osd_progbar_value=(demuxer->filepos-demuxer->movi_start)/len;
+	    vo_osd_changed(OSDTYPE_PROGBAR);
+	  }
 	}
       }
 #endif
@@ -2686,6 +2836,22 @@
         if(vo_spudec) spudec_reset(vo_spudec);
       }
   }
+#ifdef USE_EDL
+      {
+	int x;
+	if( !edl_decision ) {
+	  for( x = 0; x < num_edl_records; x++ ) { // FIXME: do binary search
+	    // Find first EDL entry where start follows current time
+	    if( edl_records[ x ].start_sec >= d_video->pts && edl_records[ x ].action != EDL_MUTE ) {
+	      next_edl_record = &edl_records[ x ];
+	      break;
+	    }
+	  }
+	} else {
+	  edl_decision = 0;
+	}
+      }
+#endif
   rel_seek_secs=0;
   abs_seek_pos=0;
   frame_time_remaining=0;