[MPlayer-dev-eng] [PATCH] edl now works when seeking, more

Reynaldo H. Verdejo Pinochet reynaldo at opendot.cl
Wed Aug 25 07:39:14 CEST 2004


Hi all

Im trying to implement edl on mencoder, to do so
I have to remove some edl's code from mplayer.c and put it
on his own edl.c (mencoder will use the same functions)
while Im on it I have fixed some edl's flaws

* slighty faster
* removed MAX_EDL_ENTRIES limit (just reserve the memory we really need)
* really treat edl_records as a linked list (coz it is)
* edl now 'remembers' pending operations after a manual _seek_
* better way of handling Mute/Umute eliminates some nasty bugs
when manual seeking (scrwed up mute/unmute order, no audio after
seek, etc)
* seeking while on -edl mode now _WORKS_

Hope to get mencoder's edl working this weekend, please review and
apply this patches ASAP

Regards

  Reynaldo


-------------- next part --------------
--- mplayer.c	2004-08-25 00:18:34.000000000 -0400
+++ ../my_main/mplayer.c	2004-08-24 23:49:09.000000000 -0400
@@ -350,13 +350,13 @@
 #endif
 
 #ifdef USE_EDL
-struct edl_record edl_records[ MAX_EDL_ENTRIES ];
-int num_edl_records = 0;
-FILE* edl_fd = NULL;
+edl_record_ptr edl_records = NULL;
 edl_record_ptr next_edl_record = NULL;
-static char* edl_filename = NULL;
-static char* edl_output_filename = NULL;
+int edl_memory_slots = 0;
+int edl_operations = 0;
 short edl_decision = 0;
+FILE* edl_fd = NULL;
+int edl_mute_count = 0;
 #endif
 
 static unsigned int inited_flags=0;
@@ -960,100 +960,55 @@
 #endif
 
 #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 );
-	 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
- }
+
+if(edl_check_mode() == EDL_ERROR && edl_filename)
+{
+	mp_msg( MSGT_CPLAYER, MSGL_WARN, "Cant use -edl and -edlout at the same time\n" );
+	mp_msg( MSGT_CPLAYER, MSGL_WARN, "Not using EDL at all!!!\n" );
+	edl_filename = NULL;
+	edl_output_filename = NULL;
+	edl_records = NULL;
+	next_edl_record = edl_records; 
+}
+else if( edl_filename )
+{
+	edl_memory_slots=edl_count_entries();
+	if( edl_memory_slots > 0 )
+	{
+		edl_records=calloc( edl_memory_slots, sizeof(struct edl_record) );
+		if( edl_records == NULL )
+		{
+			mp_msg( MSGT_CPLAYER, MSGL_WARN, "Cant allocate enough memory to hold EDL data!!\n");
+			mp_msg( MSGT_CPLAYER, MSGL_WARN, "Disabling EDL!!!\n" );
+			edl_filename = NULL;
+			edl_output_filename = NULL;
+			edl_records = NULL;
+		}
+		else
+		{
+			if( ( edl_operations = edl_parse_file(edl_records) ) >0 )
+			{
+				mp_msg( MSGT_CPLAYER, MSGL_INFO, "Readed %d EDL actions\n",
+								edl_operations);
+			}else{
+				mp_msg( MSGT_CPLAYER, MSGL_INFO, "There are no EDL actions to take care of\n");
+			}
+		}
+	}
+
+	next_edl_record = edl_records;
+	
+}else if(edl_output_filename)
+{
+	if( ( edl_fd = fopen( edl_output_filename, "w" ) ) == NULL ) {
+		printf( "Error opening file [%s] for writing!\n", edl_output_filename );
+		edl_output_filename = NULL;
+		next_edl_record = edl_records;
+	}
+}
+	
+
+		
 #endif
 
     if(!filename){
@@ -2494,7 +2449,7 @@
 //================= EDL =========================================
 
 #ifdef USE_EDL
- if( next_edl_record->next ) { // Are we (still?) doing EDL?
+ if( next_edl_record ) { // Are we (still?) doing EDL?
   if ( !sh_video ) {
     mp_msg( MSGT_CPLAYER, MSGL_ERR, "Cannot use edit list without video. EDL disabled.\n" );
     next_edl_record->next = NULL;
@@ -2508,15 +2463,15 @@
        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(&mixer);
+	   edl_mute_count++; // seek needs this!!
 #ifdef DEBUG_EDL
        printf( "\nEDL_MUTE: [%f]\n", next_edl_record->start_sec );
 #endif
        edl_decision = 1;
-       next_edl_record = next_edl_record->next;
      }
+	 next_edl_record=next_edl_record->next;
    }
   }
  }
