[MPlayer-dev-eng] [patch] dvd navigation for 20020402

Kees Cook mplayer at outflux.net
Tue Apr 2 20:09:31 CEST 2002


Okay, another attempt at the dvd nav patch update.

- moves as much of the code to separate .c and .h files
- moves event handling into mplayer.c
- changes CMD_QUEUE_SIZE to 100 for large number of back-logged DVD Nav 
  events seen during start up.
- adds "void *" as a type to mp_cmd_arg_value_t for sending event
  structures.
- adds possible dvdnav reset'ing
- first stab at repeating previous frame, but seems to grab the
  wrong frame, so it's disabled for now.
- disables caching similar to "-nocache" if using dvdnav
- adds ability to update SPU palette
- small spelling corrections in a comment
- corrected (changed?) SPU pts calculation to *90000/1024 instead of *100

So, as things stand:
- Still Images still don't work, as there isn't a very clean way to 
  "pause" the video and audio.  I've tried, but I think someone more 
  familiar with it needs to take a look at how to do it.
- Menu highlighting is still a line-drawing hack, but at least something
  is visible.
- Audio stream IDs need to change dynamically more cleanly, but it mostly
  works.
- SPU stream IDs need to change dynanmically more cleanly, but it mostly
  works, though there appears to be problems with palettes (I sometimes
  get all-black or all-white subtitles.)

Other than those things, DVD menu navigation works fine.

Should I do any things in this patch differently?  Any suggestions to THIS 
patch?  I'd like to get this into CVS since it's a big change, but doesn't 
seem to break anything.

Has anyone else tested these DVD nav patches?  I'd like to not be the only 
person testing it.  ;)

-- 
Kees Cook                                            @outflux.net
-------------- next part --------------
diff --exclude=CVS -ur MPlayer-20020402-clean/Makefile MPlayer-20020402-dvdnav/Makefile
--- MPlayer-20020402-clean/Makefile	Sat Mar 30 15:02:13 2002
+++ MPlayer-20020402-dvdnav/Makefile	Sun Mar 31 15:47:53 2002
@@ -37,7 +37,7 @@
 # a BSD compatible 'install' program
 INSTALL = install
 
-SRCS_COMMON = cyuv.c xacodec.c cpudetect.c mp_msg.c msvidc.c cinepak.c fli.c qtrle.c codec-cfg.c cfgparser.c my_profile.c RTjpegN.c minilzo.c nuppelvideo.c spudec.c playtree.c playtreeparser.c asxparser.c qtsmc.c ducktm1.c roqav.c qtrpza.c vobsub.c
+SRCS_COMMON = cyuv.c xacodec.c cpudetect.c mp_msg.c msvidc.c cinepak.c fli.c qtrle.c codec-cfg.c cfgparser.c my_profile.c RTjpegN.c minilzo.c nuppelvideo.c dvdnav_stream.c spudec.c playtree.c playtreeparser.c asxparser.c qtsmc.c ducktm1.c roqav.c qtrpza.c vobsub.c
 SRCS_MENCODER = mencoder.c $(SRCS_COMMON) libao2/afmt.c divx4_vbr.c libvo/aclib.c libvo/img_format.c libvo/osd.c me-opt-reg.c
 SRCS_MPLAYER = mplayer.c $(SRCS_COMMON) find_sub.c subreader.c lirc_mp.c mixer.c mp-opt-reg.c
 
