[gst-devel] dvd code

David I. Lehn dlehn at vt.edu
Thu Oct 4 23:03:02 CEST 2001


Here's a dvd playing patch.  Makes dvdsrc more high level.  Uses latest
libdvdread + libdvdcss.  I'm no diff master so put the dvdplay.c file in
./test/.  To play title 1, chap 1, angle 1 of /dev/dvd:

./test/dvdplay /dev/dvd 1 1 1

-dave
-- 
David I. Lehn <dlehn at vt.edu>  | http://www.lehn.org/~dlehn/
Computer Engineering Graduate @ Virginia Tech in sunny Blacksburg, VA
-------------- next part --------------
Index: REQUIREMENTS
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/REQUIREMENTS,v
retrieving revision 1.19
diff -u -r1.19 REQUIREMENTS
--- REQUIREMENTS	2001/07/18 22:08:30	1.19
+++ REQUIREMENTS	2001/10/05 05:42:04
@@ -53,8 +53,9 @@
 			http://www.arts-project.org
 raw1394/linux1394	(for the dv plugin)
 			http://linux1394.sourceforge.net
-decss		(for the dvdsrc)
-			http://www.linuxrising.com/dvd-munitions_tar.gz
+libdvdread	(for the dvdsrc)
+			http://www.dtek.chalmers.se/groups/dvd/
+			(optional: libcss for encrypted DVDs)
 libesound	(for the esd sink 
 			ftp.gnome.org/pub/GNOME/stable/sources/esound)
 gnome-vfs	(for the gnome-vfs src)
Index: acconfig.h
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/acconfig.h,v
retrieving revision 1.37
diff -u -r1.37 acconfig.h
--- acconfig.h	2001/09/06 20:12:17	1.37
+++ acconfig.h	2001/10/05 05:42:04
@@ -30,7 +30,7 @@
 #undef HAVE_LIBXV
 #undef HAVE_OSS
 #undef HAVE_XAUDIO
-#undef HAVE_CSSAUTH
+#undef HAVE_LIBDVDREAD
 #undef HAVE_VORBIS
 #undef HAVE_LIBMAD
 #undef HAVE_LIBMIKMOD
Index: configure.base
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/configure.base,v
retrieving revision 1.89
diff -u -r1.89 configure.base
--- configure.base	2001/10/04 08:53:47	1.89
+++ configure.base	2001/10/05 05:42:04
@@ -197,7 +197,6 @@
 AC_MSG_RESULT(no)
 ])
 
-
 dnl Check for essential libraries first:
 dnl ====================================
 
@@ -658,18 +657,11 @@
 AC_MSG_CHECKING(openquicktime)
 AC_CHECK_LIB(openquicktime, quicktime_init, HAVE_LIBOPENQUICKTIME=yes, HAVE_LIBOPENQUICKTIME=no, )
 AC_CHECK_HEADER(openquicktime/openquicktime.h, :, HAVE_LIBOPENQUICKTIME=no)
-
 
-dnl check if css-auth.c exists (FIXME)
-AC_MSG_CHECKING(DVD CSS code)
-if test -f plugins/dvdsrc/css-auth.c
-then
-  AC_MSG_RESULT(yes)
-  HAVE_CSSAUTH="yes"
-else
-  AC_MSG_RESULT(no)
-  HAVE_CSSAUTH="no"
-fi
+dnl Check for libdvdread
+AC_MSG_CHECKING(libdvdread)
+AC_CHECK_LIB(dvdread, DVDOpen, HAVE_LIBDVDREAD=yes, HAVE_LIBDVDREAD=no, )
+AC_CHECK_HEADER(dvdread/dvd_reader.h, :, HAVE_LIBDVDREAD=no)
 
 dnl Check for SDL library
 AC_MSG_CHECKING(SDL library)
@@ -968,8 +960,8 @@
   AC_DEFINE(HAVE_LIBHERMES)
 fi
 
-if test "x$HAVE_CSSAUTH" = xyes; then
-  AC_DEFINE(HAVE_CSSAUTH)
+if test "x$HAVE_LIBDVDREAD" = xyes; then
+  AC_DEFINE(HAVE_LIBDVDREAD)
 fi
 
 if test "x$HAVE_LINUX_CDROM" = xyes; then
@@ -1015,7 +1007,7 @@
 AM_CONDITIONAL(HAVE_LIBMIKMOD,      test "x$HAVE_LIBMIKMOD" = "xyes")
 AM_CONDITIONAL(HAVE_LINUX_CDROM,    test "x$HAVE_LINUX_CDROM" = "xyes")
 AM_CONDITIONAL(HAVE_LINUX_VIDEODEV, test "x$HAVE_LINUX_VIDEODEV" = "xyes")
-AM_CONDITIONAL(HAVE_CSSAUTH,        test "x$HAVE_CSSAUTH" = "xyes")
+AM_CONDITIONAL(HAVE_LIBDVDREAD,     test "x$HAVE_LIBDVDREAD" = "xyes")
 AM_CONDITIONAL(HAVE_VORBIS,         test "x$HAVE_VORBIS" = "xyes")
 AM_CONDITIONAL(HAVE_LIBJPEG,        test "x$HAVE_LIBJPEG" = "xyes")
 AM_CONDITIONAL(HAVE_LIBSDL,         test "x$HAVE_LIBSDL" = "xyes")
@@ -1063,7 +1055,7 @@
 dnl ############################
 
 dnl Set location of configuration dir.
