changeset 1596:fc0e9953bc2d

libDVDread support
author arpi
date Mon, 20 Aug 2001 21:20:03 +0000
parents 1918610d2802
children 37b81a811cb2
files cfg-mplayer.h configure mplayer.c open.c
diffstat 4 files changed, 349 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/cfg-mplayer.h	Mon Aug 20 20:18:27 2001 +0000
+++ b/cfg-mplayer.h	Mon Aug 20 21:20:03 2001 +0000
@@ -54,6 +54,12 @@
 extern int vo_aa_parseoption(struct config * conf, char *opt, char * param);
 #endif
 
+#ifdef USE_DVDREAD
+extern int dvd_title;
+extern int dvd_chapter;
+extern int dvd_angle;
+#endif
+
 /*
  * CONF_TYPE_FUNC_FULL :
  * allows own implemtations for passing the params
@@ -85,10 +91,10 @@
 #ifdef HAVE_LIBCSS
         {"dvdauth", &dvd_auth_device, CONF_TYPE_STRING, 0, 0, 0},
         {"dvdkey", &dvdimportkey, CONF_TYPE_STRING, 0, 0, 0},
-	{"dvd", "Option -dvd will be \"full disk\" mode, old meaning has been renamed to -dvdauth.\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0},
+//	{"dvd", "Option -dvd will be \"full disk\" mode, old meaning has been renamed to -dvdauth.\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0},
 #else
-        {"dvd", "DVD support was not compiled in. See file DOCS/DVD.\n",
-            CONF_TYPE_PRINT, CONF_NOCFG, 0 , 0},
+//        {"dvd", "DVD support was not compiled in. See file DOCS/DVD.\n",
+//            CONF_TYPE_PRINT, CONF_NOCFG, 0 , 0},
         {"dvdkey", "DVD support was not compiled in. See file DOCS/DVD.\n",
             CONF_TYPE_PRINT, CONF_NOCFG, 0 , 0},
         {"dvdauth", "DVD support was not compiled in. See file DOCS/DVD.\n",
@@ -174,6 +180,13 @@
 	{"dshow", &allow_dshow, CONF_TYPE_FLAG, 0, 0, 1}, // Is this still needed? atmos ::
 	{"nodshow", &allow_dshow, CONF_TYPE_FLAG, 0, 1, 0},
 	{"vcd", &vcd_track, CONF_TYPE_INT, CONF_RANGE, 1, 99},
+#ifdef USE_DVDREAD
+	{"dvd", &dvd_title, CONF_TYPE_INT, CONF_RANGE, 1, 99},
+	{"dvdangle", &dvd_angle, CONF_TYPE_INT, CONF_RANGE, 1, 99},
+	{"chapter", &dvd_chapter, CONF_TYPE_INT, CONF_RANGE, 1, 99},
+#else
+	{"dvd", "MPlayer was compiled WITHOUT libdvdread support!\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0},
+#endif
 	{"divxq", "Option -divxq has been renamed to -pp (postprocessing), use -pp !\n",
             CONF_TYPE_PRINT, 0, 0, 0},
 	{"pp", &divx_quality, CONF_TYPE_INT, CONF_RANGE, 0, 63},
--- a/configure	Mon Aug 20 20:18:27 2001 +0000
+++ b/configure	Mon Aug 20 21:20:03 2001 +0000
@@ -457,6 +457,7 @@
 [ "$system_name" = Linux ] && _fbdev=yes
 _lirc=no
 _css=no
+_dvdread=no
 _win32dll=yes _dshow=yes
 [ "$host_arch" != i386 ] && _dshow=no _win32dll=no
 _fastmemcpy=yes
@@ -872,6 +873,17 @@
 $_cc $_extraincdir $_extralibdir $TMPC -o $TMPO -ldivxdecore > /dev/null 2>&1 || \
  { _divx4linux=no; echo "DivX4Linux includes (decore.h) not found!";}
 
+cat > $TMPC << EOF
+#include <dvdread/dvd_reader.h>
+#include <dvdread/ifo_types.h>
+#include <dvdread/ifo_read.h>
+#include <dvdread/dvd_udf.h>
+#include <dvdread/nav_read.h>
+int main( void ) { return 0; }
+EOF
+$_cc $_extraincdir $_extralibdir -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE $TMPC -o $TMPO -ldvdread > /dev/null 2>&1 && \
+ { _dvdread=yes;_largefiles=yes; }
+
 rm -f $TMPC $TMPO
 
 
@@ -1412,6 +1424,7 @@
 echo "Checking for ESD Audio ... $_esd"
 echo "Checking for Sun Audio ... $_sun_audio"
 echo "Checking for DeCSS support ... $_css"
+echo "Checking for DVDread support ... $_dvdread"
 echo "Checking for PNG support ... $_png"
 echo "Checking for Win32 DLL support ... $_win32dll"
 echo "Checking for DirectShow ... $_dshow"
@@ -1442,6 +1455,16 @@
    fi
 fi
 
+_css='#undef HAVE_LIBCSS'
+_csslib=''
+_cssinc=''
+
+if [ $_dvdread = yes ]; then
+   _csslib='-ldvdread'
+   _dvdreaddef='#define USE_DVDREAD'
+else
+   _dvdreaddef='#undef USE_DVDREAD'
+
 if [ $_css = yes ]; then
    if [ ! -z "$_csslibdir" ]; then
      _csslib="-L${_csslibdir} -lcss"
@@ -1454,10 +1477,8 @@
    else
      _cssinc=""
    fi
-else
-   _css='#undef HAVE_LIBCSS'
-   _csslib=''
-   _cssinc=''
+fi
+
 fi
 
 
@@ -1641,6 +1662,10 @@
 # 64 bit file offsets?
 if [ "$_largefiles" = "yes" -o "$system_name" = "FreeBSD" ]; then
 CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
+  if [ "$_dvdread" = "yes" ]; then
+  # dvdread support requires this (for off64_t)
+  CFLAGS="$CFLAGS -D_LARGEFILE64_SOURCE"
+  fi
 fi
 
 # echo 'CFLAGS=$(OPTFLAGS) -Wall -DMPG12PLAY' >> config.mak
@@ -1899,6 +1924,8 @@
 
 $_debugdef
 
+$_dvdreaddef
+
 /* Common data directory (for fonts, etc) */
 #define DATADIR "$_datadir"
 
