[MPlayer-dev-eng] DVD navigation again

Kees Cook mplayer at outflux.net
Thu Mar 28 02:10:58 CET 2002


Hello!

An attempt was made a while back to add DVD navigation into mplayer, so I 
started with that patch and updated it as best I could for the latest 
MPlayer source.  Mostly, I added stuff to the new input subsystem, and 
tried to solve problems with caching.

I'm not sure what to do about caching as it seriously breaks the 
navigation.  libdvdnav has a read-ahead feature that maybe could be 
hooked, so for now I just disabled it in my mplayer.conf file.  :)

Anyway, this uses Xine's dvdnav library:
http://dvd.sourceforge.net/xine-dvdnav.shtml

This doesn't get in the way of existing DVD functions (I made a new 
"STREAMTYPE_DVDNAV" to separate it).

Some things don't behave the way they should (like, say, the open
warning), but I don't care about that right now.  :P

I'd like to know where to hook in to do "highlighting" for the button 
navigation.  The screen coords and other info arrives, I just need to know 
how to hook it into the OSD, or something similar.  Maybe postprocessing 
of some sort?  I haven't looked into this.

I hope other people like this!

-- 
Kees Cook                                            @outflux.net
-------------- next part --------------
diff -ur MPlayer-20020327-clean/cfg-common.h MPlayer-20020327-dvdnav/cfg-common.h
--- MPlayer-20020327-clean/cfg-common.h	Mon Mar 25 21:25:14 2002
+++ MPlayer-20020327-dvdnav/cfg-common.h	Wed Mar 27 12:09:50 2002
@@ -12,6 +12,9 @@
 #else
 	{"vcd", "VCD support is NOT available on this system!\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
 #endif
+#ifdef USE_DVDNAV
+	{"dvdnav", &dvd_nav, CONF_TYPE_FLAG, 0, 0, 1},
+#endif
 #ifdef USE_DVDREAD
 	{"dvd-device", &dvd_device,  CONF_TYPE_STRING, 0, 0, 0, NULL}, 
 	{"dvd", &dvd_title, CONF_TYPE_INT, CONF_RANGE, 1, 99, NULL},
diff -ur MPlayer-20020327-clean/configure MPlayer-20020327-dvdnav/configure
--- MPlayer-20020327-clean/configure	Tue Mar 26 19:45:54 2002
+++ MPlayer-20020327-dvdnav/configure	Wed Mar 27 12:43:49 2002
@@ -207,6 +207,7 @@
   --with-csslibdir=DIR     libcss in DIR
   --with-madlibdir=DIR     libmad (libmad shared lib.) in DIR
   --with-mlibdir=DIR       libmlib (MLIB support) in DIR (Solaris only)
+  --with-libdvdnav=DIR     libdvdnav in DIR
   --with-win32libdir=DIR   W*ndows DLL files in DIR
   --with-xanimlibdir=DIR   XAnim DLL files in DIR
   --with-xvidcore=PATH     path to XviD libcore.a (e.g: /opt/lib/libcore.a)
@@ -787,6 +788,7 @@
 _vorbis=auto
 _faad=auto
 _css=auto
+_dvdnav=no
 _dvdread=auto
 _xanim=auto
 _xinerama=auto
@@ -970,6 +972,10 @@
   --language=*)
     LINGUAS=`echo $ac_option | cut -d '=' -f 2`
     ;;
+  --with-libdvdnav=*)
+    _dvdnavdir=`echo $ac_option | cut -d '=' -f 2`
+    _dvdnav=yes
+    ;;
 
   --with-win32libdir=*)
     _win32libdir=`echo $ac_option | cut -d '=' -f 2`
@@ -2414,7 +2420,6 @@
   echores "no"
 fi
 
-
 echocheck "DVD support (libdvdread - new style)"
 if test "$_dvdread" = auto ; then
   cat > $TMPC << EOF
@@ -2443,6 +2448,28 @@
   echores "no"
 fi
 