-dnl AC_DEFINE_UNQUOTED(GST_CONFIG_DIR,"$GST_CONFIG_DIR")
+AC_DEFINE_UNQUOTED(GST_CONFIG_DIR,"$GST_CONFIG_DIR")
 AC_SUBST(GST_CONFIG_DIR)
 
 dnl Set location of windows dll dir.
Index: plugins/Makefile.am
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/plugins/Makefile.am,v
retrieving revision 1.64
diff -u -r1.64 Makefile.am
--- plugins/Makefile.am	2001/09/06 20:12:17	1.64
+++ plugins/Makefile.am	2001/10/05 05:42:05
@@ -10,7 +10,7 @@
 JPEG_SUBDS = 
 endif
 
-if HAVE_CSSAUTH
+if HAVE_LIBDVDREAD
 DVD_SUBDS = dvdsrc
 else
 DVD_SUBDS = 
Index: plugins/dvdsrc/Makefile.am
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/plugins/dvdsrc/Makefile.am,v
retrieving revision 1.8
diff -u -r1.8 Makefile.am
--- plugins/dvdsrc/Makefile.am	2001/09/17 23:40:18	1.8
+++ plugins/dvdsrc/Makefile.am	2001/10/05 05:42:05
@@ -2,17 +2,14 @@
 
 filter_LTLIBRARIES = libdvdsrc.la
 
+LIBDVDREADCFLAGS =
+LIBDVDREADLIBS = -ldvdread
 
-if HAVE_CSSAUTH
-CSSAUTH_SRC = css-auth.c css-descramble.c
-CSSAUTH_HDR = css-auth.h css-descramble.h
-else
-CSSAUTH_SRC =
-CSSAUTH_HDR =
-endif
+AM_CFLAGS = -D_LARGEFILE64_SOURCE $(LIBDVDREADCFLAGS)
 
-libdvdsrc_la_SOURCES = dvdsrc.c $(CSSAUTH_SRC)
+libdvdsrc_la_SOURCES = dvdsrc.c
+libdvdsrc_la_LDFLAGS = $(LIBDVDREADLIBS)
 
-noinst_HEADERS = dvdsrc.h $(CSSAUTH_HDR)
+noinst_HEADERS = dvdsrc.h
 
 EXTRA_DIST = README
Index: plugins/dvdsrc/dvdsrc.c
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/plugins/dvdsrc/dvdsrc.c,v
retrieving revision 1.10
diff -u -r1.10 dvdsrc.c
--- plugins/dvdsrc/dvdsrc.c	2001/08/22 21:47:51	1.10
+++ plugins/dvdsrc/dvdsrc.c	2001/10/05 05:42:05
@@ -17,6 +17,24 @@
  * Boston, MA 02111-1307, USA.
  */
 
+/**
+ * Copyright (C) 2001 Billy Biggs <vektor at dumbterm.net>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -30,9 +48,40 @@
 #include <dirent.h>
 #include <errno.h>
 #include <linux/cdrom.h>
+#include <assert.h>
 
 #include <dvdsrc.h>
 
+#include "config.h"
+
+#include <dvdread/dvd_reader.h>
+#include <dvdread/ifo_types.h>
+#include <dvdread/ifo_read.h>
+#include <dvdread/nav_read.h>
+#include <dvdread/nav_print.h>
+
+struct _DVDSrcPrivate {
+  GstElement element;
+  /* pads */
+  GstPad *srcpad;
+
+  /* location */
+  gchar *location;
+
+  gboolean new_seek;
+
+  int title, chapter, angle;
+  int pgc_id, start_cell, cur_cell, cur_pack;
+  int ttn, pgn, next_cell;
+  dvd_reader_t *dvd;
+  dvd_file_t *dvd_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;
+};
+
 
 GstElementDetails dvdsrc_details = {
   "DVD Source",
@@ -40,7 +89,7 @@
   "Asynchronous read from encrypted DVD disk",
   VERSION,
   "Erik Walthinsen <omega at cse.ogi.edu>",
-  "(C) 1999",
+  "(C) 2001",
 };
 
 
@@ -53,22 +102,21 @@
 enum {
   ARG_0,
   ARG_LOCATION,
-  ARG_DEVICE,
-  ARG_TITLE_KEY,
-  ARG_BYTESPERREAD,
-  ARG_OFFSET,
-  ARG_FILESIZE,
+  ARG_TITLE,
+  ARG_CHAPTER,
+  ARG_ANGLE
 };
 
 
-static void 			dvdsrc_class_init	(DVDSrcClass *klass);
-static void 			dvdsrc_init		(DVDSrc *dvdsrc);
+static void 		dvdsrc_class_init	(DVDSrcClass *klass);
+static void 		dvdsrc_init		(DVDSrc *dvdsrc);
 