diff --exclude=CVS -ur MPlayer-20020402-clean/cfg-common.h MPlayer-20020402-dvdnav/cfg-common.h
--- MPlayer-20020402-clean/cfg-common.h	Sun Mar 31 14:01:54 2002
+++ MPlayer-20020402-dvdnav/cfg-common.h	Tue Apr  2 09:50:59 2002
@@ -14,7 +14,8 @@
 	{"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},
+	{"dvdnav", &dvd_nav, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+	{"skipopening", &dvd_nav_skip_opening, CONF_TYPE_FLAG, 0, 0, 1, NULL},
 #endif
 #ifdef USE_DVDREAD
 	{"dvd-device", &dvd_device,  CONF_TYPE_STRING, 0, 0, 0, NULL}, 
diff --exclude=CVS -ur MPlayer-20020402-clean/input/input.c MPlayer-20020402-dvdnav/input/input.c
--- MPlayer-20020402-clean/input/input.c	Thu Mar 28 12:40:21 2002
+++ MPlayer-20020402-dvdnav/input/input.c	Mon Apr  1 15:41:49 2002
@@ -78,8 +78,9 @@
 
 #ifdef USE_DVDNAV
   { MP_CMD_DVDNAV, "dvdnav", 1, { {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
+  { MP_CMD_DVDNAV_EVENT, "dvdnav_event", 1, { { MP_CMD_ARG_VOID, {0}}, {-1, {0}} } },
 #endif
-  
+
   { 0, NULL, 0, {} }
 };
 
@@ -257,7 +258,7 @@
 #define MP_FD_GOT_CMD (1<<3)
 #define MP_FD_NO_SELECT (1<<4)
 
-#define CMD_QUEUE_SIZE 10
+#define CMD_QUEUE_SIZE 100
 
 typedef struct mp_input_fd {
   int fd;
@@ -394,7 +395,7 @@
 
 
 
-static mp_cmd_t*
+mp_cmd_t*
 mp_input_parse_cmd(char* str) {
   int i,l;
   char *ptr,*e;
diff --exclude=CVS -ur MPlayer-20020402-clean/input/input.h MPlayer-20020402-dvdnav/input/input.h
--- MPlayer-20020402-clean/input/input.h	Thu Mar 28 12:40:21 2002
+++ MPlayer-20020402-dvdnav/input/input.h	Tue Apr  2 09:34:08 2002
@@ -37,6 +37,8 @@
 #define MP_CMD_GUI_FULLSCREEN   5008
 #define MP_CMD_GUI_SKINBROWSER  5009
 
+#define MP_CMD_DVDNAV_EVENT     6000
+
 #define MP_CMD_DVDNAV_UP        1
 #define MP_CMD_DVDNAV_DOWN      2
 #define MP_CMD_DVDNAV_LEFT      3
@@ -48,6 +50,7 @@
 #define MP_CMD_ARG_INT 0
 #define MP_CMD_ARG_FLOAT 1
 #define MP_CMD_ARG_STRING 2
+#define MP_CMD_ARG_VOID 3
 
 #ifndef MP_CMD_MAX_ARGS
 #define MP_CMD_MAX_ARGS 10
@@ -77,6 +80,7 @@
   int i;
   float f;
   char* s;
+  void* v;
 } mp_cmd_arg_value_t;
 
 typedef struct mp_cmd_arg {
@@ -155,6 +159,11 @@
 mp_cmd_t*
 mp_cmd_clone(mp_cmd_t* cmd);
 
+// This will parse a string into a command.  Can be injected via mp_input_queue_cmd
+mp_cmd_t*
+mp_input_parse_cmd(char* str);
+
+
 // When you create a new driver you should add it in this 2 functions.
 void
 mp_input_init(void);
diff --exclude=CVS -ur MPlayer-20020402-clean/libmpdemux/demuxer.c MPlayer-20020402-dvdnav/libmpdemux/demuxer.c
--- MPlayer-20020402-clean/libmpdemux/demuxer.c	Mon Apr  1 09:11:59 2002
+++ MPlayer-20020402-dvdnav/libmpdemux/demuxer.c	Tue Apr  2 09:50:59 2002
@@ -261,6 +261,7 @@
   if(verbose>2){
     if(ds==demux->audio) mp_dbg(MSGT_DEMUXER,MSGL_DBG3,"ds_fill_buffer(d_audio) called\n");else
     if(ds==demux->video) mp_dbg(MSGT_DEMUXER,MSGL_DBG3,"ds_fill_buffer(d_video) called\n");else
+    if(ds==demux->sub)   mp_dbg(MSGT_DEMUXER,MSGL_DBG3,"ds_fill_buffer(d_sub) called\n");else
                          mp_dbg(MSGT_DEMUXER,MSGL_DBG3,"ds_fill_buffer(unknown 0x%X) called\n",(unsigned int)ds);
   }
   while(1){
diff --exclude=CVS -ur MPlayer-20020402-clean/libmpdemux/open.c MPlayer-20020402-dvdnav/libmpdemux/open.c
--- MPlayer-20020402-clean/libmpdemux/open.c	Thu Mar 28 14:45:09 2002
+++ MPlayer-20020402-dvdnav/libmpdemux/open.c	Mon Apr  1 07:54:22 2002
@@ -31,10 +31,10 @@
 int dvd_angle=1;
 char* dvd_device=NULL;
 char* cdrom_device=NULL;
-int dvd_nav=0;
+int dvd_nav=0;                  /* use libdvdnav? */
 
 #ifdef USE_DVDNAV
-#include <dvdnav.h>
+#include "../dvdnav_stream.h"
 #endif
 
 #ifdef USE_DVDREAD
@@ -117,20 +117,22 @@
 //============ Open DVD title ==============
 #ifdef USE_DVDNAV
 if(dvd_nav){
-    dvdnav_t *dvdnav;
+    dvdnav_priv_t *dvdnav_priv;
     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;
+
+    if(!filename) filename=DEFAULT_DVD_DEVICE;
+    if (!(dvdnav_priv=new_dvdnav_stream(filename))) {
+	mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,filename);
+        return NULL;
+    }
+
+    stream->priv=(void*)dvdnav_priv;
     return stream;
 }
 #endif
diff --exclude=CVS -ur MPlayer-20020402-clean/libmpdemux/stream.c MPlayer-20020402-dvdnav/libmpdemux/stream.c
--- MPlayer-20020402-clean/libmpdemux/stream.c	Thu Mar 28 15:14:14 2002
+++ MPlayer-20020402-dvdnav/libmpdemux/stream.c	Tue Apr  2 09:28:39 2002
@@ -28,13 +28,6 @@
 
 #endif
 
-#ifdef USE_DVDNAV
-#include <dvdnav.h>
-#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);
@@ -68,93 +61,8 @@
 #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: {
-          dvdnav_still_event_t *still_event = (dvdnav_still_event_t*)(s->buffer);
-          printf( "Still Frame\n" );
-	  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;
-      }
+    dvdnav_stream_read((dvdnav_priv_t*)s->priv,s->buffer,&len);
+    if (len==0) return 0; // this was an event, so repeat the read
     break;
   }
 #endif
@@ -237,6 +145,19 @@
 #endif
     break;
 #endif
+#ifdef USE_DVDNAV
+  case STREAMTYPE_DVDNAV: {
+    if (newpos==0) {
+      if (dvdnav_stream_reset((dvdnav_priv_t*)s->priv))
+        s->pos=0;
+    }
+    if(newpos!=s->pos){
+      mp_msg(MSGT_STREAM,MSGL_INFO,"Cannot seek in DVDNAV streams!\n");
+      return 1;
+    }
+    break;
+  }
+#endif
 #ifdef USE_DVDREAD
   case STREAMTYPE_DVD:
     s->pos=newpos; // real seek
diff --exclude=CVS -ur MPlayer-20020402-clean/libmpdemux/stream.h MPlayer-20020402-dvdnav/libmpdemux/stream.h
--- MPlayer-20020402-clean/libmpdemux/stream.h	Thu Mar 28 12:40:05 2002
+++ MPlayer-20020402-dvdnav/libmpdemux/stream.h	Mon Apr  1 12:44:11 2002
@@ -16,7 +16,7 @@
 #define STREAMTYPE_PLAYLIST 6
 #define STREAMTYPE_MF   7
 #define STREAMTYPE_DS   8
-#define STREAMTYPE_DVDNAV 9
+#define STREAMTYPE_DVDNAV 9   // we cannot safely "seek" in this...
 
 #define VCD_SECTOR_SIZE 2352
 #define VCD_SECTOR_OFFS 24
@@ -202,6 +202,10 @@
 int dvd_parse_chapter_range(struct config*, const char*);
 //#endif
 
+#ifdef USE_DVDNAV
+#include "../dvdnav_stream.h"
+#endif
+
 #ifdef USE_DVDREAD
 
 #include <dvdread/dvd_reader.h>
diff --exclude=CVS -ur MPlayer-20020402-clean/libmpdemux/video.c MPlayer-20020402-dvdnav/libmpdemux/video.c
--- MPlayer-20020402-clean/libmpdemux/video.c	Sun Mar 31 10:28:00 2002
+++ MPlayer-20020402-dvdnav/libmpdemux/video.c	Mon Apr  1 19:24:23 2002
@@ -196,6 +196,17 @@
     float pts1=d_video->pts;
 //    unsigned char* start=NULL;
     int in_size=0;
+    static unsigned char *prev_start=NULL;
+    static int prev_size=0;
+
+#ifdef USE_DVDNAV
+    /* repeat the last frame if we're on a still */
+    if (dvd_nav && dvd_nav_still && prev_start) {
+      printf("repeating last from @ %x size %d\n",prev_start,prev_size);
+      *start=prev_start;
+      return prev_size;
+    }
+#endif
     
     *start=NULL;
 
@@ -310,6 +321,11 @@
        demuxer->file_format==DEMUXER_TYPE_MPEG_ES) d_video->pts+=frame_time;
     
     if(frame_time_ptr) *frame_time_ptr=frame_time;
+
+    /* retain buffer info in case we need to repeat the frame */
+    prev_start=*start;
+    prev_size=in_size;
+
     return in_size;
 
 }
diff --exclude=CVS -ur MPlayer-20020402-clean/libvo/sub.c MPlayer-20020402-dvdnav/libvo/sub.c
--- MPlayer-20020402-clean/libvo/sub.c	Sat Mar 23 16:32:13 2002
+++ MPlayer-20020402-dvdnav/libvo/sub.c	Tue Apr  2 09:37:17 2002
@@ -6,6 +6,8 @@
 
 #include <stdlib.h>
 
+#include "../libmpdemux/stream.h"
+
 char * __sub_osd_names[]={
     "Seekbar",
     "Play",
@@ -51,6 +53,124 @@
 
 }
 
+/* draws a line with a font character.  :P */
+inline static void vo_osd_draw_line(int dxs, int dys, int sx, int sy, int ex, int ey,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){
+        int font;
+        int cx, cy; /* current x,y location */
+        int xspan, yspan; /* how far they need to go */
+        float xwhole, ywhole; /* how large is a "whole" step */
+        float xstep, ystep; /* x, y steps */
+        float xcounter, ycounter;
+        unsigned char c='+';
+
+        if (!vo_font) return;
+
+        /* stay within screen */
+        if (sx>=dxs) sx=dxs-1;
+        if (ex>=dxs) ex=dxs-1;
+        if (sy>=dys) sy=dys-1;
+        if (ey>=dys) ey=dys-1;
+
+        /* only draw left to right */
+        if ( sx > ex ) {
+                int tmp;
+                tmp=sx;
+                sx=ex;
+                ex=tmp;
+                c=sy;
+                sy=ey;
+                ey=tmp;
+        }
+
+        xspan=ex-sx;
+        yspan=ey-sy;
+
+        if (xspan==0 && yspan==0)
+                return; /* nothing to draw! */
+
+        if ((font=vo_font->font[c])<0)
+                return; /* font not there?! */
+
+        //printf("font width: %d\n",vo_font->width[c]);
+
+        xwhole=ywhole=(float)vo_font->width[c]/2.0;
+        if (xwhole==0.0) {
+                xwhole=ywhole=1.0;
+        }
+
+        // invert the y drawing if need to go bottom to top
+        if (yspan<0) {
+                yspan=0-yspan;
+                ywhole*=-1;
+        }
+
+        if (xspan>yspan) {
+                xstep=xwhole;
+                ystep=(float)ywhole*(float)yspan/(float)xspan;
+        }
+        else {
+                xstep=(float)xwhole*(float)xspan/(float)yspan;
+                ystep=ywhole;
+        }
+
+        /*
+        printf("draw line\n");
+        printf("xspan: %d xwhole: %0.2f\n",xspan,xwhole);
+        printf("yspan: %d ywhole: %0.2f\n",yspan,ywhole);
+        printf("xstep: %d\n",xstep);
+        printf("ystep: %d\n",ystep);
+        printf("(%d,%d)-(%d,%d)\n",sx,sy,ex,ey);
+        */
+
+        cx=sx;
+        cy=sy;
+        xcounter=ycounter=0.0;
+        if (ywhole>0.0) {
+            while (cx<=ex && cy<=ey) {
+                //printf("pixel: %d,%d\n",cx,cy);
+                /* draw the "pixel" */
+                draw_alpha(cx-(vo_font->width[c]/2),cy-(vo_font->pic_a[font]->h/2),
+                  vo_font->width[c],
+                  vo_font->pic_a[font]->h,
+                  vo_font->pic_b[font]->bmp+vo_font->start[c],
+                  vo_font->pic_a[font]->bmp+vo_font->start[c],
+                  vo_font->pic_a[font]->w);
+
+                /* update the positions */
+                if ((xcounter+=xstep)>=xwhole) {
+                        xcounter-=xwhole;
+                        cx+=xwhole;
+                }
+                if ((ycounter+=ystep)>=ywhole) {
+                        ycounter-=ywhole;
+                        cy+=ywhole;
+                }
+            }
+        }
+        else {
+            while (cx<=ex && cy>=ey) {
+                printf("pixel: %d,%d\n",cx,cy);
+                /* draw the "pixel" */
+                draw_alpha(cx-(vo_font->width[c]/2),cy-(vo_font->pic_a[font]->h/2),
+                  vo_font->width[c],
+                  vo_font->pic_a[font]->h,
+                  vo_font->pic_b[font]->bmp+vo_font->start[c],
+                  vo_font->pic_a[font]->bmp+vo_font->start[c],
+                  vo_font->pic_a[font]->w);
+
+                /* update the positions */
+                if ((xcounter+=xstep)>=xwhole) {
+                        xcounter-=xwhole;
+                        cx+=xwhole;
+                }
+                if ((ycounter+=ystep)<=ywhole) {
+                        ycounter-=ywhole;
+                        cy+=ywhole;
+                }
+            }
+        }
+}
+
 int vo_osd_progbar_type=-1;
 int vo_osd_progbar_value=100;   // 0..256
 
@@ -319,6 +439,21 @@
         vo_draw_text_progbar(dxs,dys,draw_alpha);
     }
 
+    if (osd_show_dvd_nav_highlight) {
+        vo_osd_draw_line(dxs,dys,
+                        osd_show_dvd_nav_sx,osd_show_dvd_nav_sy,
+                        osd_show_dvd_nav_sx,osd_show_dvd_nav_ey,draw_alpha); /* |   left */
+        vo_osd_draw_line(dxs,dys,
+                        osd_show_dvd_nav_ex,osd_show_dvd_nav_sy,
+                        osd_show_dvd_nav_ex,osd_show_dvd_nav_ey,draw_alpha); /*   | right */
+        vo_osd_draw_line(dxs,dys,
+                        osd_show_dvd_nav_sx,osd_show_dvd_nav_sy,
+                        osd_show_dvd_nav_ex,osd_show_dvd_nav_sy,draw_alpha); /* --- top */
+        vo_osd_draw_line(dxs,dys,
+                        osd_show_dvd_nav_sx,osd_show_dvd_nav_ey,
+                        osd_show_dvd_nav_ex,osd_show_dvd_nav_ey,draw_alpha); /* ___ bottom */
+    }
+
 }
          
 static int vo_osd_changed_status = 0;