@@ -2019,6 +2046,8 @@
 #define DEFAULT_CDROM_DEVICE    "/dev/cdrom"
 #endif
 
+#define DEFAULT_DVD_DEVICE "/dev/dvd"
+
 /*----------------------------------------------------------------------------
 **
 ** NOTE: Instead of modifying these definitions here, use the
--- a/mplayer.c	Mon Aug 20 20:18:27 2001 +0000
+++ b/mplayer.c	Mon Aug 20 21:20:03 2001 +0000
@@ -233,6 +233,8 @@
 static char *stream_dump_name=NULL;
 static int stream_dump_type=0;
 
+extern int dvd_title;
+
 int index_mode=-1;  // -1=untouched  0=don't use index  1=use (geneate) index
 int force_ni=0;
 
@@ -495,8 +497,7 @@
 #endif
 
 if(!filename){
-  if(vcd_track) filename=DEFAULT_CDROM_DEVICE;
-  else {
+  if(!vcd_track && !dvd_title){
     printf("%s",help_text); exit(0);
   }
 }
@@ -591,7 +592,7 @@
        subtitles=sub_read_file(sub_name);
        if(!subtitles) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub,sub_name);
   } else {
-      if(sub_auto)  // auto load sub file ...
+      if(sub_auto && filename)  // auto load sub file ...
          subtitles=sub_read_file( sub_filename( get_path("sub/"), filename ) );
       if(!subtitles) subtitles=sub_read_file(get_path("default.sub")); // try default
   }
@@ -599,7 +600,7 @@
 
   stream=open_stream(filename,vcd_track,&file_format);
   if(!stream) return 1; // error...
-  use_stdin=(!strcmp(filename,"-"));
+  use_stdin=filename && (!strcmp(filename,"-"));
   stream->start_pos+=seek_to_byte;
 
 #ifdef HAVE_LIBCSS
--- a/open.c	Mon Aug 20 20:18:27 2001 +0000
+++ b/open.c	Mon Aug 20 21:20:03 2001 +0000
@@ -22,6 +22,38 @@
 static URL_t* url;
 #endif
 
+int dvd_title=0;
+int dvd_chapter=1;
+int dvd_angle=1;
+
+#ifdef USE_DVDREAD
+
+#include <dvdread/dvd_reader.h>
+#include <dvdread/ifo_types.h>
+#include <dvdread/ifo_read.h>
+#include <dvdread/dvd_udf.h>
+#include <dvdread/nav_read.h>
+//#include <dvdread/nav_print.h>
+
+typedef struct {
+    dvd_reader_t *dvd;
+    dvd_file_t *title;
+    ifo_handle_t *vmg_file;
+    tt_srpt_t *tt_srpt;
+    ifo_handle_t *vts_file;
+    vts_ptt_srpt_t *vts_ptt_srpt;
+    pgc_t *cur_pgc;
+    //
+    int cur_cell;
+    int cur_pack;
+    int cell_last_pack;
+    // Navi:
+    int packs_left;
+    dsi_t dsi_pack;
+} dvd_priv_t;
+
+#endif
+
 extern int vcd_get_track_end(int fd,int track);
 
 // Open a new stream  (stdin/file/vcd/url)
@@ -40,6 +72,7 @@
 //============ Open VideoCD track ==============
 if(vcd_track){
   int ret,ret2;
+  if(!filename) filename=DEFAULT_CDROM_DEVICE;
   f=open(filename,O_RDONLY);
   if(f<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CdDevNotfound,filename);return NULL; }
   vcd_read_toc(f);
@@ -63,6 +96,136 @@
   return stream;
 }
 
+//============ Open DVD title ==============
+#ifdef USE_DVDREAD
+if(dvd_title){
+  int ret,ret2;
+  dvd_priv_t *d;
+    int ttn,pgc_id,pgn;
+    dvd_reader_t *dvd;
+    dvd_file_t *title;
+    ifo_handle_t *vmg_file;
+    tt_srpt_t *tt_srpt;
+    ifo_handle_t *vts_file;
+    /**
+     * Open the disc.
+     */
+    if(!filename) filename=DEFAULT_DVD_DEVICE;
+    dvd = DVDOpen(filename);
+    if( !dvd ) {
+        mp_msg(MSGT_OPEN,MSGL_ERR, "Couldn't open DVD: %s\n",filename);
+        return NULL;
+    }
+
+    mp_msg(MSGT_OPEN,MSGL_INFO, "Reading disc structure, please wait...\n");
+
+    /**
+     * Load the video manager to find out the information about the titles on
+     * this disc.
+     */
+    vmg_file = ifoOpen( dvd, 0 );
+    if( !vmg_file ) {
+        mp_msg(MSGT_OPEN,MSGL_ERR, "Can't open VMG info!\n");
+        DVDClose( dvd );
+        return NULL;
+    }
+    tt_srpt = vmg_file->tt_srpt;
+    /**
+     * Make sure our title number is valid.
+     */
+    mp_msg(MSGT_OPEN,MSGL_INFO, "There are %d titles on this DVD.\n",
+             tt_srpt->nr_of_srpts );
+    if( dvd_title < 1 || dvd_title > tt_srpt->nr_of_srpts ) {
+	mp_msg(MSGT_OPEN,MSGL_ERR, "Invalid DVD title number: %d\n", dvd_title);
+        ifoClose( vmg_file );
+        DVDClose( dvd );
+        return NULL;
+    }
+    --dvd_title; // remap 1.. -> 0..
+    /**
+     * Make sure the chapter number is valid for this title.
+     */
+    mp_msg(MSGT_OPEN,MSGL_INFO, "There are %d chapters in this DVD title.\n",
+             tt_srpt->title[dvd_title].nr_of_ptts );
+    if( dvd_chapter<1 || dvd_chapter>tt_srpt->title[dvd_title].nr_of_ptts ) {
+	mp_msg(MSGT_OPEN,MSGL_ERR, "Invalid DVD chapter number: %d\n", dvd_chapter);
+        ifoClose( vmg_file );
+        DVDClose( dvd );
+        return NULL;
+    }
+    --dvd_chapter; // remap 1.. -> 0..
+    /**
+     * Make sure the angle number is valid for this title.
+     */
+    mp_msg(MSGT_OPEN,MSGL_INFO, "There are %d angles in this DVD title.\n",
+             tt_srpt->title[dvd_title].nr_of_angles );
+    if( dvd_angle<1 || dvd_angle>tt_srpt->title[dvd_title].nr_of_angles ) {
+	mp_msg(MSGT_OPEN,MSGL_ERR, "Invalid DVD angle number: %d\n", dvd_angle);
+        ifoClose( vmg_file );
+        DVDClose( dvd );
+        return NULL;
+    }
+    /**
+     * Load the VTS information for the title set our title is in.
+     */
+    vts_file = ifoOpen( dvd, tt_srpt->title[dvd_title].title_set_nr );
+    if( !vts_file ) {
+	mp_msg(MSGT_OPEN,MSGL_ERR, "Can't open the IFO file for DVD title %d.\n",
+                 tt_srpt->title[dvd_title].title_set_nr );
+        ifoClose( vmg_file );
+        DVDClose( dvd );
+        return NULL;
+    }
+    /**
+     * We've got enough info, time to open the title set data.
+     */
+    title = DVDOpenFile( dvd, tt_srpt->title[dvd_title].title_set_nr,
+                         DVD_READ_TITLE_VOBS );
+    if( !title ) {
+	mp_msg(MSGT_OPEN,MSGL_ERR, "Can't open title VOBS (VTS_%02d_1.VOB).\n",
+                 tt_srpt->title[dvd_title].title_set_nr );
+        ifoClose( vts_file );
+        ifoClose( vmg_file );
+        DVDClose( dvd );
+        return NULL;
+    }
+
+    mp_msg(MSGT_OPEN,MSGL_INFO, "DVD successfully opened!\n");
+    // store data
+    d=malloc(sizeof(dvd_priv_t)); memset(d,0,sizeof(dvd_priv_t));
+    d->dvd=dvd;
+    d->title=title;
+    d->vmg_file=vmg_file;
+    d->tt_srpt=tt_srpt;
+    d->vts_file=vts_file;
+
+    /**
+     * Determine which program chain we want to watch.  This is based on the
+     * chapter number.
+     */
+    ttn = tt_srpt->title[ dvd_title ].vts_ttn; // local
+    pgc_id = vts_file->vts_ptt_srpt->title[ttn-1].ptt[dvd_chapter].pgcn; // local
+    pgn    = vts_file->vts_ptt_srpt->title[ttn-1].ptt[dvd_chapter].pgn;  // local
+    d->cur_pgc = vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc;
+    d->cur_cell = d->cur_pgc->program_map[pgn-1] - 1; // start playback here
+    d->packs_left=-1;      // for Navi stuff
+    
+    if( d->cur_pgc->cell_playback[d->cur_cell].block_type 
+	== BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle;
+    d->cur_pack = d->cur_pgc->cell_playback[ d->cur_cell ].first_sector;
+    d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector;
+    mp_msg(MSGT_DVD,MSGL_V, "DVD start cell: %d  pack: 0x%X-0x%X  \n",d->cur_cell,d->cur_pack,d->cell_last_pack);
+
+    // ... (unimplemented)
+//    return NULL;
+  stream=new_stream(-1,STREAMTYPE_DVD);
+  stream->start_pos=(off_t)d->cur_pack*2048;
+  //stream->end_pos=0;
+  stream->priv=(void*)d;
+  return stream;
+}
+#endif
+
 //============ Open STDIN ============
   if(!strcmp(filename,"-")){
       // read from stdin
@@ -107,3 +270,135 @@
        return stream;
 
 }