-static void 			dvdsrc_set_property		(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static void 			dvdsrc_get_property		(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+static void 		dvdsrc_set_property		(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void 		dvdsrc_get_property		(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
 
-static GstBuffer *		dvdsrc_get		(GstPad *pad);
-//static GstBuffer *		dvdsrc_get_region	(GstPad *pad,gulong offset,gulong size);
+//static GstBuffer *	dvdsrc_get		(GstPad *pad);
+static void     	dvdsrc_loop		(GstElement *element);
+//static GstBuffer *	dvdsrc_get_region	(GstPad *pad,gulong offset,gulong size);
 
 static GstElementStateReturn 	dvdsrc_change_state 	(GstElement *element);
 
@@ -110,25 +158,19 @@
 
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_LOCATION,
     g_param_spec_string("location","location","location",
-                        NULL, G_PARAM_READWRITE)); // CHECKME
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE,
-    g_param_spec_string("device","device","device",
-                        NULL, G_PARAM_READWRITE)); // CHECKME
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_TITLE_KEY,
-    g_param_spec_string("title_key","title_key","title_key",
-                        NULL, G_PARAM_READWRITE)); // CHECKME
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BYTESPERREAD,
-    g_param_spec_int("bytesperread","bytesperread","bytesperread",
-                     G_MININT,G_MAXINT,0,G_PARAM_READABLE)); // CHECKME
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_OFFSET,
-    g_param_spec_int("offset","offset","offset",
-                     G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FILESIZE,
-    g_param_spec_int("filesize","filesize","filesize",
-                     G_MININT,G_MAXINT,0,G_PARAM_READABLE)); // CHECKME
+                        NULL, G_PARAM_READWRITE));
+  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_TITLE,
+    g_param_spec_int("title","title","title",
+                     0,G_MAXINT,0,G_PARAM_READWRITE));
+  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHAPTER,
+    g_param_spec_int("chapter","chapter","chapter",
+                     0,G_MAXINT,0,G_PARAM_READWRITE));
+  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ANGLE,
+    g_param_spec_int("angle","angle","angle",
+                     0,G_MAXINT,0,G_PARAM_READWRITE));
 
-  gobject_class->set_property = dvdsrc_set_property;
-  gobject_class->get_property = dvdsrc_get_property;
+  gobject_class->set_property = GST_DEBUG_FUNCPTR(dvdsrc_set_property);
+  gobject_class->get_property = GST_DEBUG_FUNCPTR(dvdsrc_get_property);
 
   gstelement_class->change_state = dvdsrc_change_state;
 }
@@ -136,83 +178,65 @@
 static void 
 dvdsrc_init (DVDSrc *dvdsrc) 
 {
-  dvdsrc->srcpad = gst_pad_new ("src", GST_PAD_SRC);
-  gst_pad_set_get_function (dvdsrc->srcpad, dvdsrc_get);
-  gst_element_add_pad (GST_ELEMENT (dvdsrc), dvdsrc->srcpad);
-
-  dvdsrc->filename = "/cdrom/VIDEO_TS/VTS_02_1.VOB";
-  dvdsrc->device = "/dev/dvd";
-//  dvdsrc->device = NULL;
-  dvdsrc->title_key = NULL;
-  dvdsrc->fd = 0;
-  dvdsrc->curoffset = 0;
-  dvdsrc->bytes_per_read = 2048;
-  dvdsrc->seq = 0;
-  dvdsrc->new_seek = FALSE;
+  dvdsrc->priv = g_new(DVDSrcPrivate, 1);
+  dvdsrc->priv->srcpad = gst_pad_new ("src", GST_PAD_SRC);
+  gst_element_add_pad (GST_ELEMENT (dvdsrc), dvdsrc->priv->srcpad);
+  gst_element_set_loop_function (GST_ELEMENT(dvdsrc), GST_DEBUG_FUNCPTR(dvdsrc_loop));
+
+  dvdsrc->priv->location = "/dev/dvd";
+  dvdsrc->priv->new_seek = FALSE;
+  dvdsrc->priv->title = 1;
+  dvdsrc->priv->chapter = 1;
+  dvdsrc->priv->angle = 1;
 }
-
 