diff --exclude=CVS -ur MPlayer-20020402-clean/mplayer.c MPlayer-20020402-dvdnav/mplayer.c
--- MPlayer-20020402-clean/mplayer.c	Mon Apr  1 18:32:54 2002
+++ MPlayer-20020402-dvdnav/mplayer.c	Tue Apr  2 09:50:59 2002
@@ -301,14 +301,14 @@
     getch2_disable();
   }
 
-#ifdef USE_DVDREAD
+//#ifdef USE_DVDREAD
   if (mask&INITED_SPUDEC){
     inited_flags&=~INITED_SPUDEC;
     current_module="uninit_spudec";
     spudec_free(vo_spudec);
     vo_spudec=NULL;
   }
-#endif
+//#endif
   if(mask&INITED_VO){
     inited_flags&=~INITED_VO;
     current_module="uninit_vo";
@@ -915,6 +915,13 @@
 
 //============ Open & Sync STREAM --- fork cache2 ====================
 
+#ifdef USE_DVDNAV
+  // must disable caching...
+  if (dvd_nav) {
+    stream_cache_size=0;
+  }
+#endif
+
   current_module="open_stream";
   stream=open_stream(filename,vcd_track,&file_format);
   if(!stream) { // error...
@@ -1118,13 +1125,16 @@
     vo_spudec=spudec_new_scaled(palette, sh_video->disp_w, sh_video->disp_h);
 }
 
-#ifdef USE_DVDREAD
+#if USE_DVDREAD || USE_DVDNAV
 if (vo_spudec==NULL) {
-current_module="spudec_init";
-vo_spudec=spudec_new_scaled(stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(stream->priv))->cur_pgc->palette:NULL,
+  current_module="spudec_init";
+  vo_spudec=spudec_new_scaled(stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(stream->priv))->cur_pgc->palette:
+                            (stream->type==STREAMTYPE_DVDNAV?dvdnav_stream_get_palette((dvdnav_priv_t*)(stream->priv))
+                             :NULL),
 			    sh_video->disp_w, sh_video->disp_h);
 }
 #endif
