1
mirror of https://github.com/mpv-player/mpv synced 2024-07-11 23:47:56 +02:00

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>


git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8532 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
arpi 2002-12-23 00:33:22 +00:00
parent da02716487
commit 7f1c583447
8 changed files with 249 additions and 6 deletions

View File

@ -206,6 +206,19 @@ Prints some statistics on CPU usage and dropped frames at the end.
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.

View File

@ -227,6 +227,11 @@ extern int demuxer_type, audio_demuxer_type, sub_demuxer_type;
#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},

View File

@ -203,6 +203,13 @@ static config_t mplayer_opts[]={
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},

17
configure vendored
View File

@ -140,6 +140,7 @@ Optional features:
--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 @@ _select=yes
_tv=yes
_tv_v4l=auto
_tv_bsdbt848=auto
_edl=yes
_streaming=yes
_vidix=auto
_joystick=no
@ -1153,6 +1155,8 @@ for ac_option do
--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 @@ else
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 @@ $_def_nas
/* Enable TV Interface support */
$_def_tv
/* Enable EDL support */
$_def_edl
/* Enable Video 4 Linux TV interface support */
$_def_tv_v4l

25
edl.h Normal file
View File

@ -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

View File

@ -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 @@ static mp_cmd_bind_t def_cmd_binds[] = {
{ { '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" },

View File

@ -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

178
mplayer.c
View File

@ -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 char* menu_root = "main";
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 @@ if(!parse_codec_cfg(get_path("codecs.conf"))){
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 @@ if (stream->type==STREAMTYPE_DVDNAV && dvd_nav_still)
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 @@ if (stream->type==STREAMTYPE_DVDNAV && dvd_nav_still)
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 @@ if(rel_seek_secs || abs_seek_pos){
#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(rel_seek_secs || abs_seek_pos){
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;