[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