@@ -3544,24 +3470,57 @@
 	drop_frame_cnt=0;
 	too_slow_frame_cnt=0;
 	too_fast_frame_cnt=0;
-
+	
         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 >= sh_video->pts && edl_records[ x ].action != EDL_MUTE ) {
-	      next_edl_record = &edl_records[ x ];
-	      break;
-	    }
-	  }
-	} else {
-	  edl_decision = 0;
+/*
+ * We Saw a seek, have to rewind the edl operations stak
+ * and find the next edl action to take care off
+ */
+
+next_edl_record=edl_records;
+
+while( next_edl_record )
+{
+		/* trying to remember if we need to mute/unmute first
+		 * prior edl implementation lacks this
+		 */
+		if( next_edl_record->start_sec >= sh_video->pts )
+		{
+			if( edl_mute_count > 0 )
+			{
+				if( ( edl_mute_count % 2 ) == 0 &&
+								next_edl_record->mute_state == EDL_MUTE_END )
+				{
+					mixer_mute(&mixer);
+					edl_mute_count++;
+				}
+				if( ( edl_mute_count % 2 ) != 0 &&
+								next_edl_record->mute_state == EDL_MUTE_START )
+				{
+					mixer_mute(&mixer);
+					edl_mute_count++;
+				}
+			}else if( next_edl_record->mute_state == EDL_MUTE_END )
+			{
+				mixer_mute(&mixer);
+				edl_mute_count++;
+			}
+			break;
+		}
+		
+	next_edl_record=next_edl_record->next;
+	
+	if( !next_edl_record && ( edl_mute_count%2 )!= 0 && edl_mute_count > 0 )
+	{
+		mixer_mute(&mixer);
+		edl_mute_count++;
 	}
+}
+
       }
 #endif
   rel_seek_secs=0;
-------------- next part --------------
--- edl.h	2004-08-25 00:18:30.000000000 -0400
+++ ../my_main/edl.h	2004-08-24 20:12:32.000000000 -0400
@@ -5,8 +5,9 @@
 
 #define EDL_SKIP 0
 #define EDL_MUTE 1
-
-#define MAX_EDL_ENTRIES 1000
+#define EDL_ERROR -1
+#define EDL_MUTE_START 1
+#define EDL_MUTE_END 0 
 
 struct edl_record {
   float start_sec;
@@ -16,9 +17,19 @@
   float length_sec;
   long length_frame;
   short action;
+  short mute_state;
   struct edl_record* next;
 };
 
 typedef struct edl_record* edl_record_ptr;
 
+
+char *edl_filename;
+char *edl_output_filename;
+
+
+int edl_check_mode(void);
+int edl_count_entries(void);
+int edl_parse_file(struct edl_record *edl_records);
+
 #endif