+
 if (vo_spudec!=NULL)
   inited_flags|=INITED_SPUDEC;
 
@@ -1385,6 +1395,12 @@
 
 InitTimer();
 
+#ifdef USE_DVDNAV
+if (dvd_nav && stream->type==STREAMTYPE_DVDNAV) {
+  dvdnav_stream_fullstart((dvdnav_priv_t *)stream->priv);
+}
+#endif
+
 total_time_usage_start=GetTimer();
 audio_time_usage=0; video_time_usage=0; vout_time_usage=0;
 while(!eof){
@@ -1486,7 +1502,7 @@
 
 if(1)
   while(1){
-  
+
     float frame_time=0;
     int blit_frame=0;
     
@@ -1904,6 +1920,16 @@
 	rel_seek_secs+=step_sec;
 }
 
+#ifdef USE_DVDNAV
+if (stream->type==STREAMTYPE_DVDNAV) {
+  dvdnav_priv_t * dvdnav_priv=(dvdnav_priv_t*)stream->priv;
+
+  if (dvd_nav_still)
+    dvdnav_stream_sleeping(dvdnav_priv);
+}
+#endif
+
+
 //================= Keyboard events, SEEKing ====================
 
 #ifndef HAVE_NEW_INPUT
@@ -1978,13 +2004,6 @@
       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
@@ -2461,25 +2480,180 @@
 	if(sub_pos <0) sub_pos=0;
     }	break;
 #ifdef USE_DVDNAV