+echocheck "libdvdnav"
+if test "$_dvdnav" = yes ; then
+  cat > $TMPC <<EOF
+#include <dvdnav.h>
+int main(void) { dvdnav_t *dvd=0; return 0; }
+EOF
+  _dvdnav=no
+  cc_check $_inc_extra -I$_dvdnavdir $_ld_css -L$_dvdnavdir/.libs -ldvdnav && _dvdnav=yes
+fi
+if test "$_dvdnav" = yes ; then
+  _largefiles=yes
+  _def_dvdnav='#define USE_DVDNAV 1'
+  _ld_css="$_ld_css -L$_dvdnavdir/.libs -ldvdnav"
+  _inc_extra="$_inc_extra -I$_dvdnavdir"
+  _inputmodules="dvdnav $_inputmodules"
+  echores "yes"
+else
+  _def_dvdnav='#undef USE_DVDNAV'
+  _noinputmodules="dvdnav $_noinputmodules"
+  echores "no"
+fi
+
 echocheck "zlib"
 cat > $TMPC << EOF
 #include <zlib.h>
@@ -3466,6 +3493,9 @@
 /* DeCSS support using libcss */
 $_def_css
 
+/* DVD navigation support using libdvdnav */
+$_def_dvdnav
+
 /* Define this to enable MPEG 1/2 image postprocessing (requires FAST cpu!) */
 #define MPEG12_POSTPROC 1
 
diff -ur MPlayer-20020327-clean/input/input.c MPlayer-20020327-dvdnav/input/input.c
--- MPlayer-20020327-clean/input/input.c	Wed Mar 20 05:30:57 2002
+++ MPlayer-20020327-dvdnav/input/input.c	Wed Mar 27 16:28:18 2002
@@ -75,6 +75,10 @@
   { MP_CMD_GUI_PREFERENCES, "gui_preferences", 0, { {-1,{0}} } },
   { MP_CMD_GUI_SKINBROWSER, "gui_skinbrowser", 0, { {-1,{0}} } },
 #endif