-------------- next part --------------
--- /dev/null	2004-08-08 23:33:15.000000000 -0400
+++ edl.c	2004-08-24 23:50:48.000000000 -0400
@@ -0,0 +1,146 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "config.h"
+#include "edl.h"
+
+#ifdef USE_EDL
+
+int edl_check_mode(void)
+{
+		if(edl_filename && edl_output_filename)
+		{
+				return(EDL_ERROR);
+		}
+
+		return(1);
+}
+
+int edl_count_entries(void)
+{
+	FILE *fd = NULL;
+	int entries = 0;
+	int action = 0;
+	float start = 0;
+	float stop = 0;
+	char line[ 100 ];
+
+	if( edl_filename )
+	{
+		if( ( fd = fopen(edl_filename, "r" ) ) == NULL )
+		{
+			return(EDL_ERROR);
+			printf("Cant open edl file for reading!!\n");
+		}
+		else
+		{
+			while( fgets( line, 99, fd ) != NULL )
+			{
+				if( ( sscanf( line, "%f %f %d", &start, &stop, &action ) ) != 0 )
+				{
+					if(action == EDL_SKIP) entries+=1;
+					if(action == EDL_MUTE) entries+=2;
+				}
+			}
+			
+		}
+	}
+	else
+	{
+		return(EDL_ERROR);
+	}
+	
+	return(entries);
+}
+
+int edl_parse_file(struct edl_record *edl_records)
+{
+	FILE* fd;
+	char line[ 100 ];
+	float start, stop;
+	int action;
+	int record_count = 0;
+	int lineCount = 0;
+	struct edl_record *next_edl_record = edl_records;
+	
+	if( edl_filename )
+	{
+		if( ( fd = fopen( edl_filename, "r" ) ) == NULL ) {
+			return(EDL_ERROR);
+		} 
+		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( record_count > 0 )
+				{
+	     			if( start <= (next_edl_record - 1)->stop_sec )
+					{
+	       				printf( "Invalid EDL line [%d]: %s ", 
+										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", ( next_edl_record -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;
+	   				}
+	   				next_edl_record->action = action;
+	   				if( action == EDL_MUTE ) 
+					{
+						next_edl_record->length_sec = 0;
+						next_edl_record->start_sec = start;
+						next_edl_record->stop_sec = start;
+						next_edl_record->mute_state = EDL_MUTE_START;
+						next_edl_record++;
+						( next_edl_record-1 )->next = next_edl_record;
+						next_edl_record->action = action;
+						next_edl_record->length_sec = 0;
+						next_edl_record->start_sec = stop;
+						next_edl_record->stop_sec = stop;
+						next_edl_record->mute_state = EDL_MUTE_END;
+						
+					}
+					else
+					{
+						next_edl_record->length_sec = stop - start;
+						next_edl_record->start_sec = start;
+						next_edl_record->stop_sec = stop;
+					}
+						next_edl_record++;
+						
+						if( record_count >= 0)
+						{
+							(next_edl_record-1)->next=next_edl_record;
+						}
+
+						record_count++;
+			}
+			}	
+			
+			if( record_count > 0)
+			{
+				( next_edl_record - 1 )->next=NULL;
+			}
+		} 
+     fclose( fd );
+    }
+	else 
+	{
+		return(EDL_ERROR);	
+	}
+	
+	return(record_count);
+}
+
+#endif
-------------- next part --------------
--- Makefile	2004-08-23 00:31:53.000000000 -0400
+++ ../my_main/Makefile	2004-08-23 17:15:54.000000000 -0400
@@ -19,7 +19,7 @@
 DO_MAKE = @ for i in $(SUBDIRS); do $(MAKE) -C $$i $@; done
 endif
 
-SRCS_COMMON = cpudetect.c codec-cfg.c spudec.c playtree.c playtreeparser.c asxparser.c vobsub.c subreader.c sub_cc.c find_sub.c m_config.c m_option.c parser-cfg.c m_struct.c
+SRCS_COMMON = cpudetect.c codec-cfg.c spudec.c playtree.c playtreeparser.c asxparser.c vobsub.c subreader.c sub_cc.c find_sub.c m_config.c m_option.c parser-cfg.c m_struct.c edl.c
 SRCS_MENCODER = mencoder.c mp_msg-mencoder.c $(SRCS_COMMON) libao2/afmt.c divx4_vbr.c libvo/aclib.c libvo/osd.c libvo/sub.c libvo/font_load.c libvo/font_load_ft.c xvid_vbr.c parser-mecmd.c
 SRCS_MPLAYER = mplayer.c mp_msg.c $(SRCS_COMMON) mixer.c parser-mpcmd.c
 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/attachments/20040825/7d183db1/attachment.pgp>


More information about the MPlayer-dev-eng mailing list