+    case MP_CMD_DVDNAV_EVENT: {
+      dvdnav_priv_t * dvdnav_priv = (dvdnav_priv_t*)(stream->priv);
+      dvdnav_event_t * dvdnav_event = (dvdnav_event_t *)(cmd->args[0].v.v);
+
+      if (!dvdnav_event) {
+        printf("DVDNAV Event NULL?!\n");
+        break;
+      }
+
+      if (stream->type!=STREAMTYPE_DVDNAV) {
+        printf("Got DVDNAV event when not running a DVDNAV stream!?\n");
+        break;
+      }
+
+      //printf("mplayer: got event: %d\n",dvdnav_event->event);
+
+      switch (dvdnav_event->event) {
+      case DVDNAV_BLOCK_OK: {
+          /* be silent about this one */
+                break;
+          }
+      case DVDNAV_HIGHLIGHT: {
+          dvdnav_highlight_event_t *hevent = (dvdnav_highlight_event_t*)(dvdnav_event->details);
+          if (!hevent) {
+                printf("DVDNAV Event: Highlight event broken\n");
+                break;
+          }
+
+          if (hevent->display && hevent->buttonN>0)
+          {
+                //dvdnav_priv->seen_root_menu=1; /* if we got a highlight, we're on a menu */
+                sprintf( dvd_nav_text, "Highlight button %d (%u,%u)-(%u,%u) PTS %d (now is %5.2f)",
+                     hevent->buttonN,
+                     hevent->sx,hevent->sy,
+                     hevent->ex,hevent->ey,
+                     hevent->pts, d_video->pts);
+                printf("DVDNAV Event: %s\n",dvd_nav_text);
+                //osd_show_dvd_nav_delay = 60;
+
+                osd_show_dvd_nav_highlight=1;
+                osd_show_dvd_nav_sx=hevent->sx;
+                osd_show_dvd_nav_ex=hevent->ex;
+                osd_show_dvd_nav_sy=hevent->sy;
+                osd_show_dvd_nav_ey=hevent->ey;
+          }
+          else {
+                  osd_show_dvd_nav_highlight=0;
+                  printf("DVDNAV Event: Highlight Hide\n");
+          }
+        break;
+        }
+      case DVDNAV_STILL_FRAME: {
+          dvdnav_still_event_t *still_event = (dvdnav_still_event_t*)(dvdnav_event->details);
+
+          printf( "######################################## DVDNAV Event: Still Frame: %d sec(s)\n", still_event->length );
+          while (dvdnav_stream_sleeping(dvdnav_priv)) {
+            usleep(1000); /* 1ms */
+          }
+          dvdnav_stream_sleep(dvdnav_priv,still_event->length);
+        break;
+        }
+      case DVDNAV_STOP: {
+          printf( "DVDNAV Event: Nav Stop\n" );
+        break;
+        }
+      case DVDNAV_NOP: {
+        printf("DVDNAV Event: Nav NOP\n");
+        break;
+        }
+      case DVDNAV_SPU_STREAM_CHANGE: {
+        dvdnav_stream_change_event_t * stream_change=(dvdnav_stream_change_event_t*)(dvdnav_event->details);
+
+        printf("DVDNAV Event: Nav SPU Stream Change: phys: %d logical: %d\n",
+                stream_change->physical,
+                stream_change->logical);
+
+        if (vo_spudec && dvdsub_id!=stream_change->physical) {
+                mp_msg(MSGT_INPUT,MSGL_DBG2,"d_dvdsub->id change: was %d is now %d\n",
+                        d_dvdsub->id,stream_change->physical);
+                // FIXME: need a better way to change SPU id
+                d_dvdsub->id=dvdsub_id=stream_change->physical;
+                if (vo_spudec) spudec_reset(vo_spudec);
+        }
+
+        break;
+        }
+      case DVDNAV_AUDIO_STREAM_CHANGE: {
+        int aid_temp;
+        dvdnav_stream_change_event_t *stream_change = (dvdnav_stream_change_event_t*)(dvdnav_event->details);
+
+        printf("DVDNAV Event: Nav Audio Stream Change: phys: %d logical: %d\n",
+                stream_change->physical,
+                stream_change->logical);
+
+        aid_temp=stream_change->physical;
+        if (aid_temp>=0) aid_temp+=128; // FIXME: is this sane?
+        if (d_audio && audio_id!=aid_temp) {
+                mp_msg(MSGT_INPUT,MSGL_DBG2,"d_audio->id change: was %d is now %d\n",
+                        d_audio->id,aid_temp);
+                // FIXME: need a bettery way to change audio stream id
+                d_audio->id=dvdsub_id=aid_temp;
+                resync_audio_stream(sh_audio);
+        }
+
+        break;
+      }
+      case DVDNAV_VTS_CHANGE: {
+        printf("DVDNAV Event: Nav VTS Change\n");
+        break;
+        }
+      case DVDNAV_CELL_CHANGE: {
+        dvdnav_cell_change_event_t *cell_change = (dvdnav_cell_change_event_t*)(dvdnav_event->details);
+        cell_playback_t * cell_playback = cell_change->new_cell;
+
+        printf("DVDNAV Event: Nav Cell Change\n");
+        osd_show_dvd_nav_highlight=0; /* screen changed, disable menu */
+        /*
+        printf("new still time: %d\n",cell_playback->still_time);
+        printf("new cell_cmd_nr: %d\n",cell_playback->cell_cmd_nr);
+        printf("new playback_time: %02d:%02d:%02d.%02d\n",
+                        cell_playback->playback_time.hour,
+                        cell_playback->playback_time.minute,
+                        cell_playback->playback_time.second,
+                        cell_playback->playback_time.frame_u);
+
+        */
+        break;
+        }
+      case DVDNAV_NAV_PACKET: {
+        // printf("DVDNAV Event: Nav Packet\n");
+        break;
+        }
+      case DVDNAV_SPU_CLUT_CHANGE: {
+        uint32_t * new_clut = (uint32_t *)(dvdnav_event->details);
+
+        printf("DVDNAV Event: Nav SPU CLUT Change\n");
+        // send new palette to SPU decoder
+        if (vo_spudec) spudec_update_palette(vo_spudec,new_clut);
+
+        break;
+        }
+      case DVDNAV_SEEK_DONE: {
+        printf("DVDNAV Event: Nav Seek Done\n");
+        break;
+        }
+      }
+
+      // free the dvdnav event
+      free(dvdnav_event->details);
+      free(dvdnav_event);
+      cmd->args[0].v.v=NULL;
+    }
     case MP_CMD_DVDNAV: {
+      dvdnav_priv_t * dvdnav_priv=(dvdnav_priv_t*)stream->priv;
+
       switch (cmd->args[0].v.i) {
         case MP_CMD_DVDNAV_UP:
-          dvdnav_upper_button_select(stream->priv);
+          dvdnav_upper_button_select(dvdnav_priv->dvdnav);
           break;
         case MP_CMD_DVDNAV_DOWN:
-          dvdnav_lower_button_select(stream->priv);
+          dvdnav_lower_button_select(dvdnav_priv->dvdnav);
           break;
         case MP_CMD_DVDNAV_LEFT:
-          dvdnav_left_button_select(stream->priv);
+          dvdnav_left_button_select(dvdnav_priv->dvdnav);
           break;
         case MP_CMD_DVDNAV_RIGHT:
-          dvdnav_right_button_select(stream->priv);
+          dvdnav_right_button_select(dvdnav_priv->dvdnav);
           break;
         case MP_CMD_DVDNAV_MENU:
-          dvdnav_menu_call(stream->priv,DVD_MENU_Root);
+          printf("Menu call\n");
+          dvdnav_menu_call(dvdnav_priv->dvdnav,DVD_MENU_Root);
           break;
         case MP_CMD_DVDNAV_SELECT:
-          dvdnav_button_activate(stream->priv);
+          dvdnav_button_activate(dvdnav_priv->dvdnav);
           break;
         default:
           mp_msg(MSGT_CPLAYER, MSGL_V, "Weird DVD Nav cmd %d\n",cmd->args[0].v.i);
@@ -2575,9 +2749,9 @@
 	too_slow_frame_cnt=0;
 	too_fast_frame_cnt=0;
 
-#ifdef USE_DVDREAD
+//#ifdef USE_DVDREAD
       if(vo_spudec) spudec_reset(vo_spudec);
-#endif
+//#endif
       }
   }
   rel_seek_secs=0;