+
+#ifdef USE_DVDNAV
+  { MP_CMD_DVDNAV, "dvdnav", 1, { {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
+#endif
   
   { 0, NULL, 0, {} }
 };
@@ -159,26 +163,33 @@
   { {  MOUSE_BTN5, 0 }, "volume 1" },
   { {  MOUSE_BTN6, 0 }, "volume -1" },
   
+#ifdef USE_DVDNAV
+  { { 'K', 0 }, "dvdnav 1" },   // up
+  { { 'J', 0 }, "dvdnav 2" },   // down
+  { { 'H', 0 }, "dvdnav 3" },   // left
+  { { 'L', 0 }, "dvdnav 4" },   // right
+  { { 'M', 0 }, "dvdnav 5" },   // menu
+  { { 'S', 0 }, "dvdnav 6" },   // select
+#endif
+
   { { KEY_RIGHT, 0 }, "seek 10" },
   { {  KEY_LEFT, 0 }, "seek -10" },
   { {  KEY_UP, 0 }, "seek 60" },
   { {  KEY_DOWN, 0 }, "seek -60" },
+  { { KEY_ESC, 0 }, "quit" },
   { {  KEY_PAGE_UP, 0 }, "seek 600" },
   { { KEY_PAGE_DOWN, 0 }, "seek -600" },
   { { '-', 0 }, "audio_delay 0.100" },
   { { '+', 0 }, "audio_delay -0.100" },
   { { 'q', 0 }, "quit" },
-  { { KEY_ESC, 0 }, "quit" },
 #ifndef HAVE_NEW_GUI
+  { { KEY_ENTER, 0 }, "pt_step 1 1" },
   { { 'p', 0 }, "pause" },
 #endif
   { { ' ', 0 }, "pause" },
   { { KEY_HOME, 0 }, "pt_up_step 1" },
   { { KEY_END, 0 }, "pt_up_step -1" },
   { { '>', 0 }, "pt_step 1" },
-#ifndef HAVE_NEW_GUI
-  { { KEY_ENTER, 0 }, "pt_step 1 1" },
-#endif
   { { '<', 0 }, "pt_step -1" },
   { { KEY_INS, 0 }, "alt_src_step 1" },
   { { KEY_DEL, 0 }, "alt_src_step -1" },
diff -ur MPlayer-20020327-clean/input/input.h MPlayer-20020327-dvdnav/input/input.h
--- MPlayer-20020327-clean/input/input.h	Tue Mar 19 05:29:28 2002
+++ MPlayer-20020327-dvdnav/input/input.h	Wed Mar 27 16:24:09 2002
@@ -24,6 +24,7 @@
 #define MP_CMD_TV_STEP_CHANNEL_LIST 19
 #define MP_CMD_VO_FULLSCREEN 20
 #define MP_CMD_SUB_POS 21
+#define MP_CMD_DVDNAV 22
 
 #define MP_CMD_GUI_EVENTS       5000
 #define MP_CMD_GUI_LOADFILE     5001
@@ -36,6 +37,13 @@
 #define MP_CMD_GUI_FULLSCREEN   5008
 #define MP_CMD_GUI_SKINBROWSER  5009
 
+#define MP_CMD_DVDNAV_UP        1
+#define MP_CMD_DVDNAV_DOWN      2
+#define MP_CMD_DVDNAV_LEFT      3
+#define MP_CMD_DVDNAV_RIGHT     4
+#define MP_CMD_DVDNAV_MENU      5
+#define MP_CMD_DVDNAV_SELECT    6
+
 // The args types
 #define MP_CMD_ARG_INT 0
 #define MP_CMD_ARG_FLOAT 1
diff -ur MPlayer-20020327-clean/libmpdemux/open.c MPlayer-20020327-dvdnav/libmpdemux/open.c
--- MPlayer-20020327-clean/libmpdemux/open.c	Sat Feb 16 13:48:59 2002
+++ MPlayer-20020327-dvdnav/libmpdemux/open.c	Wed Mar 27 15:19:44 2002
@@ -31,6 +31,11 @@
 int dvd_angle=1;
 char* dvd_device=NULL;
 char* cdrom_device=NULL;
+int dvd_nav=0;
+
+#ifdef USE_DVDNAM
+#include <dvdnav.h>
+#endif
 
 #ifdef USE_DVDREAD
 
@@ -110,10 +115,29 @@
 #endif
 
 //============ Open DVD title ==============
+#ifdef USE_DVDNAV
+if(dvd_nav){
+    dvdnav_t *dvdnav;
+    int event,len,tmplen=0;
+    if(!filename) filename=DEFAULT_DVD_DEVICE;
+    if(dvdnav_open(&dvdnav,filename)!=DVDNAV_STATUS_OK) {
+	mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,filename);
+        return NULL;
+    }
+
+    stream=new_stream(-1,STREAMTYPE_DVDNAV);
+    if (!stream) {
+        mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_Exit_error);
+        return NULL;
+    }
+    stream->priv=(void*)dvdnav;
+    return stream;
+}
+#endif
 #ifdef USE_DVDREAD
 if(dvd_title){
 //  int ret,ret2;
-  dvd_priv_t *d;
+    dvd_priv_t *d;
     int ttn,pgc_id,pgn;
     dvd_reader_t *dvd;
     dvd_file_t *title;
diff -ur MPlayer-20020327-clean/libmpdemux/stream.c MPlayer-20020327-dvdnav/libmpdemux/stream.c
--- MPlayer-20020327-clean/libmpdemux/stream.c	Sat Mar 16 06:32:03 2002
+++ MPlayer-20020327-dvdnav/libmpdemux/stream.c	Wed Mar 27 16:52:53 2002
@@ -28,6 +28,12 @@
 
 #endif
 
+#ifdef USE_DVDNAV
+#include <../linux/timer.h>
+static int still_sleep_until;
+static int sleeping=0;
+static int stillen=0;
+#endif
 #ifdef USE_DVDREAD
 int dvd_read_sector(void* d,void* p2);
 void dvd_seek(void* d,off_t pos);
@@ -59,6 +65,98 @@
     len=vcd_read(s->fd,s->buffer);break;
 #endif
 #endif
+#ifdef USE_DVDNAV
+  case STREAMTYPE_DVDNAV: {
+    int event = DVDNAV_NOP;
+    if(sleeping)
+    {
+      dvdnav_still_skip(s->priv);
+      if(sleeping==1) if(GetTimer()>=still_sleep_until) sleeping = 0;
+      len = stillen;
+    }
+    if(dvdnav_get_next_block(s->priv,s->buffer,&event,&len)!=DVDNAV_STATUS_OK)
+      printf( "Error getting next block from DVD (%s)\n",dvdnav_err_to_string(s->priv) );
+    else switch(event) {
+      case DVDNAV_BLOCK_OK: {
+          /* be silent about this one */
+                break;
+          }
+      case DVDNAV_HIGHLIGHT: {
+          dvdnav_highlight_event_t *hevent = (dvdnav_highlight_event_t*)(s->buffer);
+          if (!hevent) {
+                printf("Highlight event broken\n");
+                break;
+          }
+
+          if (hevent->display)
+          {
+    	        printf( "Highlight (%u,%u)-(%u,%u) (button %d)\n",
+                     hevent->sx,hevent->sy,
+                     hevent->ex,hevent->ey,
+                     hevent->buttonN );
+          }
+          else {
+                  printf("Highlight Hide\n");
+          }
+        break;
+        }
+      case DVDNAV_STILL_FRAME: {
+          printf( "Still Frame\n" );
+          dvdnav_still_event_t *still_event = (dvdnav_still_event_t*)(s->buffer);
+	  if(still_event->length==0xff) { printf( "Sleeping indefinately\n" ); sleeping=2; }
+	  else  {
+	    InitTimer();
+	    still_sleep_until = GetTimer() + still_event->length*1000000;
+	    printf( "Sleeping %d sec(s)\n", still_event->length );
+	    sleeping=1;
+	  }
+          stillen = len;          
+	break;
+        }
+      case DVDNAV_STOP: {
+          printf( "Nav Stop\n" );
+          len=0;
+	break;
+        }
+      case DVDNAV_NOP: {
+        printf("Nav NOP\n");
+	break;
+        }
+      case DVDNAV_SPU_STREAM_CHANGE: {
+        printf("Nav SPU Stream Change\n");
+	break;
+        }
+      case DVDNAV_AUDIO_STREAM_CHANGE: {
+        printf("Nav Audio Stream Change\n");
+	break;
+        }
+      case DVDNAV_VTS_CHANGE: {
+        printf("Nav VTS Change\n");
+	break;
+        }
+      case DVDNAV_CELL_CHANGE: {
+        printf("Nav Cell Change\n");
+	break;
+        }
+      case DVDNAV_NAV_PACKET: {
+        // printf("Nav Packet\n");
+	break;
+        }
+      case DVDNAV_SPU_CLUT_CHANGE: {
+        printf("Nav SPU CLUT Change\n");
+	break;
+        }
+      case DVDNAV_SEEK_DONE: {
+        printf("Nav Seek Done\n");
+	break;
+        }
+      default:
+        printf("Weird nav event %d\n",event);
+        break;
+      }
+    break;
+  }
+#endif
 #ifdef USE_DVDREAD
   case STREAMTYPE_DVD: {
     off_t pos=dvd_read_sector(s->priv,s->buffer);
diff -ur MPlayer-20020327-clean/libmpdemux/stream.h MPlayer-20020327-dvdnav/libmpdemux/stream.h
--- MPlayer-20020327-clean/libmpdemux/stream.h	Sat Mar 23 18:25:41 2002
+++ MPlayer-20020327-dvdnav/libmpdemux/stream.h	Wed Mar 27 14:49:53 2002
@@ -16,6 +16,7 @@
 #define STREAMTYPE_PLAYLIST 6
 #define STREAMTYPE_MF   7
 #define STREAMTYPE_DS   8
+#define STREAMTYPE_DVDNAV 9
 
 #define VCD_SECTOR_SIZE 2352
 #define VCD_SECTOR_OFFS 24
@@ -197,9 +198,14 @@
 extern int dvd_chapter;
 extern int dvd_last_chapter;
 extern int dvd_angle;
+extern int dvd_nav;
 int dvd_parse_chapter_range(struct config*, const char*);
 //#endif
 
+#ifdef USE_DVDNAV
+#include <dvdnav.h>
+#endif
+
 #ifdef USE_DVDREAD
 
 #include <dvdread/dvd_reader.h>
diff -ur MPlayer-20020327-clean/mplayer.c MPlayer-20020327-dvdnav/mplayer.c
--- MPlayer-20020327-clean/mplayer.c	Tue Mar 26 19:45:55 2002
+++ MPlayer-20020327-dvdnav/mplayer.c	Wed Mar 27 16:56:57 2002
@@ -48,6 +48,9 @@
 #include "codec-cfg.h"
 
 #include "dvdauth.h"
+#ifdef USE_DVDNAV
+#include <dvdnav.h>
+#endif
 #ifdef USE_DVDREAD
 #include "spudec.h"
 #endif
@@ -627,7 +630,7 @@
     }
 
 
-    if(!filename && !vcd_track && !dvd_title && !tv_param_on){
+    if(!filename && !vcd_track && !dvd_title && !dvd_nav && !tv_param_on){
       if(!use_gui){
 	// no file/vcd/dvd -> show HELP:
 	mp_msg(MSGT_CPLAYER, MSGL_INFO, help_text);
@@ -1930,6 +1933,53 @@
       (c=lirc_mp_getinput())>0 ||
 #endif
       (!use_stdin && (c=getch2(0))>0) || (c=mplayer_get_key())>0) switch(c){
+#ifdef USE_DVDNAV
+    case KEY_RIGHT:
+      if(dvd_nav) {
+              printf("right\n");
+        dvdnav_right_button_select(stream->priv);
+      } else {
+        osd_function=OSD_FFW;
+        rel_seek_secs+=10;
+      }
+      break;
+    case KEY_LEFT:
+      if(dvd_nav) {
+              printf("left\n");
+        dvdnav_left_button_select(stream->priv);
+      } else {
+        osd_function=OSD_REW;
+        rel_seek_secs-=10;
+      }
+      break;
+    case KEY_UP:
+      if(dvd_nav) {
+              printf("up\n");
+        dvdnav_upper_button_select(stream->priv);
+      } else {
+        osd_function=OSD_FFW;
+        rel_seek_secs+=60;
+      }
+      break;
+    case KEY_DOWN:
+              printf("top of down\n");
+      if(dvd_nav) {
+              printf("down\n");
+        dvdnav_lower_button_select(stream->priv);
+      } else {
+        osd_function=OSD_REW;
+        rel_seek_secs-=60;
+      }
+      break;
+    case KEY_ENTER:
+      if(dvd_nav) {
+              printf("click\n");
+        dvdnav_button_activate(stream->priv);
+      } else {
+        eof=2;  // jump to next file
+      }
+      break;
+#else
     // seek 10 sec
     case KEY_RIGHT:
       osd_function=OSD_FFW;
@@ -1944,6 +1994,10 @@
     case KEY_DOWN:
       osd_function=OSD_REW;
       rel_seek_secs-=60;break;
+    case KEY_ENTER: // ESC
+      eof=2;  // jump to next file
+      break;
+#endif
     // seek 10 min
     case KEY_PAGE_UP:
       rel_seek_secs+=600;break;
@@ -1962,6 +2016,13 @@
       break;
     // quit
     case KEY_ESC: // ESC
+#ifdef USE_DVDNAV
+      if(dvd_nav) {
+              printf("menu\n");
+        dvdnav_menu_call(stream->priv,DVD_MENU_Root);
+        break;
+      }
+#endif
     case 'q': 
       exit_player(MSGTR_Exit_quit);
     case KEY_ENTER: // ESC
@@ -2437,6 +2498,34 @@
 	if(sub_pos >100) sub_pos=100;
 	if(sub_pos <0) sub_pos=0;
     }	break;
+#ifdef USE_DVDNAV
+    case MP_CMD_DVDNAV: {
+      switch (cmd->args[0].v.i) {
+        case MP_CMD_DVDNAV_UP:
+          dvdnav_upper_button_select(stream->priv);
+          break;
+        case MP_CMD_DVDNAV_DOWN:
+          dvdnav_lower_button_select(stream->priv);
+          break;
+        case MP_CMD_DVDNAV_LEFT:
+          dvdnav_left_button_select(stream->priv);
+          break;
+        case MP_CMD_DVDNAV_RIGHT:
+          dvdnav_right_button_select(stream->priv);
+          break;
+        case MP_CMD_DVDNAV_MENU:
+          dvdnav_menu_call(stream->priv,DVD_MENU_Root);
+          break;
+        case MP_CMD_DVDNAV_SELECT:
+          dvdnav_button_activate(stream->priv);
+          break;
+        default:
+          mp_msg(MSGT_CPLAYER, MSGL_V, "Weird DVD Nav cmd %d\n",cmd->args[0].v.i);
+          break;
+      }
+      break;
+    }
+#endif
     default : {
 #ifdef HAVE_NEW_GUI
       if ( ( use_gui )&&( cmd->id > MP_CMD_GUI_EVENTS ) ) guiGetEvent( guiIEvent,(char *)cmd->id );


More information about the MPlayer-dev-eng mailing list