diff -PNaur MPlayer-20030526/DOCS/en/documentation.html MPlayer-20030526+EDL/DOCS/en/documentation.html
--- MPlayer-20030526/DOCS/en/documentation.html 2003-05-26 00:48:05.000000000 +0200
+++ MPlayer-20030526+EDL/DOCS/en/documentation.html 2003-05-26 15:01:21.000000000 +0200
@@ -1259,58 +1259,71 @@
in the horizontal direction due to a hardware limitation.
-
-
-The edit decision list (EDL) system allows you to automatically skip or mute
- sections of videos during playback, based on a movie specific EDL
- configuration file.
-
-This is useful for those who may want to watch a film in "family-friendly"
- mode. You can cut out any violence, profanity, Jar-Jar Binks .. from a movie
- according to your own personal preferences. Aside from this, there are other
- uses, like automatically skipping over commercials in video files you
- watch.
-
-The EDL file format is pretty bare-bones. Once the EDL system has reached a
- certain level of maturity, an XML-based file format will probably be
- implemented (keeping backwards compatibility with previous EDL formats).
+
-The maximum number of EDL entries for the current incarnation of EDL is 1000.
- If you happen to need more, change the #define MAX_EDL_ENTRIES
- in the edl.h
file.
+The edit decision list (EDL) system allows you to automatically skip or
+mute sections of videos during playback, or change the A/V sync based on
+a movie specific EDL configuration file. It is now implemented in
+the mencoder too.
-
-
-Include the -edl <filename>
flag when you run MPlayer,
- with the name of the EDL file you want applied to the video.
-
-
-
-The current EDL file format is:
-
-[begin second] [end second] [action]
-
-Where the seconds are floating-point numbers and the action is either
- 0
for skip or 1
for mute. Example:
-
-
-5.3 7.1 0
-15 16.7 1
-420 422 0
-
-
-This will skip from second 5.3 to second 7.1 of the video, then mute at
- 15 seconds, unmute at 16.7 seconds and skip from second 420 to second
- 422 of the video. These actions will be performed when the playback timer
- reaches the times given in the file.
+This is useful for those who may want to watch a film in "family-friendly"
+ mode. You can cut out any violence, profanity, Jar-Jar Binks .. from a
+movie according to your own personal preferences. Aside from this, there
+are other uses, like automatically skipping over commercials in video files
+you watch.
-To create an EDL file to work from, use the
- -edlout <filename>
flag. During playback, when you want to
- mark the previous two seconds to skip over, hit i
. A
- corresponding entry will be written to the file for that time. You can then go
- back and fine-tune the generated EDL file.
+
-
+Include the -edl <filename>
flag when you run MPlayer,
+ with the name of the EDL file you want applied to the video.
+
+
+
+The current EDL file format is:
+ <start_time> <command> [<parameter(s)>]
+
+Where the time can be floating-point numbers or [[hh:]mm:]ss format time,
+and the action is one of the followings:
+
+
+ - SKIP <end_time>
+This command skips from start_time to end_time. It may cause A/V delay problems,
+which can be corrected using a DELAY entry.
+
+ - MUTE <end_time>
+It mutes the sound in the given interval (not yet implemented in the mencoder).
+
+ - DELAY <av_delay>
+Changes the A/V delay at the given time. The av_delay value is compatible
+with -delay option and the value displayed on the OSD.
+
+ - MC <mc_value>
+It changes the A/V delay correction speed. See the -mc option for details.
+
+ - LOOP <end_time> <no_of_loops>
+It repeats from start_time to end_time no_of_loops times. LOOP entries can
+overlap and they can be nested. This entry needs two parameters.
+
+ - STOP
+Exits at start_time.
+
+
+5.3 skip 7.1
15 mute 16.7
420 skip 422
+
+This will skip from second 5.3 to second 7.1 of the video, then mute at
+ 15 seconds, unmute at 16.7 seconds and skip from second 420 to second
+ 422 of the video. These actions will be performed when the playback timer
+ reaches the times given in the file.
+
+1:15:4 delay 0.3
+1:20:0 loop 1:40:0
+10
+1:45:0 stop
+
+This will change the A/V delay to 0.3 seconds at 1:15:4, plays from 1:20:0
+to 1:40:0 10 times, and exits at 1:45:0.
+
+
diff -PNaur MPlayer-20030526/DOCS/hu/documentation.html MPlayer-20030526+EDL/DOCS/hu/documentation.html
--- MPlayer-20030526/DOCS/hu/documentation.html 2003-05-19 08:54:50.000000000 +0200
+++ MPlayer-20030526+EDL/DOCS/hu/documentation.html 2003-05-26 15:04:24.000000000 +0200
@@ -1213,59 +1213,97 @@
-
-
-Az edit decision list (EDL) rendszer segítségével lehetővé válik a film
- megadott időintervallumainak automatikus átugrása, vagy a hang
- kikapcsolása.
-
-Ennek hasznossága akkor mutatkozik meg amikor egy filmet "családbarát"
- módban akarsz megtekinteni: kivágható az erőszak, az illetlen beszéd,
- Jar-Jar Binks, stb. Valamint reklámok átugrására is használható.
-
-Az EDL fileformátum eléggé puritán. Amint az EDL rendszer megérik,
- valószínűleg egy XML-féle formátum lesz implementálva (a régi formátummal
- kompatibilisen).
+
+
+Az Edit Decision List (EDL) rendszer segítségével lehetővé válik a film
+ megadott időintervallumainak automatikus átugrása, vagy a hang kikapcsolása.
+
+Ennek hasznossága akkor mutatkozik meg amikor egy filmet "családbarát"
+ módban akarsz megtekinteni: kivágható az erőszak, az illetlen beszéd, stb.
+Valamint reklámok átugrására is használható.
+
+
+
+
+Az MPlayer indításakor add meg az -edl <filenév>
+parancsot, a filmhez használandó EDL file nevét behelyettesítve.
+
+
+
+
+ Az EDL fájl formátuma a következő:
+<időpont> PARANCS [paraméterek]
+
+
+
+ - Az időpont többféleképpen megadható. Kompatibilis az eredeti
+ verzióval, ahol másodpercben kell megadni, de lehet óra:perc:másodperc
+ formában is. A másodperc törtszám is lehet, de vigyázni kell a helyi beállításokra
+ (az 1.234 és az 1,234 nem ugyanaz). Az adott parancs ebben az időpontban
+ hajtódik végre. A sorokat nem kötelező időrendi sorrendben megadni.
+ - A paraméterek feldolgozása mindig a megadott parancstól
+ függ.
+
+ - A PARANCS pedig a következők egyike lehet:
+
+
+
+ - SKIP <időpont>
+ A paraméterben megadott időre ugrik, vagyis kihagy egy részt a
+filmből.
+ Úgy vettem észre, hogy a hang az ilyen ugrásoknál elcsúszhat, ami DELAY
+ parancsokkal kijavítható.
+ - MUTE <időpont>
+ Elnémítja a hangot a paraméterben megadott ideig. Egyelőre csak
+ az mplayerben működik, a mencoder figyelmen kívül hagyja.
+
+ - DELAY <offszet>
+ A hang szinkron pozícióját (amit a +/- gombokkal lehet az mplayernél
+ menet közben állítani) a megadott offszettel eltolja.
+ Ez most kompatibilis a -delay opcióval és az OSD-n megjelenő értékkel,
+tehát pozitív érték sietteti a hangot a képhez képest, negatív pedig késlelteti.
+ - MC <érték>
+ Megfelel a -mc opciónak (lásd a doksiban), a hang csúsztatás sebességét
+korlátozza. Negatív értékkel lehet kikapcsolni.
+ - LOOP <időpont> <hányszor>
+ Többször lejátssza a megadott tartományt. A LOOP parancsok egymásba ágyazhatók,
+és átfedés is lehet közöttük.
+ Ez a parancs két paramétert kér.
+
+ - STOP <időpont>
+ Kilép a megadott időpontban.
+
+
+
+Példa:
+
+33 skip 1:12.8
+ 2:20 delay -0.4
+ 4:19 mute 5:20
+ 1:00 loop 2:00 10
+
+Az első sor átugorja a 33 másodperc és az 1 perc 12.8 másodperc közötti
+ részt.
+ A második sor pedig 2 perc 20 másodpercnél a hangot 0.4 másodperccel
+ késlelteti a képhez képest. Itt az eltolás nem rögtön következik be (mert
+ akkor ugye hirtelen meg kéne állítani vagy ugratni a képet), hanem lassan,
+ szóval célszerű 1-2 másodperccel korábbra programozni.
+ A harmadik sor kikapcsolja a hangot a két megadott időpont között.
+ Ez egyelőre csak mplayer-ben működik.
+ Az utolsó sor pedig tízszer lejátssza az 1:00 és 2:00 közötti részt.
+5.3 skip 7.1
+15 mute 16.7
+420 skip 422
+
+
+
+Ez a video 5.3-adik másodpercénél átugrik a 7.1-ikre, aztán 15 másodpercnél
+ kikapcsolja a hangot egészen a 16.7-ig, 420 másodpercnél pedig 2 másodpercet
+ ugrik. Ezek a cselekmények akkor hajtódnak végre ha a timer a megadott
+ időhöz ért.
+
+
-Jelenleg maximum 1000 bejegyzést lehet használni, ha ez nem elég, az
- edl.h
file-ban a #define MAX_EDL_ENTRIES
értékét
- kell megnövelni.
-
-
-
-
-Az MPlayer indításakor add meg az -edl <filenév>
- parancsot, a filmhez használandó EDL file nevét behelyettesítve.
-
-
-
-
-A jelenlegi EDL formátum így épül fel:
-
-[kezdő másodperc] [vége másodperc] [cselekmény]
-
-A másodpercek helyére lebegőpontos számokat kell írni, a cselekmény pedig
- vagy 0
az átugráshoz, vagy 1
a hang elnémításához.
- Például:
-
-
-5.3 7.1 0
-15 16.7 1
-420 422 0
-
-
-Ez a video 5.3-adik másodpercénél átugrik a 7.1-ikre, aztán 15 másodpercnél
- kikapcsolja a hangot egészen a 16.7-ig, 420 másodpercnél pedig 2 másodpercet
- ugrik. Ezek a cselekmények akkor hajtódnak végre ha a timer a megadott
- időhöz ért.
-
-Egy EDL file elkészítéséhez használd az -edlout <filenév>
- parancsot, és lejátszás közben mikor azt akarod hogy az előző két
- másodperc legyen átugorva, nyomd meg az i
billentyűt. Egy ennek
- megfelelő parancs íródik a megadott nevű EDL file-ba. Kilépés után
- tetszőlegesen finomhangolható a file.
-
-
diff -PNaur MPlayer-20030526/Makefile MPlayer-20030526+EDL/Makefile
--- MPlayer-20030526/Makefile 2003-05-17 14:23:32.000000000 +0200
+++ MPlayer-20030526+EDL/Makefile 2003-05-26 13:21:13.000000000 +0200
@@ -22,7 +22,7 @@
DO_MAKE = @ for i in $(SUBDIRS); do $(MAKE) -C $$i $@; done
endif
-SRCS_COMMON = cpudetect.c codec-cfg.c cfgparser.c my_profile.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 cfgparser.c my_profile.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
diff -PNaur MPlayer-20030526/cfg-mencoder.h MPlayer-20030526+EDL/cfg-mencoder.h
--- MPlayer-20030526/cfg-mencoder.h 2003-03-03 12:03:17.000000000 +0100
+++ MPlayer-20030526+EDL/cfg-mencoder.h 2003-05-26 13:21:13.000000000 +0200
@@ -220,6 +220,7 @@
// {"quiet", &quiet, CONF_TYPE_FLAG, 0, 0, 1, NULL},
{"verbose", &verbose, CONF_TYPE_INT, CONF_RANGE|CONF_GLOBAL, 0, 100, NULL},
{"v", cfg_inc_verbose, CONF_TYPE_FUNC, CONF_GLOBAL, 0, 0, NULL},
+ {"edl", &edl_filename, CONF_TYPE_STRING, 0, 0, 0, NULL},
// {"-help", help_text, CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
// {"help", help_text, CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
// {"h", help_text, CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
diff -PNaur MPlayer-20030526/edl.c MPlayer-20030526+EDL/edl.c
--- MPlayer-20030526/edl.c 1970-01-01 01:00:00.000000000 +0100
+++ MPlayer-20030526+EDL/edl.c 2003-05-26 13:21:13.000000000 +0200
@@ -0,0 +1,256 @@
+#include
+#include
+#include
+
+#ifdef NEW_CONFIG
+#include "m_option.h"
+#include "m_config.h"
+#include "parser-mecmd.h"
+#else
+#include "cfgparser.h"
+#include "playtree.h"
+#endif
+
+#include "edl.h"
+
+edl_record_ptr edl_list = NULL, ActualEDL = NULL;
+
+typedef struct {
+ const char *const Name;
+ const int Value;
+ const int Valid;
+} EDL_List_t;
+
+static EDL_List_t Namelist[]={
+ EDL_STRING_LIST
+};
+
+
+static int convert_time(const char *time, float *val)
+{
+ float sec;
+ int hour, min;
+ if (sscanf(time, "%d:%d:%f", &hour, &min, &sec) == 3) {
+ *val = 3600*hour + 60*min + sec;
+ } else if (sscanf(time, "%d:%f", &min, &sec) == 2) {
+ *val = 60*min + sec;
+ } else if (sscanf(time, "%f", &sec) == 1) {
+ *val = sec;
+ } else {
+ printf("Error parsing edl file: <%s>\n", time);
+ return -1;
+ }
+ return 0;
+}
+
+
+static int convert_edl_action(const char *action)
+{
+ EDL_List_t *fut;
+ for (fut=Namelist; fut->Name; fut++)
+ if (fut->Valid && !strcasecmp(action, fut->Name))
+ return fut->Value;
+ printf("Invalid action string in the EDL file: <%s>\n", action);
+ return -1;
+}
+
+
+static const char *get_edl_command_name(int cmd_type)
+{
+ EDL_List_t *fut;
+ for (fut=Namelist; fut->Name; fut++)
+ if (fut->Value == cmd_type)
+ return fut->Name;
+ return "Unknown";
+}
+
+
+static edl_record_ptr insert_edl_entry(float From, int Action)
+{
+ edl_record_ptr new_one, current, *nxt;
+
+ for (nxt= &edl_list, current=NULL;
+ *nxt && (*nxt)->start_sec < From;
+ current= *nxt,
+ nxt = &((*nxt)->next)) ;
+ /* Use calloc() instead of malloc() to clear the allocated data: */
+ new_one = (edl_record_ptr)calloc(1, sizeof(struct edl_record));
+ if (new_one) {
+ new_one->start_sec = From;
+ new_one->action = Action;
+ new_one->next = *nxt;
+ if (*nxt)
+ (*nxt)->prev = new_one;
+ *nxt = new_one;
+ new_one->prev = current;
+ } else {
+ printf("Memory allocation error in EDL handler. \n");
+ }
+ return new_one;
+}
+
+
+int open_edl_file(char *ifile)
+{
+ FILE *file;
+ char sor[100], *from, *value[4], *action;
+ edl_record_ptr current;
+ int Error;
+
+ printf("EDL version " EDL_VERSION " \n");
+#ifdef DEBUG_EDL
+ printf("Opening EDL file... (%s)\n", ifile);
+#endif
+ if ((file = fopen(ifile, "r")) == NULL) {
+ printf("Error opening EDL file. EDL is not used. \n");
+ } else {
+ Error = insert_edl_entry(0.0, EDL_BEGIN_PROGRAM) == NULL;
+ while (!Error && fgets(sor, sizeof(sor), file)) {
+ if (sor[0] != '#' && sor[0] != '\r' && sor[0] != '\n' && sor[0] != '\0') {
+ float From;
+ int Action, i;
+ static const char Delim[]=" \t\r\n";
+ edl_record_ptr Actual;
+
+ /* First parameter: the time */
+ from = strtok(sor, Delim);
+ /* Second parameter: the action */
+ action = strtok(NULL, Delim);
+ /* The maximum number of 4 parameters are allowed now: */
+ if (action == NULL) action = "";
+ for (i=0; i<(sizeof(value)/sizeof(value[0])); i++) {
+ value[i] = strtok(NULL, Delim);
+ if (value[i] == NULL) value[i] = "";
+ }
+#ifdef DEBUG_EDL
+ printf("edl line: \"%s\", \"%s\", (\"%s\",\"%s\",\"%s\",\"%s\")\n",
+ from, action, value[0], value[1], value[2], value[3]);
+#endif
+ if (convert_time(from, &From) < 0) Error++;
+ if ((Action = convert_edl_action(action)) < 0) Error++;
+ /* Insert an entry to the list. Note that the data areas
+ * must be filled later! */
+ if ((Actual = insert_edl_entry(From, Action)) == NULL) Error++;
+ else switch (Action) {
+ case EDL_SKIP:
+ case EDL_AVSYNC:
+ if (convert_time(value[0], &Actual->value.f) < 0) Error++;
+ break;
+ case EDL_MUTE:
+ {
+ float Value;
+ if (convert_time(value[0], &Value) < 0 ||
+ insert_edl_entry(From+Value, EDL_UNMUTE) == NULL) {
+ Error++;
+ }
+ }
+ break;
+ case EDL_LOOP:
+ {
+ float Value;
+ edl_record_ptr Next;
+ /* This is the LOOP END position: */
+ if (convert_time(value[0], &Value) < 0 ||
+ /* New entry for LOOP END: */
+ (Next = insert_edl_entry(Value, EDL_LOOP_END)) == NULL ||
+ /* ...and the number of loops: */
+ sscanf(value[1], "%d", &Next->value.loop.n) != 1) {
+ Error++;
+ } else {
+ /* Pointer to the loop back: */
+ Next->value.loop.back = Actual;
+ Actual->value.loop.back = Next;
+ }
+ }
+ break;
+ }
+ }
+ }
+ fclose(file);
+ }
+ Error += insert_edl_entry(1e10, EDL_NOP) == NULL;
+ if (Error) printf("EDL ERROR: Abnormal termination. \n");
+ ActualEDL = edl_list;
+#ifdef DEBUG_EDL
+ for (current=edl_list; current; current=current->next) {
+ printf("EDL-> %s at %f \n", get_edl_command_name(current->action),
+ current->start_sec);
+ if (current->next == NULL) {
+ edl_record_ptr fut;
+ for (fut=current; fut; fut=fut->prev) {
+ printf("EDL<- %s at %f \n", get_edl_command_name(fut->action),
+ fut->start_sec);
+ }
+ }
+ }
+#endif
+ return 0;
+}
+
+
+/* This function returns 1 if seeking hits an EDL entry.
+ * Don't worry about speed here: it is called only once for each seek. */
+int edl_seek(float time_to_seek, int forward)
+{
+#ifdef DEBUG_EDL
+ printf("\nEDL seek to %f ... \n", time_to_seek);
+#endif
+ if (ActualEDL) {
+ float edl_mode = -1.0;
+#ifdef DEBUG_EDL
+ printf("EDL seek current: %f ...\n", ActualEDL->start_sec);
+#endif
+ if (forward) {
+ /* forward seek: */
+ edl_mode = 1.0;
+#ifdef DEBUG_EDL
+ printf("EDL: Forward seeking.\n", ActualEDL->start_sec);
+#endif
+ } else {
+ /* backward seek: */
+#ifdef DEBUG_EDL
+ printf("EDL: Backward seeking.\n", ActualEDL->start_sec);
+#endif
+ while (ActualEDL->prev) {
+ switch (ActualEDL->action) {
+ case EDL_LOOP:
+ /* Restart all the previous loop counters: */
+ ActualEDL->value.loop.n = 0;
+ break;
+ }
+ ActualEDL = ActualEDL->prev;
+ }
+ }
+ while (ActualEDL && time_to_seek >= ActualEDL->start_sec) {
+ if (ActualEDL->action == EDL_SKIP) {
+ if (time_to_seek < ActualEDL->value.f) {
+ /* The given time hits this EDL entry.
+ * Seeking position must be corrected according to
+ * the direction: */
+ float retval = edl_mode *
+ (ActualEDL->value.f - ActualEDL->start_sec);
+ /* In the case of forward seeking we seek behind the
+ * current entry, so step to the next: */
+ if (forward) ActualEDL = ActualEDL->next;
+#ifdef DEBUG_EDL
+ printf("EDL seek hit: %f (%f, %d)...\n", ActualEDL->start_sec, time_to_seek, ActualEDL->action);
+#endif
+ return retval;
+ }
+ ActualEDL = ActualEDL->next;
+ } else {
+ ExecActualEDL();
+ }
+ }
+#ifdef DEBUG_EDL
+ printf("EDL seek next: %f ...\n", ActualEDL->start_sec);
+#endif
+ }
+ return 0.0;
+}
+
+
+/*
+vim:ts=8 sw=4 sta nowrap
+*/
+
diff -PNaur MPlayer-20030526/edl.h MPlayer-20030526+EDL/edl.h
--- MPlayer-20030526/edl.h 2003-02-03 10:26:40.000000000 +0100
+++ MPlayer-20030526+EDL/edl.h 2003-05-26 13:21:13.000000000 +0200
@@ -1,24 +1,65 @@
// EDL version 0.5
-#ifndef EDLH
-#define EDLH
-
-#define EDL_SKIP 0
-#define EDL_MUTE 1
+#ifndef EDL_HEADER
+#define EDL_HEADER
+#define EDL_VERSION "0.4"
+
+enum edl_actions {
+ EDL_BEGIN_PROGRAM = 0,
+ EDL_SKIP,
+ EDL_MUTE,
+ EDL_UNMUTE,
+ EDL_AVSYNC,
+ EDL_STOP,
+ EDL_MC,
+ EDL_LOOP,
+ EDL_LOOP_END,
+ EDL_NOP
+};
-#define MAX_EDL_ENTRIES 1000
+#define EDL_STRING_LIST \
+/* Name: Value: Real/Pseudo: */ \
+ { "skip", EDL_SKIP, 1 }, \
+ { "0", EDL_SKIP, 1 }, \
+ { "mute", EDL_MUTE, 1 }, \
+ { "1", EDL_MUTE, 1 }, \
+ { "delay", EDL_AVSYNC, 1 }, \
+ { "2", EDL_AVSYNC, 1 }, \
+ { "stop", EDL_STOP, 1 }, \
+ { "mc", EDL_MC, 1 }, \
+ { "loop", EDL_LOOP, 1 }, \
+ { "LOOP_END", EDL_LOOP_END, 0 }, \
+ { "NOP", EDL_NOP, 0 }, \
+ { "BEGIN", EDL_BEGIN_PROGRAM, 0 }, \
+ { NULL, 0, 0 }
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;
+ float start_sec;
+ union {
+ float f;
+ struct {
+ int n;
+ struct edl_record *back;
+ } loop;
+ } value;
+ short action;
+ struct edl_record *next, *prev;
};
typedef struct edl_record* edl_record_ptr;
+extern edl_record_ptr ActualEDL;
+
+extern int open_edl_file(char *);
+extern int edl_seek(float, int);
+extern void ExecActualEDL(void);
+
+/* If you want see some edl-related debug messages, uncomment the next line: */
+//#define DEBUG_EDL
+
#endif
+
+/*
+vim:ts=8 sw=4 sta nowrap
+*/
+
diff -PNaur MPlayer-20030526/mencoder.c MPlayer-20030526+EDL/mencoder.c
--- MPlayer-20030526/mencoder.c 2003-05-23 17:01:02.000000000 +0200
+++ MPlayer-20030526+EDL/mencoder.c 2003-05-26 13:31:21.000000000 +0200
@@ -47,6 +47,10 @@
#include "playtree.h"
#endif
+#ifdef USE_EDL
+#include "edl.h"
+#endif
+
#include "libmpdemux/stream.h"
#include "libmpdemux/demuxer.h"
#include "libmpdemux/stheader.h"
@@ -102,6 +106,9 @@
char* audio_lang=NULL;
char* dvdsub_lang=NULL;
static char* spudec_ifo=NULL;
+#ifdef USE_EDL
+static char* edl_filename=NULL;
+#endif
static char** audio_codec_list=NULL; // override audio codec
static char** video_codec_list=NULL; // override video codec
@@ -313,6 +320,11 @@
extern void print_wave_header(WAVEFORMATEX *h);
+void ExecActualEDL(void)
+{
+ /* Do nothing */
+}
+
int main(int argc,char* argv[]){
stream_t* stream=NULL;
@@ -362,6 +374,8 @@
unsigned int timer_start;
+static float edl_avsync=0.0;
+
mp_msg_init();
mp_msg_set_level(MSGL_STATUS);
mp_msg(MSGT_CPLAYER,MSGL_INFO,"%s",banner_text);
@@ -403,6 +417,11 @@
if(!filelist) mencoder_exit(1, "error parsing cmdline");
m_entry_set_options(mconfig,&filelist[0]);
filename = filelist[0].name;
+#ifdef USE_EDL
+ if (edl_filename) open_edl_file(edl_filename);
+ else
+#endif
+ printf("No EDL file given.\n");
// Warn the user if he put more than 1 filename ?
#else
playtree = play_tree_new();
@@ -926,9 +945,73 @@
if(play_n_frames>=0){
--play_n_frames;
- if(play_n_frames<0) break;
+ if(play_n_frames<0) {
+ExitFromLoop: break;
+ }
}
+#ifdef USE_EDL
+ if (ActualEDL && d_video->pts >= ActualEDL->start_sec) {
+ switch (ActualEDL->action) {
+ case EDL_SKIP:
+#ifdef DEBUG_EDL
+ printf("\nEDL at %f: Seek to %f \n",
+ d_video->pts, ActualEDL->value.f);
+#endif
+ demux_seek(demuxer, ActualEDL->value.f, 1);
+ break;
+ case EDL_MUTE:
+ printf("TODO: mute is not implemented yet.\n");
+ break;
+ case EDL_UNMUTE:
+ printf("TODO: unmute is not implemented yet.\n");
+ break;
+ case EDL_AVSYNC:
+ /* A/V sync must be corrected by the given value. */
+ edl_avsync = ActualEDL->value.f;
+#ifdef DEBUG_EDL
+ printf( "\nEDL_AVSYNC: [%f]\n", edl_avsync );
+#endif
+ break;
+ case EDL_MC:
+ default_max_pts_correction = ActualEDL->value.f;
+#ifdef DEBUG_EDL
+ printf( "\nEDL_MC: [%f]\n", default_max_pts_correction );
+#endif
+ break;
+#ifdef DEBUG_EDL
+ case EDL_LOOP:
+ printf("\nEDL_LOOP start at %f: %d of %d \n",
+ ActualEDL->start_sec, ActualEDL->value.loop.n+1,
+ ActualEDL->value.loop.back->value.loop.n);
+ break;
+#endif
+ case EDL_LOOP_END:
+ {
+ edl_record_ptr Back = ActualEDL->value.loop.back;
+#ifdef DEBUG_EDL
+ printf("\nEDL_LOOP_END at %f \n", ActualEDL->start_sec);
+#endif
+ if (++(Back->value.loop.n) < ActualEDL->value.loop.n) {
+ demux_seek(demuxer, Back->start_sec, 1);
+ ActualEDL = Back;
+ /* Do not step to the next EDL entry: */
+ goto DoNotStep;
+ }
+ }
+ break;
+ case EDL_STOP:
+#ifdef DEBUG_EDL
+ printf( "\nEDL_STOP at %f \n", d_video->pts);
+#endif
+ goto ExitFromLoop;
+ break;
+ }
+ ActualEDL = ActualEDL->next;
+DoNotStep:;
+ }
+#endif
+
if(sh_audio){
// get audio:
while(mux_a->timer-audio_preloadtimer){
@@ -1152,7 +1235,7 @@
}
v_pts=sh_video ? sh_video->pts : d_video->pts;
// av = compensated (with out buffering delay) A-V diff
- AV_delay=(a_pts-v_pts); AV_delay-=mux_a->timer-(mux_v->timer-(v_timer_corr+v_pts_corr));
+ AV_delay=(a_pts-v_pts); AV_delay-=mux_a->timer-(mux_v->timer-(v_timer_corr+edl_avsync+v_pts_corr));
// compensate input video timer by av:
x=AV_delay*0.1f;
if(x<-max_pts_correction) x=-max_pts_correction; else
@@ -1617,3 +1700,8 @@
mencoder_exit(0, NULL);
}
#endif
+
+/*
+vim:ts=8 sw=4 sta nowrap
+*/
+
diff -PNaur MPlayer-20030526/mplayer.c MPlayer-20030526+EDL/mplayer.c
--- MPlayer-20030526/mplayer.c 2003-05-23 17:01:02.000000000 +0200
+++ MPlayer-20030526+EDL/mplayer.c 2003-05-26 13:35:33.000000000 +0200
@@ -249,9 +249,10 @@
// A-V sync:
static float default_max_pts_correction=-1;//0.01f;
+static float edl_max_pts_correction = -1.0;
static float max_pts_correction=0;//default_max_pts_correction;
static float c_total=0;
- float audio_delay=0;
+static float audio_delay = 0.0;
static int softsleep=0;
@@ -327,10 +328,7 @@
#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;
@@ -638,6 +636,91 @@
}
static int play_tree_step = 1;
+static int osd_function=OSD_PLAY;
+static demux_stream_t *d_video=NULL;
+static int osd_show_av_delay = 0;
+extern int muted;
+
+void ExecActualEDL(void)
+{
+ switch (ActualEDL->action) {
+ case EDL_BEGIN_PROGRAM:
+ audio_delay = 0.0;
+ muted = 0;
+ max_pts_correction = 0;
+ edl_max_pts_correction = default_max_pts_correction;
+ break;
+ case EDL_SKIP:
+ osd_function = OSD_FFW;
+ abs_seek_pos = 0;
+ rel_seek_secs += ActualEDL->value.f - d_video->pts;
+#ifdef DEBUG_EDL
+ printf("\nEDL_SKIP: start [%f], stop [%f], length [%f]\n",
+ ActualEDL->start_sec, ActualEDL->value.f,
+ rel_seek_secs );
+#endif
+ edl_decision = 1;
+ break;
+#ifdef DEBUG_EDL
+ case EDL_LOOP:
+ printf("\nEDL_LOOP start at %f: %d of %d \n",
+ ActualEDL->start_sec, ActualEDL->value.loop.n+1,
+ ActualEDL->value.loop.back->value.loop.n);
+ break;
+#endif
+ case EDL_LOOP_END:
+ {
+ edl_record_ptr Back = ActualEDL->value.loop.back;
+#ifdef DEBUG_EDL
+ printf("\nEDL_LOOP_END at %f \n", ActualEDL->start_sec);
+#endif
+ if (++(Back->value.loop.n) < ActualEDL->value.loop.n) {
+ abs_seek_pos = 1;
+ rel_seek_secs = Back->start_sec;
+ edl_decision = 1;
+ ActualEDL = Back;
+ /* Do not step to the next EDL entry: */
+ return;
+ }
+ }
+ break;
+ case EDL_MUTE:
+ if (!muted) mixer_mute();
+ edl_decision = 1;
+#ifdef DEBUG_EDL
+ printf( "\nEDL_MUTE: [%f]\n", ActualEDL->start_sec );
+#endif
+ break;
+ case EDL_UNMUTE:
+ if (muted) mixer_mute();
+ edl_decision = 1;
+#ifdef DEBUG_EDL
+ printf( "\nEDL_UNMUTE: [%f]\n", ActualEDL->start_sec );
+#endif
+ break;
+ case EDL_AVSYNC:
+ {
+ /* A/V sync must be corrected by the given value. */
+ audio_delay = ActualEDL->value.f;
+#ifdef DEBUG_EDL
+ printf( "\nEDL_AVSYNC: [%f]\n", audio_delay );
+#endif
+ osd_show_av_delay = 9;
+ }
+ break;
+ case EDL_MC:
+ edl_max_pts_correction = ActualEDL->value.f;
+#ifdef DEBUG_EDL
+ printf( "\nEDL_MC: [%f]\n", edl_max_pts_correction );
+#endif
+ break;
+ case EDL_STOP:
+ exit_player_with_rc(MSGTR_Exit_quit, 0);
+ break;
+ }
+ ActualEDL = ActualEDL->next;
+}
+
#ifdef USE_SUB
@@ -704,7 +787,6 @@
static demux_stream_t *d_audio=NULL;
-static demux_stream_t *d_video=NULL;
static demux_stream_t *d_dvdsub=NULL;
int file_format=DEMUXER_TYPE_UNKNOWN;
@@ -714,9 +796,7 @@
// movie info:
int eof=0;
-int osd_function=OSD_PLAY;
int osd_last_pts=-303;
-int osd_show_av_delay = 0;
int osd_show_text = 0;
int osd_show_sub_delay = 0;
int osd_show_sub_pos = 0;
@@ -904,99 +984,19 @@
#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_filename) {
+ if (edl_output_filename) {
+ printf( "Sorry; EDL mode and EDL output mode are mutually exclusive! Disabling all EDL functions.\n" );
+ edl_output_filename = NULL;
+ edl_filename = NULL;
+ } else {
+ open_edl_file(edl_filename);
+ }
+ } 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;
+ }
}
#endif
@@ -1840,6 +1840,7 @@
//==================== START PLAYING =======================
+edl_max_pts_correction = default_max_pts_correction;
if(loop_times>1) loop_times--; else
if(loop_times==1) loop_times = -1;
@@ -2213,8 +2214,8 @@
x=AV_delay*0.1f;
if(x<-max_pts_correction) x=-max_pts_correction; else
if(x> max_pts_correction) x= max_pts_correction;
- if(default_max_pts_correction>=0)
- max_pts_correction=default_max_pts_correction;
+ if(edl_max_pts_correction>=0)
+ max_pts_correction=edl_max_pts_correction;
else
max_pts_correction=sh_video->frametime*0.10; // +-10% of time
if(!frame_time_remaining){ sh_audio->delay+=x; c_total+=x;} // correction
@@ -2346,27 +2347,7 @@
//================= EDL =========================================
#ifdef USE_EDL
- if( next_edl_record->next ) { // Are we (still?) doing EDL?
- if( sh_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;
- }
- }
- }
+ if (ActualEDL && d_video->pts >= ActualEDL->start_sec) ExecActualEDL();
#endif
//================= Keyboard events, SEEKing ====================
@@ -2396,7 +2377,12 @@
rel_seek_secs = v/100.0;
}
else {
- rel_seek_secs+= v;
+ rel_seek_secs += v;
+#ifdef USE_EDL
+ /* If we hit an EDL entry, this function returns a correction
+ * value which is needed to seek out of that entry: */
+ rel_seek_secs += edl_seek(d_video->pts+rel_seek_secs, v>0.0);
+#endif
osd_function= (v > 0) ? OSD_FFW : OSD_REW;
}
} break;
@@ -3202,20 +3188,7 @@
}
}
#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;
- }
- }
+ edl_decision = 0;
#endif
rel_seek_secs=0;
abs_seek_pos=0;
@@ -3533,3 +3506,8 @@
return 1;
}
+
+/*
+vim:ts=8 sw=4 sta nowrap
+*/
+