-static void 
-super_seek (int fd, guint64 offset) 
+static void
+dvdsrc_destory (DVDSrc *dvdsrc)
 {
-  int i;
-
-  lseek (fd, offset%0x7FFFFFFF, SEEK_SET);
-  for (i=0; i < offset/0x7FFFFFFF; i++) {
-    lseek (fd, 0x7FFFFFFF, SEEK_CUR);
-  }
+  // FIXME
+  g_print("FIXME\n");
+  g_free(dvdsrc->priv);
 }
 
 static void 
 dvdsrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) 
 {
   DVDSrc *src;
+  DVDSrcPrivate *priv;
 
   /* it's not null if we got it, but it might not be ours */
   g_return_if_fail (GST_IS_DVDSRC (object));
   
   src = DVDSRC (object);
+  priv = src->priv;
 
   switch (prop_id) {
     case ARG_LOCATION:
       /* the element must be stopped in order to do this */
-//      g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING));
+      //g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING));
 
-      if (src->filename) g_free (src->filename);
+      if (priv->location)
+        g_free (priv->location);
       /* clear the filename if we get a NULL (is that possible?) */
       if (g_value_get_string (value) == NULL)
-        src->filename = NULL;
+        priv->location = "/dev/dvd";
       /* otherwise set the new filename */
       else
-        src->filename = g_strdup (g_value_get_string (value));  
+        priv->location = g_strdup (g_value_get_string (value));  
       break;
-    case ARG_DEVICE:
-      /* the element must be stopped in order to do this */
-//      g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING));
-
-      if (src->device) g_free (src->device);
-      /* reset the device if we get a NULL (is that possible?) */
-      if (g_value_get_string (value) == NULL)
-        src->device = "/dev/dvd";
-      /* otherwise set the new filename */
-      else
-        src->device = g_strdup (g_value_get_string (value));  
-      break;
-    case ARG_TITLE_KEY:
-      /* the element must be stopped in order to do this */
-//      g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING));
-      src->title_key = g_value_get_pointer (value);
-      break;
-    case ARG_BYTESPERREAD:
-      src->bytes_per_read = g_value_get_int (value);
+    case ARG_TITLE:
+      priv->title = g_value_get_int (value) - 1;
+      priv->new_seek = TRUE;
+      break;
+    case ARG_CHAPTER:
+      priv->chapter = g_value_get_int (value) - 1;
+      priv->new_seek = TRUE;
       break;
-    case ARG_OFFSET:
-      src->curoffset = g_value_get_int (value) & ~0x000007ff;
-      if (GST_FLAG_IS_SET (src, DVDSRC_OPEN))
-        super_seek (src->fd, (DVDSRC_BASEOFFSET*2048) + src->curoffset);
-      src->new_seek = TRUE;
+    case ARG_ANGLE:
+      priv->angle = g_value_get_int (value) - 1;
       break;
     default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 
@@ -222,48 +246,447 @@
 dvdsrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) 
 {
   DVDSrc *src;
+  DVDSrcPrivate *priv;
 
   /* it's not null if we got it, but it might not be ours */
   g_return_if_fail (GST_IS_DVDSRC (object));
   
   src = DVDSRC (object);
+  priv = src->priv;
 
   switch (prop_id) {
     case ARG_LOCATION:
-      g_value_set_string (value, src->filename);
+      g_value_set_string (value, priv->location);
       break;
-    case ARG_DEVICE:
-      g_value_set_string (value, src->device);
+    case ARG_TITLE:
+      g_value_set_int (value, priv->title + 1);
       break;
-    case ARG_TITLE_KEY:
-      g_value_set_pointer (value, src->title_key);
+    case ARG_CHAPTER:
+      g_value_set_int (value, priv->chapter + 1);
       break;
-    case ARG_BYTESPERREAD:
-      g_value_set_int (value, src->bytes_per_read);
+    case ARG_ANGLE:
+      g_value_set_int (value, priv->angle + 1);
       break;
-    case ARG_OFFSET:
-      g_value_set_int (value, src->curoffset);
-      break;
-    case ARG_FILESIZE:
-      g_value_set_int (value, src->size);
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
 
+/**
+ * Returns true if the pack is a NAV pack.  This check is clearly insufficient,
+ * and sometimes we incorrectly think that valid other packs are NAV packs.  I
+ * need to make this stronger.
+ */
+static int
+is_nav_pack( unsigned char *buffer )
+{
+    return ( buffer[ 41 ] == 0xbf && buffer[ 1027 ] == 0xbf );
+}
+
+static int
+_open(DVDSrcPrivate *priv, const gchar *location)
+{
+  g_return_val_if_fail(priv != NULL, -1);
+  g_return_val_if_fail(location != NULL, -1);
+
+  /**
+   * Open the disc.
+   */
+  priv->dvd = DVDOpen( location );
+  if( !priv->dvd ) {
+    fprintf( stderr, "Couldn't open DVD: %s\n", location );
+    return -1;
+  }
+
+
+  /**
+   * Load the video manager to find out the information about the titles on
+   * this disc.
+   */
+  priv->vmg_file = ifoOpen( priv->dvd, 0 );
+  if( !priv->vmg_file ) {
+    fprintf( stderr, "Can't open VMG info.\n" );
+    DVDClose( priv->dvd );
+    return -1;
+  }
+  priv->tt_srpt = priv->vmg_file->tt_srpt;
+
+  return 0;
+}
+
+static int
+_close(DVDSrcPrivate *priv)
+{
+    ifoClose( priv->vts_file );
+    ifoClose( priv->vmg_file );
+    DVDCloseFile( priv->dvd_title );
+    DVDClose( priv->dvd );
+    return 0;
+}
+
+static int
+_seek(DVDSrcPrivate *priv, int title, int chapter, int angle)
+{
+    /**
+     * Make sure our title number is valid.
+     */
+    fprintf( stderr, "There are %d titles on this DVD.\n",
+             priv->tt_srpt->nr_of_srpts );
+    if( title < 0 || title >= priv->tt_srpt->nr_of_srpts ) {
+        fprintf( stderr, "Invalid title %d.\n", title + 1 );
+        ifoClose( priv->vmg_file );
+        DVDClose( priv->dvd );
+        return -1;
+    }
+
+
+    /**
+     * Make sure the chapter number is valid for this title.
+     */
+    fprintf( stderr, "There are %d chapters in this title.\n",
+             priv->tt_srpt->title[ title ].nr_of_ptts );
+
+    if( chapter < 0 || chapter >= priv->tt_srpt->title[ title ].nr_of_ptts ) {
+        fprintf( stderr, "Invalid chapter %d\n", chapter + 1 );
+        ifoClose( priv->vmg_file );
+        DVDClose( priv->dvd );
+        return -1;
+    }
+
+
+    /**
+     * Make sure the angle number is valid for this title.
+     */
+    fprintf( stderr, "There are %d angles in this title.\n",
+             priv->tt_srpt->title[ title ].nr_of_angles );
+    if( angle < 0 || angle >= priv->tt_srpt->title[ title ].nr_of_angles ) {
+        fprintf( stderr, "Invalid angle %d\n", angle + 1 );
+        ifoClose( priv->vmg_file );
+        DVDClose( priv->dvd );
+        return -1;
+    }
+
+
+    /**
+     * Load the VTS information for the title set our title is in.
+     */
+    priv->vts_file = ifoOpen( priv->dvd, priv->tt_srpt->title[ title ].title_set_nr );
+    if( !priv->vts_file ) {
+        fprintf( stderr, "Can't open the title %d info file.\n",
+                 priv->tt_srpt->title[ title ].title_set_nr );
+        ifoClose( priv->vmg_file );
+        DVDClose( priv->dvd );
+        return -1;
+    }
+
+
+    /**
+     * Determine which program chain we want to watch.  This is based on the
+     * chapter number.
+     */
+    priv->ttn = priv->tt_srpt->title[ title ].vts_ttn;
+    priv->vts_ptt_srpt = priv->vts_file->vts_ptt_srpt;
+    priv->pgc_id = priv->vts_ptt_srpt->title[ priv->ttn - 1 ].ptt[ chapter ].pgcn;
+    priv->pgn = priv->vts_ptt_srpt->title[ priv->ttn - 1 ].ptt[ chapter ].pgn;
+    priv->cur_pgc = priv->vts_file->vts_pgcit->pgci_srp[ priv->pgc_id - 1 ].pgc;
+    priv->start_cell = priv->cur_pgc->program_map[ priv->pgn - 1 ] - 1;
+
+
+    /**
+     * We've got enough info, time to open the title set data.
+     */
+    priv->dvd_title = DVDOpenFile( priv->dvd, priv->tt_srpt->title[ title ].title_set_nr,
+                         DVD_READ_TITLE_VOBS );
+    if( !priv->dvd_title ) {
+        fprintf( stderr, "Can't open title VOBS (VTS_%02d_1.VOB).\n",
+                 priv->tt_srpt->title[ title ].title_set_nr );
+        ifoClose( priv->vts_file );
+        ifoClose( priv->vmg_file );
+        DVDClose( priv->dvd );
+        return -1;
+    }
+
+    return 0;
+}
+
+static void
+dvdsrc_loop (GstElement *element) 
+{
+  DVDSrc *dvdsrc;
+  DVDSrcPrivate *priv;
+
+  g_return_if_fail (element != NULL);
+  g_return_if_fail (GST_IS_DVDSRC (element));
+
+  dvdsrc = DVDSRC (element);
+  priv = dvdsrc->priv;
+  g_return_if_fail (GST_FLAG_IS_SET (dvdsrc, DVDSRC_OPEN));
+
+  do {
+    /**
+     * Playback by cell in this pgc, starting at the cell for our chapter.
+     */
+    priv->next_cell = priv->start_cell;
+    for( priv->cur_cell = priv->start_cell; priv->next_cell < priv->cur_pgc->nr_of_cells; ) {
+
+        priv->cur_cell = priv->next_cell;
+
+        /* Check if we're entering an angle block. */
+        if( priv->cur_pgc->cell_playback[ priv->cur_cell ].block_type
+                                        == BLOCK_TYPE_ANGLE_BLOCK ) {
+            int i;
+
+            priv->cur_cell += priv->angle;
+            for( i = 0;; ++i ) {
+                if( priv->cur_pgc->cell_playback[ priv->cur_cell + i ].block_mode
+                                          == BLOCK_MODE_LAST_CELL ) {
+                    priv->next_cell = priv->cur_cell + i + 1;
+                    break;
+                }
+            }
+        } else {
+            priv->next_cell = priv->cur_cell + 1;
+        }
+
+
+        /**
+         * We loop until we're out of this cell.
+         */
+        for( priv->cur_pack = priv->cur_pgc->cell_playback[ priv->cur_cell ].first_sector;
+             priv->cur_pack < priv->cur_pgc->cell_playback[ priv->cur_cell ].last_sector; ) {
+
+            dsi_t dsi_pack;
+            unsigned int next_vobu, next_ilvu_start, cur_output_size;
+            GstBuffer *buf;
+            unsigned char *data;
+            int len;
+
+            /* create the buffer */
+            // FIXME: should eventually use a bufferpool for this
+            buf = gst_buffer_new ();
+            g_return_if_fail (buf);
+
+            /* allocate the space for the buffer data */
+            data = g_malloc (1024 * DVD_VIDEO_LB_LEN);
+            GST_BUFFER_DATA (buf) = data;
+
+            g_return_if_fail (GST_BUFFER_DATA (buf) != NULL);
+
+            /*
+            if (priv->new_seek) {
+              _seek(priv, priv->titleid, priv->chapid, priv->angle);
+              GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLUSH);
+              priv->new_seek = FALSE;
+            }
+            */
+
+            /**
+             * Read NAV packet.
+             */
+            len = DVDReadBlocks( priv->dvd_title, priv->cur_pack, 1, data );
+            if( len == 0 ) {
+                fprintf( stderr, "Read failed for block %d\n", priv->cur_pack );
+                _close(priv);
+                gst_element_signal_eos (GST_ELEMENT (dvdsrc));
+                return;
+            }
+            assert( is_nav_pack( data ) );
+
+
+            /**
+             * Parse the contained dsi packet.
+             */
+            navRead_DSI( &dsi_pack, &(data[ DSI_START_BYTE ]) );
+            assert( priv->cur_pack == dsi_pack.dsi_gi.nv_pck_lbn );
+            navPrint_DSI(&dsi_pack);
+
+
+            /**
+             * Determine where we go next.  These values are the ones we mostly
+             * care about.
+             */
+            next_ilvu_start = priv->cur_pack
+                              + dsi_pack.sml_agli.data[ priv->angle ].address;
+            cur_output_size = dsi_pack.dsi_gi.vobu_ea;
+
+
+            /**
+             * 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( dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL ) {
+                next_vobu = priv->cur_pack
+                            + ( dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
+            } else {
+                next_vobu = priv->cur_pack + cur_output_size + 1;
+            }
+
+            assert( cur_output_size < 1024 );
+            priv->cur_pack++;
+
+            /**
+             * Read in and output cursize packs.
+             */
+            len = DVDReadBlocks( priv->dvd_title, priv->cur_pack,
+                                         cur_output_size, data );
+            if( len != cur_output_size ) {
+                fprintf( stderr, "Read failed for %d blocks at %d\n",
+                         cur_output_size, priv->cur_pack );
+                _close(priv);
+                gst_element_signal_eos (GST_ELEMENT (dvdsrc));
+                return;
+            }
+
+            GST_BUFFER_SIZE(buf) = cur_output_size * DVD_VIDEO_LB_LEN;
+            gst_pad_push(priv->srcpad, buf);
+            gst_buffer_unref(buf);
+            priv->cur_pack = next_vobu;
+        }
+    }
+  } while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
+}
+
+#if 0
+static int
+_read(DVDSrcPrivate *priv, int angle, int new_seek, GstBuffer *buf)
+{
+    unsigned char *data;
+
+    data = GST_BUFFER_DATA(buf);
+
+    /**
+     * Playback by cell in this pgc, starting at the cell for our chapter.
+     */
+    if (new_seek) {
+      priv->next_cell = priv->start_cell;
+      priv->cur_cell = priv->start_cell;
+    }
+    if (priv->next_cell < priv->cur_pgc->nr_of_cells) {
+
+        priv->cur_cell = priv->next_cell;
+
+        /* Check if we're entering an angle block. */
+        if( priv->cur_pgc->cell_playback[ priv->cur_cell ].block_type
+                                        == BLOCK_TYPE_ANGLE_BLOCK ) {
+            int i;
+
+            priv->cur_cell += angle;
+            for( i = 0;; ++i ) {
+                if( priv->cur_pgc->cell_playback[ priv->cur_cell + i ].block_mode
+                                          == BLOCK_MODE_LAST_CELL ) {
+                    priv->next_cell = priv->cur_cell + i + 1;
+                    break;
+                }
+            }
+        } else {
+            priv->next_cell = priv->cur_cell + 1;
+        }
+
+
+        /**
+         * We loop until we're out of this cell.
+         */
+        if (priv->new_cell) {
+          priv->cur_pack = priv->cur_pgc->cell_playback[ priv->cur_cell ].first_sector;
+          priv->new_cell = FALSE;
+        }
+
+        if (priv->cur_pack < priv->cur_pgc->cell_playback[ priv->cur_cell ].last_sector; ) {
+
+            dsi_t dsi_pack;
+            unsigned int next_vobu, next_ilvu_start, cur_output_size;
+            int len;
+
+
+            /**
+             * Read NAV packet.
+             */
+            len = DVDReadBlocks( priv->title, priv->cur_pack, 1, data );
+            if( len == 0 ) {
+                fprintf( stderr, "Read failed for block %d\n", priv->cur_pack );
+                _close(priv);
+                return -1;
+            }
+            assert( is_nav_pack( data ) );
+
+
+            /**
+             * Parse the contained dsi packet.
+             */
+            navRead_DSI( &dsi_pack, &(data[ DSI_START_BYTE ]), sizeof(dsi_t) );
+            assert( priv->cur_pack == dsi_pack.dsi_gi.nv_pck_lbn );
+
+
+            /**
+             * Determine where we go next.  These values are the ones we mostly
+             * care about.
+             */
+            next_ilvu_start = priv->cur_pack
+                              + dsi_pack.sml_agli.data[ angle ].address;
+            cur_output_size = dsi_pack.dsi_gi.vobu_ea;
+
+
+            /**
+             * 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( dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL ) {
+                next_vobu = priv->cur_pack
+                            + ( dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
+            } else {
+                next_vobu = priv->cur_pack + cur_output_size + 1;
+            }
+
+            assert( cur_output_size < 1024 );
+            priv->cur_pack++;
+
+            /**
+             * Read in and output cursize packs.
+             */
+            len = DVDReadBlocks( priv->title, priv->cur_pack,
+                                         cur_output_size, data );
+            if( len != cur_output_size ) {
+                fprintf( stderr, "Read failed for %d blocks at %d\n",
+                         cur_output_size, priv->cur_pack );
+                _close(priv);
+                return -1;
+            }
+
+            GST_BUFFER_SIZE(buf) = cur_output_size * DVD_VIDEO_LB_LEN;
+            priv->cur_pack = next_vobu;
+        }
+    } else {
+        return -1;
+    }
+
+    return 0;
+}
+
 static GstBuffer *
 dvdsrc_get (GstPad *pad) 
 {
   DVDSrc *dvdsrc;
+  DVDSrcPrivate *priv;
   GstBuffer *buf;
-  glong readbytes;
 
   g_return_val_if_fail (pad != NULL, NULL);
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
   dvdsrc = DVDSRC (gst_pad_get_parent (pad));
+  priv = dvdsrc->priv;
   g_return_val_if_fail (GST_FLAG_IS_SET (dvdsrc, DVDSRC_OPEN),NULL);
 
   /* create the buffer */
@@ -272,138 +695,43 @@
   g_return_val_if_fail (buf, NULL);
 
   /* allocate the space for the buffer data */
-  GST_BUFFER_DATA (buf) = g_malloc (dvdsrc->bytes_per_read);
+  GST_BUFFER_DATA (buf) = g_malloc (1024 * DVD_VIDEO_LB_LEN);
   g_return_val_if_fail (GST_BUFFER_DATA (buf) != NULL, NULL);
 
+  if (priv->new_seek) {
+    _seek(priv, priv->titleid, priv->chapid, priv->angle);
+    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLUSH);
+  }
+
   /* read it in from the file */
-  readbytes = read (dvdsrc->fd, GST_BUFFER_DATA (buf), dvdsrc->bytes_per_read);
-  if (readbytes == 0) {
+  if (_read (priv, priv->angle, priv->new_seek, buf)) {
     gst_element_signal_eos (GST_ELEMENT (dvdsrc));
     return NULL;
   }
-
-  // we can only decrypt full sectors, but if at end, signal EOS anyway
-  if (readbytes < dvdsrc->bytes_per_read)
-    GST_BUFFER_FLAG_SET(buf,GST_BUFFER_EOS);
-  else {
-    if (*(GST_BUFFER_DATA (buf)+20) & 0x30) {
-      css_descramble (GST_BUFFER_DATA (buf), dvdsrc->title_key);
-    }
-  }
 
-  if (dvdsrc->new_seek) {
-    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLUSH);
-    dvdsrc->new_seek = FALSE;
+  if (priv->new_seek) {
+    priv->new_seek = FALSE;
   }
 
-  GST_BUFFER_OFFSET (buf) = dvdsrc->curoffset;
-  GST_BUFFER_SIZE (buf) = readbytes;
-  dvdsrc->curoffset += readbytes;
-
   return buf;
 }
+#endif
 
 /* open the file, necessary to go to RUNNING state */
 static gboolean 
 dvdsrc_open_file (DVDSrc *src) 
 {
-  struct stat fileinfo, devinfo;
-
+  g_return_val_if_fail (src != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_DVDSRC(src), FALSE);
   g_return_val_if_fail (!GST_FLAG_IS_SET (src, DVDSRC_OPEN), FALSE);
-
-  // if we don't have the title-key yet, we have to go 'find' it
-  if (src->title_key == NULL) {
-    // if we have the device path, our life is easier, else find it
-    if (src->device == NULL) {
-      DIR *devdir;
-      struct dirent *dirent;
-      gchar *path;
-
-      // stat the file to get the device major:minor
-      if (stat (src->filename, &fileinfo) < 0) {
-	g_print ("%s", src->filename);
-	perror (" ");
-	return FALSE;
-      }
-
-      // open up /dev to find the right device
-      devdir = opendir ("/dev");
-      // look through all the devices for a match
-      while ((dirent = readdir (devdir))) {
-        path = g_strconcat ("/dev/", dirent->d_name, NULL);
-        stat (path, &devinfo);
-        if ((devinfo.st_rdev == fileinfo.st_dev) && S_ISBLK(devinfo.st_mode)) {
-          src->device = path;
-          break;
-        } else
-          g_free (path);
-      }
-      closedir (devdir);
-    }
-
-    /* reset the device */
-    if (src->device != NULL) {
-       int dvdfd;
-       dvd_authinfo ai;
-       int i;
-       guchar disk_key[2048];
-       gint lba;
-
-       // open the device
-       dvdfd = open (src->device, O_RDONLY | O_NONBLOCK);
-
-       // reset the drive's auth codes
-       for (i=0; i<4; i++) {
-         memset (&ai, 0, sizeof (ai));
-         ai.type = DVD_INVALIDATE_AGID;
-         ai.lsa.agid = i;
-         ioctl (dvdfd, DVD_AUTH, &ai);
-       }
-
-       // get the LBA (what's that?, logical block address?  looks so...)
-       lba = path_to_lba (src->filename);
-       // special case if we aren't root...
-       if (lba == -1) {
-         g_print ("lba failed\n");
-       }
-       else {
-         g_print ("lba is %d\n",lba);
-       }
-
-       // allocate the title_key
-       src->title_key = g_malloc (5);
-
-       // get the disk key
-       authenticate (dvdfd, lba, FALSE, disk_key, src->title_key);
-       // get the title key
-       authenticate (dvdfd, lba, TRUE, disk_key, src->title_key);
 
-       css_decrypttitlekey (src->title_key, disk_key);
-
-       // close the device
-       close (dvdfd);
-    } else {
-      fprintf (stderr,"sorry, couldn't find DVD device for '%s'\n", src->filename);
-      exit (2);
-    }
-  }
-
-  stat (src->filename, &fileinfo);
-
-  src->size = fileinfo.st_size;
-  g_print("size %ld\n", src->size);
-
-  /* open the file */
-  src->fd = open (src->filename,O_RDONLY);
-  if (src->fd < 0) {
-    perror ("open()");
-    gst_element_error (GST_ELEMENT (src), "opening file");
+  if (_open(src->priv, src->priv->location))
     return FALSE;
-  }
-
-  // seek to the correct position
-  super_seek (src->fd, DVDSRC_BASEOFFSET*2048);
-  src->curoffset = 0;
+  if (_seek(src->priv,
+      src->priv->title,
+      src->priv->chapter,
+      src->priv->angle))
+    return FALSE;
 
   GST_FLAG_SET (src, DVDSRC_OPEN);
   
@@ -415,14 +743,8 @@
 dvdsrc_close_file (DVDSrc *src) 
 {
   g_return_if_fail (GST_FLAG_IS_SET (src, DVDSRC_OPEN));
-
-  /* close the file */
-  close (src->fd);
 
-  /* zero out a lot of our state */
-  src->fd = 0;
-  src->curoffset = 0;
-  src->seq = 0;
+  _close(src->priv);
 
   GST_FLAG_UNSET (src, DVDSRC_OPEN);
 }
@@ -461,7 +783,7 @@
   /* create an elementfactory for the dvdsrc element */
   factory = gst_elementfactory_new ("dvdsrc", GST_TYPE_DVDSRC,
                                     &dvdsrc_details);
-  g_return_val_if_fail (factory != NULL, NULL);
+  g_return_val_if_fail (factory != NULL, FALSE);
   
   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
   
Index: plugins/dvdsrc/dvdsrc.h
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/plugins/dvdsrc/dvdsrc.h,v
retrieving revision 1.5
diff -u -r1.5 dvdsrc.h
--- plugins/dvdsrc/dvdsrc.h	2001/06/25 01:20:09	1.5
+++ plugins/dvdsrc/dvdsrc.h	2001/10/05 05:42:05
@@ -31,8 +31,6 @@
 #endif /* __cplusplus */
 
 
-#define DVDSRC_BASEOFFSET 0x0
-
 GstElementDetails dvdsrc_details;
 
 
@@ -55,31 +53,12 @@
 } DVDSrcFlags;
 
 typedef struct _DVDSrc DVDSrc;
+typedef struct _DVDSrcPrivate DVDSrcPrivate;
 typedef struct _DVDSrcClass DVDSrcClass;
 
 struct _DVDSrc {
   GstElement element;
-  /* pads */
-  GstPad *srcpad;
-
-  /* filename */
-  gchar *filename;
-  /* device */
-  gchar *device;
-  /* title key for decrypt */
-  guchar *title_key;
-  /* disk key in case we have to get it ourselves (simplest?) */
-  guchar *disk_key;
-  /* fd */
-  gint fd;
-
-  gulong curoffset;			/* current offset in file */
-  gulong bytes_per_read;		/* bytes per read */
-  gulong size;
-
-  gulong seq;				/* buffer sequence number */
-
-  gboolean new_seek;
+  DVDSrcPrivate *priv;
 };
 
 struct _DVDSrcClass {
Index: plugins/mpeg2/parse/mpeg2parse.c
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/plugins/mpeg2/parse/mpeg2parse.c,v
retrieving revision 1.35
diff -u -r1.35 mpeg2parse.c
--- plugins/mpeg2/parse/mpeg2parse.c	2001/09/18 00:03:19	1.35
+++ plugins/mpeg2/parse/mpeg2parse.c	2001/10/05 05:42:05
@@ -88,7 +88,7 @@
   GST_PAD_SOMETIMES,
   GST_CAPS_NEW (
     "mpeg2parse_private1",
-    "audio/ac3",
+    "audio/a52",
     "framed", GST_PROPS_BOOLEAN (FALSE)
   )
 );
Index: test/.cvsignore
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/test/.cvsignore,v
retrieving revision 1.15
diff -u -r1.15 .cvsignore
--- test/.cvsignore	2001/09/10 16:32:23	1.15
+++ test/.cvsignore	2001/10/05 05:42:05
@@ -58,3 +58,4 @@
 mp2tomp1v2
 main
 testspeed
+dvdplay
Index: test/Makefile.am
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/test/Makefile.am,v
retrieving revision 1.38
diff -u -r1.38 Makefile.am
--- test/Makefile.am	2001/09/14 16:25:24	1.38
+++ test/Makefile.am	2001/10/05 05:42:05
@@ -4,7 +4,7 @@
 GNOME_PROGS = spectrum wave mp1parse videotest aviparse \
 		videotest2 video2mp1 dvshow dv2mp1 \
 		mpeg2parse2 mpeg2parse3 \
-		mp2tomp1v2 main sinesliders testspeed
+		mp2tomp1v2 main sinesliders testspeed dvdplay
 else
 GNOME_PROGS =
 endif
Index: test/mpeg2parse3.c
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/test/mpeg2parse3.c,v
retrieving revision 1.2
diff -u -r1.2 mpeg2parse3.c
--- test/mpeg2parse3.c	2001/05/25 21:00:07	1.2
+++ test/mpeg2parse3.c	2001/10/05 05:42:05
@@ -108,7 +108,7 @@
   a_queue = gst_elementfactory_make("queue","a_queue");
   g_return_val_if_fail(a_queue != NULL, -1);
   
-  a_decode = gst_elementfactory_make("ac3dec","decode_audio");
+  a_decode = gst_elementfactory_make("a52dec","decode_audio");
   g_return_val_if_fail(a_decode != NULL, -1);
 
   osssink = gst_elementfactory_make("osssink","osssink");
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dvdplay.c
Type: text/x-csrc
Size: 4742 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20011004/74f93d62/attachment.c>


More information about the gstreamer-devel mailing list