@@ -2632,6 +2806,10 @@
       char osd_text_tmp[50];
       if(pts==osd_last_pts-1) ++pts; else osd_last_pts=pts;
       vo_osd_text=osd_text_buffer;
+      if (osd_show_dvd_nav_delay) {
+          sprintf(osd_text_tmp, "DVDNAV: %s", dvd_nav_text);
+          osd_show_dvd_nav_delay--;
+      } else
       if (osd_show_sub_delay) {
 	  sprintf(osd_text_tmp, "Sub delay: %d ms",(int)(sub_delay*1000));
 	  osd_show_sub_delay--;
@@ -2683,7 +2861,7 @@
     current_module=NULL;
   }
 
-#ifdef USE_DVDREAD
+//#ifdef USE_DVDREAD
   // DVD sub:
   if(vo_flags & 0x08){
     static vo_mpegpes_t packet;
@@ -2699,16 +2877,16 @@
     int len;
     current_module="spudec";
     while((len=ds_get_packet_sub(d_dvdsub,&packet))>0){
-      mp_msg(MSGT_CPLAYER,MSGL_V,"\rDVD sub: len=%d  v_pts=%5.3f  s_pts=%5.3f  \n",len,d_video->pts,d_dvdsub->pts);
-      spudec_assemble(vo_spudec,packet,len,100*d_dvdsub->pts);
+      mp_msg(MSGT_CPLAYER,MSGL_V,"\rDVD spu: len=%d  v_pts=%5.3f  s_pts=%5.3f  \n",len,d_video->pts,d_dvdsub->pts);
+      spudec_assemble(vo_spudec,packet,len,90000*d_video->pts/1024);
     }
-    spudec_heartbeat(vo_spudec,100*d_video->pts);
+    spudec_heartbeat(vo_spudec,90000*d_video->pts/1024);
 
-    /* Don't know how to detect wether the sub has changed or not */
+    /* Don't know how to detect whether the sub has changed or not */
     vo_osd_changed(1);
     current_module=NULL;
   }