+
+
+#ifdef USE_DVDREAD
+
+static int dvd_next_cell(dvd_priv_t *d){
+    int next_cell=d->cur_cell;
+    
+    if( d->cur_pgc->cell_playback[ next_cell ].block_type
+                                        == BLOCK_TYPE_ANGLE_BLOCK ) {
+	    int i;
+	    while(next_cell<d->cur_pgc->nr_of_cells){
+                if( d->cur_pgc->cell_playback[next_cell].block_mode
+                                          == BLOCK_MODE_LAST_CELL ) break;
+		++next_cell;
+            }
+    }
+    
+    ++next_cell;
+    if(next_cell>=d->cur_pgc->nr_of_cells) return -1; // EOF
+    if( d->cur_pgc->cell_playback[next_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK ){
+	next_cell+=dvd_angle;
+	if(next_cell>=d->cur_pgc->nr_of_cells) return -1; // EOF
+    }
+    return next_cell;
+}
+
+int dvd_read_sector(dvd_priv_t *d,unsigned char* data){
+    int len;
+    
+    if(d->packs_left==0){
+            /**
+             * If we're not at the end of this cell, we can determine the next
+             * VOBU to display using the VOBU_SRI information section of the
+             * DSI.  Using this value correctly follows the current angle,
+             * avoiding the doubled scenes in The Matrix, and makes our life
+             * really happy.
+             *
+             * Otherwise, we set our next address past the end of this cell to
+             * force the code above to go to the next cell in the program.
+             */
+            if( d->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL ) {
+                d->cur_pack= d->dsi_pack.dsi_gi.nv_pck_lbn +
+		( d->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
+		mp_msg(MSGT_DVD,MSGL_DBG2, "Navi  new pos=0x%X  \n",d->cur_pack);
+            } else {
+		// end of cell! find next cell!
+		mp_msg(MSGT_DVD,MSGL_V, "--- END OF CELL !!! ---\n");
+		d->cur_pack=d->cell_last_pack+1;
+            }
+    }
+
+read_next:
+
+    if(d->cur_pack>d->cell_last_pack){
+	// end of cell!
+	int next=dvd_next_cell(d);
+	if(next>=0){
+	    d->cur_cell=next;
+
+    if( d->cur_pgc->cell_playback[d->cur_cell].block_type 
+	== BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle;
+    d->cur_pack = d->cur_pgc->cell_playback[ d->cur_cell ].first_sector;
+    d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector;
+    mp_msg(MSGT_DVD,MSGL_V, "DVD next cell: %d  pack: 0x%X-0x%X  \n",d->cur_cell,d->cur_pack,d->cell_last_pack);
+	    
+	} else return -1; // EOF
+    }
+
+    len = DVDReadBlocks( d->title, d->cur_pack, 1, data );
+    if(!len) return -1; //error
+    
+    if(data[38]==0 && data[39]==0 && data[40]==1 && data[41]==0xBF &&
+       data[1024]==0 && data[1025]==0 && data[1026]==1 && data[1027]==0xBF){
+	// found a Navi packet!!!
+        navRead_DSI( &d->dsi_pack, &(data[ DSI_START_BYTE ]), sizeof(dsi_t) );
+	if(d->cur_pack != d->dsi_pack.dsi_gi.nv_pck_lbn ){
+	    mp_msg(MSGT_DVD,MSGL_V, "Invalid NAVI packet! lba=0x%X  navi=0x%X  \n",
+		d->cur_pack,d->dsi_pack.dsi_gi.nv_pck_lbn);
+	} else {
+	    // process!
+    	    d->packs_left = d->dsi_pack.dsi_gi.vobu_ea;
+	    mp_msg(MSGT_DVD,MSGL_DBG2, "Found NAVI packet! lba=0x%X  len=%d  \n",d->cur_pack,d->packs_left);
+	}
+	++d->cur_pack;
+	goto read_next;
+    }
+
+    ++d->cur_pack;
+    if(d->packs_left>=0) --d->packs_left;
+
+    return d->cur_pack-1;
+}
+
+void dvd_seek(dvd_priv_t *d,int pos){
+    d->packs_left=-1;
+    d->cur_pack=pos;
+    
+// check if we stay in current cell (speedup things, and avoid angle skip)
+if(d->cur_pack>d->cell_last_pack &&
+   d->cur_pack<d->cur_pgc->cell_playback[ d->cur_cell ].first_sector){
+
+    // ok, cell change, find the right cell!
+    d->cur_cell=0;
+    if( d->cur_pgc->cell_playback[d->cur_cell].block_type 
+	== BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle;
+
+  while(1){
+    int next;
+    d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector;
+    if(d->cur_pack<d->cur_pgc->cell_playback[ d->cur_cell ].first_sector){
+	d->cur_pack=d->cur_pgc->cell_playback[ d->cur_cell ].first_sector;
+	break;
+    }
+    if(d->cur_pack<=d->cell_last_pack) break; // ok, we find it! :)
+    next=dvd_next_cell(d);
+    if(next<0){
+//	d->cur_pack=d->cell_last_pack+1;
+	break; // we're after the last cell
+    }
+    d->cur_cell=next;
+  }
+}
+
+mp_msg(MSGT_DVD,MSGL_V, "DVD Seek! lba=0x%X  cell=%d  packs: 0x%X-0x%X  \n",
+    d->cur_pack,d->cur_cell,d->cur_pgc->cell_playback[ d->cur_cell ].first_sector,d->cell_last_pack);
+
+// TODO: if we're in interleaved multi-angle cell, find the right angle chain!
+// (read Navi block, and use the seamless angle jump table)
+
+}
+
+#endif