-#endif
+//#endif
   
 } // while(!eof)
 
@@ -2824,3 +3002,4 @@
 
 return 1;
 }
+
diff --exclude=CVS -ur MPlayer-20020402-clean/spudec.c MPlayer-20020402-dvdnav/spudec.c
--- MPlayer-20020402-clean/spudec.c	Thu Mar 28 19:17:57 2002
+++ MPlayer-20020402-dvdnav/spudec.c	Sun Mar 31 11:59:49 2002
@@ -206,6 +206,8 @@
       case 0x00:
 	/* Menu ID, 1 byte */
 	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Menu ID\n");
+	//this->start_pts = pts100 + date;
+	//this->end_pts = UINT_MAX;
 	break;
       case 0x01:
 	/* Start display */
@@ -385,12 +387,13 @@
   if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts) {
     if (spu->orig_frame_width == 0 || spu->orig_frame_height == 0
 	|| (spu->orig_frame_width == dxs && spu->orig_frame_height == dys)) {
-      if (spu->image)
+      if (spu->image) {
 	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
 		   spu->image, spu->aimage, spu->stride);
+      }
     }
     else {
-      if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) {	/* Resizing is needed */
+      if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) { /* Resizing is needed */
 	/* scaled_x = scalex * x / 0x100
 	   scaled_y = scaley * y / 0x100
 	   order of operations is important because of rounding. */
@@ -646,11 +649,24 @@
 	  spu->scaled_frame_height = dys;
 	}
       }
-      if (spu->scaled_image)
+      if (spu->scaled_image) {
 	draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,
 		   spu->scaled_image, spu->scaled_aimage, spu->scaled_stride);
+      }
     }
   }
+  else
+  {
+    mp_msg(MSGT_SPUDEC,MSGL_DBG2,"SPU not displayed: start_pts=%d  end_pts=%d  now_pts=%d\n",
+        spu->start_pts, spu->end_pts, spu->now_pts);
+  }
+}
+
+void spudec_update_palette(void * me, unsigned int *palette)
+{
+  spudec_handle_t *spu = (spudec_handle_t *)me;
+  if (spu && palette)
+    memcpy(spu->global_palette, palette, sizeof(spu->global_palette));
 }
 
 void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height)
diff --exclude=CVS -ur MPlayer-20020402-clean/spudec.h MPlayer-20020402-dvdnav/spudec.h
--- MPlayer-20020402-clean/spudec.h	Thu Jan 10 09:17:05 2002
+++ MPlayer-20020402-dvdnav/spudec.h	Sun Mar 31 11:45:48 2002
@@ -5,6 +5,7 @@
 void spudec_assemble(void *this, unsigned char *packet, unsigned int len, unsigned int pts100);
 void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
 void spudec_draw_scaled(void *this, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
+void spudec_update_palette(void * me, unsigned int *palette);
 void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height);
 void *spudec_new(unsigned int *palette);
 void spudec_free(void *this);


More information about the MPlayer-dev-eng mailing list