ext/dvdread/dvdreadsrc.c: Fix. Don't do one big huge loop around the whole DVD, that will cache all data and thus eat...

Original commit message from CVS:
* ext/dvdread/dvdreadsrc.c: (dvdreadsrc_class_init),
(dvdreadsrc_init), (dvdreadsrc_dispose), (dvdreadsrc_set_property),
(dvdreadsrc_get_property), (_open), (_seek), (_read),
(dvdreadsrc_get), (dvdreadsrc_open_file),
(dvdreadsrc_change_state):
Fix. Don't do one big huge loop around the whole DVD, that will
cache all data and thus eat sizeof(dvd) (several GB) before we
see something.
* gst-libs/gst/riff/riff-read.c: (gst_riff_read_seek):
Actually NULL'ify event after using it.
* gst/matroska/ebml-read.c: (gst_ebml_read_use_event),
(gst_ebml_read_handle_event), (gst_ebml_read_element_id),
(gst_ebml_read_element_length), (gst_ebml_read_element_data),
(gst_ebml_read_seek), (gst_ebml_read_skip):
Handle events.
* gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_base_init),
(gst_dvd_demux_init), (gst_dvd_demux_get_audio_stream),
(gst_dvd_demux_get_subpicture_stream), (gst_dvd_demux_plugin_init):
Fix timing (this will probably break if I seek using menus, but
I didn't get there yet). VOBs and normal DVDs should now work.
Add a mpeg2-only pad with high rank so this get autoplugged for
MPEG-2 movies.
* gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_base_init),
(gst_mpeg_demux_class_init), (gst_mpeg_demux_init),
(gst_mpeg_demux_new_output_pad), (gst_mpeg_demux_get_video_stream),
(gst_mpeg_demux_get_audio_stream),
(gst_mpeg_demux_get_private_stream), (gst_mpeg_demux_parse_packet),
(gst_mpeg_demux_parse_pes), (gst_mpeg_demux_plugin_init):
Use this as second rank for MPEG-1 and MPEG-2. Still use this for
MPEG-1 but use dvddemux for MPEG-2.
* gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_class_init),
(gst_mpeg_parse_init), (gst_mpeg_parse_new_pad),
(gst_mpeg_parse_parse_packhead):
Timing. Only add pad template if it exists. Add sink template from
class and not from ourselves. This means we will always use the
correct sink template even if it is not the one defined in this
file.
This commit is contained in:
Ronald S. Bultje 2004-10-01 08:42:56 +00:00
parent 1fc1f89e91
commit 97148ae7cd
6 changed files with 254 additions and 244 deletions

View file

@ -1,3 +1,43 @@
2004-10-01 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* ext/dvdread/dvdreadsrc.c: (dvdreadsrc_class_init),
(dvdreadsrc_init), (dvdreadsrc_dispose), (dvdreadsrc_set_property),
(dvdreadsrc_get_property), (_open), (_seek), (_read),
(dvdreadsrc_get), (dvdreadsrc_open_file),
(dvdreadsrc_change_state):
Fix. Don't do one big huge loop around the whole DVD, that will
cache all data and thus eat sizeof(dvd) (several GB) before we
see something.
* gst-libs/gst/riff/riff-read.c: (gst_riff_read_seek):
Actually NULL'ify event after using it.
* gst/matroska/ebml-read.c: (gst_ebml_read_use_event),
(gst_ebml_read_handle_event), (gst_ebml_read_element_id),
(gst_ebml_read_element_length), (gst_ebml_read_element_data),
(gst_ebml_read_seek), (gst_ebml_read_skip):
Handle events.
* gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_base_init),
(gst_dvd_demux_init), (gst_dvd_demux_get_audio_stream),
(gst_dvd_demux_get_subpicture_stream), (gst_dvd_demux_plugin_init):
Fix timing (this will probably break if I seek using menus, but
I didn't get there yet). VOBs and normal DVDs should now work.
Add a mpeg2-only pad with high rank so this get autoplugged for
MPEG-2 movies.
* gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_base_init),
(gst_mpeg_demux_class_init), (gst_mpeg_demux_init),
(gst_mpeg_demux_new_output_pad), (gst_mpeg_demux_get_video_stream),
(gst_mpeg_demux_get_audio_stream),
(gst_mpeg_demux_get_private_stream), (gst_mpeg_demux_parse_packet),
(gst_mpeg_demux_parse_pes), (gst_mpeg_demux_plugin_init):
Use this as second rank for MPEG-1 and MPEG-2. Still use this for
MPEG-1 but use dvddemux for MPEG-2.
* gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_class_init),
(gst_mpeg_parse_init), (gst_mpeg_parse_new_pad),
(gst_mpeg_parse_parse_packhead):
Timing. Only add pad template if it exists. Add sink template from
class and not from ourselves. This means we will always use the
correct sink template even if it is not the one defined in this
file.
2004-09-29 Wim Taymans <wim@fluendo.com>
* gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_packet),

View file

@ -64,7 +64,6 @@
struct _DVDReadSrcPrivate
{
GstElement element;
/* pads */
GstPad *srcpad;
@ -73,6 +72,8 @@ struct _DVDReadSrcPrivate
gboolean new_seek;
gboolean new_cell;
int title, chapter, angle;
int pgc_id, start_cell, cur_cell, cur_pack;
int ttn, pgn, next_cell;
@ -85,6 +86,8 @@ struct _DVDReadSrcPrivate
pgc_t *cur_pgc;
};
GST_DEBUG_CATEGORY_STATIC (gstdvdreadsrc_debug);
#define GST_CAT_DEFAULT (gstdvdreadsrc_debug)
GstElementDetails dvdreadsrc_details = {
"DVD Source",
@ -113,14 +116,14 @@ enum
static void dvdreadsrc_base_init (gpointer g_class);
static void dvdreadsrc_class_init (DVDReadSrcClass * klass);
static void dvdreadsrc_init (DVDReadSrc * dvdreadsrc);
static void dvdreadsrc_dispose (GObject * object);
static void dvdreadsrc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void dvdreadsrc_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
/*static GstData * dvdreadsrc_get (GstPad *pad); */
static void dvdreadsrc_loop (GstElement * element);
static GstData *dvdreadsrc_get (GstPad * pad);
/*static GstBuffer * dvdreadsrc_get_region (GstPad *pad,gulong offset,gulong size); */
@ -191,7 +194,12 @@ dvdreadsrc_class_init (DVDReadSrcClass * klass)
gobject_class->set_property = GST_DEBUG_FUNCPTR (dvdreadsrc_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (dvdreadsrc_get_property);
gobject_class->dispose = dvdreadsrc_dispose;
gstelement_class->change_state = dvdreadsrc_change_state;
GST_DEBUG_CATEGORY_INIT (gstdvdreadsrc_debug, "dvdreadsrc", 0,
"DVD reader element based on dvdreadsrc");
}
static void
@ -199,27 +207,28 @@ dvdreadsrc_init (DVDReadSrc * dvdreadsrc)
{
dvdreadsrc->priv = g_new (DVDReadSrcPrivate, 1);
dvdreadsrc->priv->srcpad = gst_pad_new ("src", GST_PAD_SRC);
gst_pad_set_get_function (dvdreadsrc->priv->srcpad, dvdreadsrc_get);
gst_element_add_pad (GST_ELEMENT (dvdreadsrc), dvdreadsrc->priv->srcpad);
gst_element_set_loop_function (GST_ELEMENT (dvdreadsrc),
GST_DEBUG_FUNCPTR (dvdreadsrc_loop));
dvdreadsrc->priv->location = g_strdup ("/dev/dvd");
dvdreadsrc->priv->new_seek = FALSE;
dvdreadsrc->priv->title = 1;
dvdreadsrc->priv->chapter = 1;
dvdreadsrc->priv->angle = 1;
dvdreadsrc->priv->new_seek = TRUE;
dvdreadsrc->priv->new_cell = TRUE;
dvdreadsrc->priv->title = 0;
dvdreadsrc->priv->chapter = 0;
dvdreadsrc->priv->angle = 0;
}
/* FIXME: this code is not being used */
#ifdef PLEASEFIXTHISCODE
static void
dvdreadsrc_destroy (DVDReadSrc * dvdreadsrc)
dvdreadsrc_dispose (GObject * object)
{
/* FIXME */
g_print ("FIXME\n");
g_free (dvdreadsrc->priv);
DVDReadSrc *dvdreadsrc = DVDREADSRC (object);
if (dvdreadsrc->priv) {
g_free (dvdreadsrc->priv->location);
g_free (dvdreadsrc->priv);
dvdreadsrc->priv = NULL;
}
}
#endif
static void
dvdreadsrc_set_property (GObject * object, guint prop_id, const GValue * value,
@ -249,15 +258,15 @@ dvdreadsrc_set_property (GObject * object, guint prop_id, const GValue * value,
priv->location = g_strdup (g_value_get_string (value));
break;
case ARG_TITLE:
priv->title = g_value_get_int (value) - 1;
priv->title = g_value_get_int (value);
priv->new_seek = TRUE;
break;
case ARG_CHAPTER:
priv->chapter = g_value_get_int (value) - 1;
priv->chapter = g_value_get_int (value);
priv->new_seek = TRUE;
break;
case ARG_ANGLE:
priv->angle = g_value_get_int (value) - 1;
priv->angle = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -284,13 +293,13 @@ dvdreadsrc_get_property (GObject * object, guint prop_id, GValue * value,
g_value_set_string (value, priv->location);
break;
case ARG_TITLE:
g_value_set_int (value, priv->title + 1);
g_value_set_int (value, priv->title);
break;
case ARG_CHAPTER:
g_value_set_int (value, priv->chapter + 1);
g_value_set_int (value, priv->chapter);
break;
case ARG_ANGLE:
g_value_set_int (value, priv->angle + 1);
g_value_set_int (value, priv->angle);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -320,7 +329,7 @@ _open (DVDReadSrcPrivate * priv, const gchar * location)
*/
priv->dvd = DVDOpen (location);
if (!priv->dvd) {
fprintf (stderr, "Couldn't open DVD: %s\n", location);
GST_ERROR ("Couldn't open DVD: %s", location);
return -1;
}
@ -331,7 +340,7 @@ _open (DVDReadSrcPrivate * priv, const gchar * location)
*/
priv->vmg_file = ifoOpen (priv->dvd, 0);
if (!priv->vmg_file) {
fprintf (stderr, "Can't open VMG info.\n");
GST_ERROR ("Can't open VMG info");
DVDClose (priv->dvd);
return -1;
}
@ -356,10 +365,10 @@ _seek (DVDReadSrcPrivate * 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);
GST_LOG ("There are %d titles on this DVD", priv->tt_srpt->nr_of_srpts);
if (title < 0 || title >= priv->tt_srpt->nr_of_srpts) {
fprintf (stderr, "Invalid title %d.\n", title + 1);
GST_ERROR ("Invalid title %d (only %d available)",
title, priv->tt_srpt->nr_of_srpts);
ifoClose (priv->vmg_file);
DVDClose (priv->dvd);
return -1;
@ -369,11 +378,12 @@ _seek (DVDReadSrcPrivate * priv, int title, int chapter, int angle)
/**
* Make sure the chapter number is valid for this title.
*/
fprintf (stderr, "There are %d chapters in this title.\n",
GST_LOG ("There are %d chapters in this title",
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);
GST_ERROR ("Invalid chapter %d (only %d available)",
chapter, priv->tt_srpt->title[title].nr_of_ptts);
ifoClose (priv->vmg_file);
DVDClose (priv->dvd);
return -1;
@ -383,10 +393,11 @@ _seek (DVDReadSrcPrivate * priv, int title, int chapter, int angle)
/**
* Make sure the angle number is valid for this title.
*/
fprintf (stderr, "There are %d angles in this title.\n",
GST_LOG ("There are %d angles available in this title",
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);
GST_ERROR ("Invalid angle %d (only %d available)",
angle, priv->tt_srpt->title[title].nr_of_angles);
ifoClose (priv->vmg_file);
DVDClose (priv->dvd);
return -1;
@ -399,7 +410,7 @@ _seek (DVDReadSrcPrivate * priv, int title, int chapter, int angle)
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",
GST_ERROR ("Can't open the info file of title %d",
priv->tt_srpt->title[title].title_set_nr);
ifoClose (priv->vmg_file);
DVDClose (priv->dvd);
@ -418,7 +429,6 @@ _seek (DVDReadSrcPrivate * priv, int title, int chapter, int angle)
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.
*/
@ -426,7 +436,7 @@ _seek (DVDReadSrcPrivate * priv, int title, int chapter, int angle)
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",
GST_ERROR ("Can't open title VOBS (VTS_%02d_1.VOB)",
priv->tt_srpt->title[title].title_set_nr);
ifoClose (priv->vts_file);
ifoClose (priv->vmg_file);
@ -437,141 +447,11 @@ _seek (DVDReadSrcPrivate * priv, int title, int chapter, int angle)
return 0;
}
static void
dvdreadsrc_loop (GstElement * element)
{
DVDReadSrc *dvdreadsrc;
DVDReadSrcPrivate *priv;
/*
* Read function.
* -1: error, -2: eos, -3: try again, 0: ok.
*/
g_return_if_fail (element != NULL);
g_return_if_fail (GST_IS_DVDREADSRC (element));
dvdreadsrc = DVDREADSRC (element);
priv = dvdreadsrc->priv;
g_return_if_fail (GST_FLAG_IS_SET (dvdreadsrc, DVDREADSRC_OPEN));
/**
* 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);
/**
* 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_set_eos (GST_ELEMENT (dvdreadsrc));
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_set_eos (GST_ELEMENT (dvdreadsrc));
return;
}
GST_BUFFER_SIZE (buf) = cur_output_size * DVD_VIDEO_LB_LEN;
gst_pad_push (priv->srcpad, GST_DATA (buf));
priv->cur_pack = next_vobu;
}
}
}
#if 0
static int
_read (DVDReadSrcPrivate * priv, int angle, int new_seek, GstBuffer * buf)
{
@ -586,9 +466,10 @@ _read (DVDReadSrcPrivate * priv, int angle, int new_seek, GstBuffer * buf)
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;
if (priv->next_cell < priv->cur_pgc->nr_of_cells) {
if (priv->new_cell)
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
@ -618,20 +499,17 @@ _read (DVDReadSrcPrivate * priv, int angle, int new_seek, GstBuffer * buf)
}
if (priv->cur_pack <
priv->cur_pgc->cell_playback[priv->cur_cell].last_sector;) {
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);
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_ERROR ("Read failed for block %d", priv->cur_pack);
return -1;
}
assert (is_nav_pack (data));
@ -640,7 +518,7 @@ _read (DVDReadSrcPrivate * priv, int angle, int new_seek, GstBuffer * buf)
/**
* Parse the contained dsi packet.
*/
navRead_DSI (&dsi_pack, &(data[DSI_START_BYTE]), sizeof (dsi_t));
navRead_DSI (&dsi_pack, &(data[DSI_START_BYTE]));
assert (priv->cur_pack == dsi_pack.dsi_gi.nv_pck_lbn);
@ -674,27 +552,34 @@ _read (DVDReadSrcPrivate * priv, int angle, int new_seek, GstBuffer * buf)
/**
* Read in and output cursize packs.
*/
len = DVDReadBlocks (priv->title, priv->cur_pack, cur_output_size, data);
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",
GST_ERROR ("Read failed for %d blocks at %d",
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;
return 0;
} else {
priv->new_cell = TRUE;
}
} else {
return -1;
return -2;
}
return 0;
/* again */
return -3;
}
static GstData *
dvdreadsrc_get (GstPad * pad)
{
gint res;
DVDReadSrc *dvdreadsrc;
DVDReadSrcPrivate *priv;
GstBuffer *buf;
@ -708,30 +593,33 @@ dvdreadsrc_get (GstPad * pad)
/* create the buffer */
/* FIXME: should eventually use a bufferpool for this */
buf = gst_buffer_new ();
g_return_val_if_fail (buf, NULL);
/* allocate the space for the buffer data */
GST_BUFFER_DATA (buf) = g_malloc (1024 * DVD_VIDEO_LB_LEN);
g_return_val_if_fail (GST_BUFFER_DATA (buf) != NULL, NULL);
buf = gst_buffer_new_and_alloc (1024 * DVD_VIDEO_LB_LEN);
if (priv->new_seek) {
_seek (priv, priv->titleid, priv->chapid, priv->angle);
_seek (priv, priv->title, priv->chapter, priv->angle);
}
/* read it in from the file */
if (_read (priv, priv->angle, priv->new_seek, buf)) {
gst_element_signal_eos (GST_ELEMENT (dvdreadsrc));
return NULL;
while ((res = _read (priv, priv->angle, priv->new_seek, buf)) == -3);
switch (res) {
case -1:
GST_ELEMENT_ERROR (dvdreadsrc, RESOURCE, READ, (NULL), (NULL));
gst_buffer_unref (buf);
return NULL;
case -2:
gst_element_set_eos (GST_ELEMENT (dvdreadsrc));
gst_buffer_unref (buf);
return GST_DATA (gst_event_new (GST_EVENT_EOS));
case 0:
break;
default:
g_assert_not_reached ();
}
if (priv->new_seek) {
priv->new_seek = FALSE;
}
priv->new_seek = FALSE;
return buf;
return GST_DATA (buf);
}
#endif
/* open the file, necessary to go to RUNNING state */
static gboolean
@ -741,10 +629,14 @@ dvdreadsrc_open_file (DVDReadSrc * src)
g_return_val_if_fail (GST_IS_DVDREADSRC (src), FALSE);
g_return_val_if_fail (!GST_FLAG_IS_SET (src, DVDREADSRC_OPEN), FALSE);
if (_open (src->priv, src->priv->location))
if (_open (src->priv, src->priv->location)) {
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), (NULL));
return FALSE;
if (_seek (src->priv, src->priv->title, src->priv->chapter, src->priv->angle))
}
if (_seek (src->priv, src->priv->title, src->priv->chapter, src->priv->angle)) {
GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (NULL), (NULL));
return FALSE;
}
GST_FLAG_SET (src, DVDREADSRC_OPEN);
@ -765,20 +657,29 @@ dvdreadsrc_close_file (DVDReadSrc * src)
static GstElementStateReturn
dvdreadsrc_change_state (GstElement * element)
{
DVDReadSrc *dvdreadsrc = DVDREADSRC (element);
g_return_val_if_fail (GST_IS_DVDREADSRC (element), GST_STATE_FAILURE);
GST_DEBUG ("gstdvdreadsrc: state pending %d", GST_STATE_PENDING (element));
/* if going down into NULL state, close the file if it's open */
if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
if (GST_FLAG_IS_SET (element, DVDREADSRC_OPEN))
dvdreadsrc_close_file (DVDREADSRC (element));
/* otherwise (READY or higher) we need to open the file */
} else {
if (!GST_FLAG_IS_SET (element, DVDREADSRC_OPEN)) {
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
if (!dvdreadsrc_open_file (DVDREADSRC (element)))
return GST_STATE_FAILURE;
}
break;
case GST_STATE_PAUSED_TO_READY:
dvdreadsrc->priv->new_cell = TRUE;
dvdreadsrc->priv->new_seek = TRUE;
dvdreadsrc->priv->chapter = 0;
dvdreadsrc->priv->title = 0;
break;
case GST_STATE_READY_TO_NULL:
dvdreadsrc_close_file (DVDREADSRC (element));
break;
default:
break;
}
/* if we haven't failed already, give the parent class a chance to ;-) */

View file

@ -306,6 +306,7 @@ gst_riff_read_seek (GstRiffRead * riff, guint64 offset)
GST_WARNING ("Unexpected event before seek");
if (!gst_riff_read_use_event (riff, event))
return NULL;
event = NULL;
}
if (remaining)

View file

@ -60,6 +60,13 @@ enum
/* Define the capabilities separately, to be able to reuse them. */
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/mpeg, "
"mpegversion = (int) 2, " "systemstream = (boolean) TRUE")
);
#define VIDEO_CAPS \
GST_STATIC_CAPS ("video/mpeg, " \
"mpegversion = (int) { 1, 2 }, " \
@ -196,6 +203,10 @@ gst_dvd_demux_base_init (GstDVDDemuxClass * klass)
mpeg_parse_class->send_data = gst_dvd_demux_send_data;
/* sink pad */
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_template));
demux_class->audio_template = gst_static_pad_template_get (&audio_template);
klass->cur_video_template = gst_static_pad_template_get (&cur_video_template);
@ -247,7 +258,6 @@ static void
gst_dvd_demux_init (GstDVDDemux * dvd_demux)
{
GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (dvd_demux);
GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (dvd_demux);
gint i;
GST_FLAG_SET (dvd_demux, GST_ELEMENT_EVENT_AWARE);
@ -256,12 +266,15 @@ gst_dvd_demux_init (GstDVDDemux * dvd_demux)
dvd_demux->cur_video =
DEMUX_CLASS (dvd_demux)->new_output_pad (mpeg_demux, "current_video",
CLASS (dvd_demux)->cur_video_template);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), dvd_demux->cur_video);
dvd_demux->cur_audio =
DEMUX_CLASS (dvd_demux)->new_output_pad (mpeg_demux, "current_audio",
CLASS (dvd_demux)->cur_audio_template);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), dvd_demux->cur_audio);
dvd_demux->cur_subpicture =
DEMUX_CLASS (dvd_demux)->new_output_pad (mpeg_demux, "current_subpicture",
CLASS (dvd_demux)->cur_subpicture_template);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), dvd_demux->cur_subpicture);
dvd_demux->mpeg_version = 0;
dvd_demux->cur_video_nr = 0;
@ -271,10 +284,24 @@ gst_dvd_demux_init (GstDVDDemux * dvd_demux)
/* Start the timestamp sequence in 0. */
dvd_demux->last_end_ptm = 0;
/* (Ronald) so, this was disabled. I'm enabling (default) it again.
* Timestamp adjustment is fairly evil, we would ideally use discont
* events instead. However, our current clocking has a pretty serious
* race condition: imagine that $pipeline is at time 30sec and $audio
* receives a discont to 0sec. Video processes its last buffer and
* calls _wait() on $timestamp, which is 30s - so we wait (hang) 30sec.
* This is unacceptable, obviously, and timestamp adjustment, no matter
* how evil, solves this.
* Before disabling this again, tripple check that al .vob files on our
* websites /media/ directory work fine, especially bullet.vob and
* barrage.vob.
*/
#if 0
/* Try to prevent the mpegparse infrastructure from doing timestamp
adjustment. */
mpeg_parse->do_adjust = FALSE;
mpeg_parse->adjust = 0;
#endif
dvd_demux->just_flushed = FALSE;
dvd_demux->discont_time = GST_CLOCK_TIME_NONE;
@ -484,9 +511,9 @@ gst_dvd_demux_get_audio_stream (GstMPEGDemux * mpeg_demux,
guint8 sample_info = 0;
GstMPEGStream *str;
GstDVDLPCMStream *lpcm_str = NULL;
gchar *name;
GstCaps *caps;
gint width, rate, channels;
gboolean add_pad = FALSE;
g_return_val_if_fail (stream_nr < GST_MPEG_DEMUX_NUM_AUDIO_STREAMS, NULL);
g_return_val_if_fail (type > GST_MPEG_DEMUX_AUDIO_UNKNOWN &&
@ -502,6 +529,8 @@ gst_dvd_demux_get_audio_stream (GstMPEGDemux * mpeg_demux,
str = mpeg_demux->audio_stream[stream_nr];
if (str == NULL) {
gchar *name;
if (type != GST_DVD_DEMUX_AUDIO_LPCM) {
str = g_new0 (GstMPEGStream, 1);
} else {
@ -515,6 +544,7 @@ gst_dvd_demux_get_audio_stream (GstMPEGDemux * mpeg_demux,
/* update caps */
str->type = GST_MPEG_DEMUX_AUDIO_UNKNOWN;
g_free (name);
add_pad = TRUE;
mpeg_demux->audio_stream[stream_nr] = str;
} else {
@ -587,6 +617,8 @@ gst_dvd_demux_get_audio_stream (GstMPEGDemux * mpeg_demux,
/* This is the current audio stream. Use the same caps. */
gst_pad_set_explicit_caps (dvd_demux->cur_audio, gst_caps_copy (caps));
}
if (add_pad)
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
str->type = type;
}
@ -603,6 +635,7 @@ gst_dvd_demux_get_subpicture_stream (GstMPEGDemux * mpeg_demux,
GstMPEGStream *str;
gchar *name;
GstCaps *caps;
gboolean add_pad = FALSE;
g_return_val_if_fail (stream_nr < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS, NULL);
g_return_val_if_fail (type > GST_DVD_DEMUX_SUBP_UNKNOWN &&
@ -618,6 +651,7 @@ gst_dvd_demux_get_subpicture_stream (GstMPEGDemux * mpeg_demux,
DEMUX_CLASS (dvd_demux)->init_stream (mpeg_demux, type, str, stream_nr,
name, CLASS (dvd_demux)->subpicture_template);
g_free (name);
add_pad = TRUE;
dvd_demux->subpicture_stream[stream_nr] = str;
} else {
@ -637,6 +671,8 @@ gst_dvd_demux_get_subpicture_stream (GstMPEGDemux * mpeg_demux,
}
gst_caps_free (caps);
if (add_pad)
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
str->type = GST_DVD_DEMUX_SUBP_DVD;
}
@ -891,5 +927,5 @@ gboolean
gst_dvd_demux_plugin_init (GstPlugin * plugin)
{
return gst_element_register (plugin, "dvddemux",
GST_RANK_PRIMARY - 1, GST_TYPE_DVD_DEMUX);
GST_RANK_PRIMARY, GST_TYPE_DVD_DEMUX);
}

View file

@ -175,9 +175,6 @@ gst_mpeg_demux_base_init (GstMPEGDemuxClass * klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_template));
klass->video_template = gst_static_pad_template_get (&video_template);
klass->audio_template = gst_static_pad_template_get (&audio_template);
klass->private_template = gst_static_pad_template_get (&private_template);
@ -218,20 +215,16 @@ gst_mpeg_demux_class_init (GstMPEGDemuxClass * klass)
klass->get_private_stream = gst_mpeg_demux_get_private_stream;
klass->send_subbuffer = gst_mpeg_demux_send_subbuffer;
klass->process_private = gst_mpeg_demux_process_private;
/* we have our own sink pad template, but don't use it in subclasses */
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sink_template));
}
static void
gst_mpeg_demux_init (GstMPEGDemux * mpeg_demux)
{
gint i;
GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (mpeg_demux);
gst_element_remove_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->sinkpad);
mpeg_parse->sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get (&sink_template),
"sink");
gst_element_add_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->sinkpad);
gst_element_remove_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->srcpad);
/* i think everything is already zero'd, but oh well */
for (i = 0; i < GST_MPEG_DEMUX_NUM_VIDEO_STREAMS; i++) {
@ -340,8 +333,6 @@ gst_mpeg_demux_new_output_pad (GstMPEGDemux * mpeg_demux,
gst_pad_set_query_function (pad, gst_mpeg_parse_handle_src_query);
gst_pad_use_explicit_caps (pad);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), pad);
return pad;
}
@ -406,9 +397,11 @@ gst_mpeg_demux_get_video_stream (GstMPEGDemux * mpeg_demux,
GST_ELEMENT_ERROR (GST_ELEMENT (mpeg_demux),
CORE, NEGOTIATION, (NULL), ("failed to set caps"));
gst_caps_free (caps);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
return str;
}
gst_caps_free (caps);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
/* Store the current values. */
video_str->mpeg_version = mpeg_version;
@ -458,9 +451,11 @@ gst_mpeg_demux_get_audio_stream (GstMPEGDemux * mpeg_demux,
GST_ELEMENT_ERROR (GST_ELEMENT (mpeg_demux),
CORE, NEGOTIATION, (NULL), ("failed to set caps"));
gst_caps_free (caps);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
return str;
}
gst_caps_free (caps);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
}
return str;
@ -483,6 +478,7 @@ gst_mpeg_demux_get_private_stream (GstMPEGDemux * mpeg_demux,
CLASS (mpeg_demux)->init_stream (mpeg_demux, type, str, stream_nr, name,
CLASS (mpeg_demux)->private_template);
g_free (name);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
mpeg_demux->private_stream[stream_nr] = str;
}
@ -784,7 +780,7 @@ gst_mpeg_demux_parse_pes (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
guint16 datalen;
guint16 headerlen;
GstClockTime timestamp = GST_CLOCK_TIME_NONE;
GstClockTime timestamp;
GstMPEGStream *outstream = NULL;
guint8 *buf;
@ -828,7 +824,7 @@ gst_mpeg_demux_parse_pes (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
id, pts, MPEGTIME_TO_GSTTIME (pts));
pts += mpeg_parse->adjust;
timestamp = MPEGTIME_TO_GSTTIME (pts) + mpeg_demux->adjust;;
timestamp = MPEGTIME_TO_GSTTIME (pts) + mpeg_demux->adjust;
} else {
timestamp = GST_CLOCK_TIME_NONE;
}
@ -863,6 +859,8 @@ gst_mpeg_demux_parse_pes (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
/* constant corresponds to the 2 bytes of the packet length. */
headerlen = 2;
datalen = packet_length;
timestamp = GST_CLOCK_TIME_NONE;
}
GST_DEBUG_OBJECT (mpeg_demux, "headerlen is %d, datalen is %d",
@ -1096,5 +1094,5 @@ gboolean
gst_mpeg_demux_plugin_init (GstPlugin * plugin)
{
return gst_element_register (plugin, "mpegdemux",
GST_RANK_PRIMARY, GST_TYPE_MPEG_DEMUX);
GST_RANK_SECONDARY, GST_TYPE_MPEG_DEMUX);
}

View file

@ -94,6 +94,8 @@ static void gst_mpeg_parse_send_data (GstMPEGParse * mpeg_parse, GstData * data,
static void gst_mpeg_parse_send_discont (GstMPEGParse * mpeg_parse,
GstClockTime time);
static void gst_mpeg_parse_new_pad (GstElement * element, GstPad * pad);
static void gst_mpeg_parse_loop (GstElement * element);
static void gst_mpeg_parse_get_property (GObject * object, guint prop_id,
@ -172,6 +174,7 @@ gst_mpeg_parse_class_init (GstMPEGParseClass * klass)
gobject_class->get_property = gst_mpeg_parse_get_property;
gobject_class->set_property = gst_mpeg_parse_set_property;
gstelement_class->new_pad = gst_mpeg_parse_new_pad;
gstelement_class->change_state = gst_mpeg_parse_change_state;
gstelement_class->set_clock = gst_mpeg_parse_set_clock;
gstelement_class->get_index = gst_mpeg_parse_get_index;
@ -198,31 +201,34 @@ gst_mpeg_parse_class_init (GstMPEGParseClass * klass)
static void
gst_mpeg_parse_init (GstMPEGParse * mpeg_parse)
{
mpeg_parse->sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get (&sink_factory),
"sink");
GstElementClass *klass = GST_ELEMENT_GET_CLASS (mpeg_parse);
GstPadTemplate *templ;
templ = gst_element_class_get_pad_template (klass, "sink");
mpeg_parse->sinkpad = gst_pad_new_from_template (templ, "sink");
gst_element_add_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->sinkpad);
gst_pad_set_formats_function (mpeg_parse->sinkpad,
gst_mpeg_parse_get_src_formats);
gst_pad_set_convert_function (mpeg_parse->sinkpad,
gst_mpeg_parse_convert_src);
mpeg_parse->srcpad =
gst_pad_new_from_template (gst_static_pad_template_get (&src_factory),
"src");
gst_element_add_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->srcpad);
gst_pad_set_formats_function (mpeg_parse->srcpad,
gst_mpeg_parse_get_src_formats);
gst_pad_set_convert_function (mpeg_parse->srcpad, gst_mpeg_parse_convert_src);
gst_pad_set_event_mask_function (mpeg_parse->srcpad,
gst_mpeg_parse_get_src_event_masks);
gst_pad_set_event_function (mpeg_parse->srcpad,
gst_mpeg_parse_handle_src_event);
gst_pad_set_query_type_function (mpeg_parse->srcpad,
gst_mpeg_parse_get_src_query_types);
gst_pad_set_query_function (mpeg_parse->srcpad,
gst_mpeg_parse_handle_src_query);
gst_pad_use_explicit_caps (mpeg_parse->srcpad);
if ((templ = gst_element_class_get_pad_template (klass, "src"))) {
mpeg_parse->srcpad = gst_pad_new_from_template (templ, "src");
gst_element_add_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->srcpad);
gst_pad_set_formats_function (mpeg_parse->srcpad,
gst_mpeg_parse_get_src_formats);
gst_pad_set_convert_function (mpeg_parse->srcpad,
gst_mpeg_parse_convert_src);
gst_pad_set_event_mask_function (mpeg_parse->srcpad,
gst_mpeg_parse_get_src_event_masks);
gst_pad_set_event_function (mpeg_parse->srcpad,
gst_mpeg_parse_handle_src_event);
gst_pad_set_query_type_function (mpeg_parse->srcpad,
gst_mpeg_parse_get_src_query_types);
gst_pad_set_query_function (mpeg_parse->srcpad,
gst_mpeg_parse_handle_src_query);
gst_pad_use_explicit_caps (mpeg_parse->srcpad);
}
gst_element_set_loop_function (GST_ELEMENT (mpeg_parse), gst_mpeg_parse_loop);
@ -343,6 +349,31 @@ gst_mpeg_parse_send_discont (GstMPEGParse * mpeg_parse, GstClockTime time)
}
}
static void
gst_mpeg_parse_new_pad (GstElement * element, GstPad * pad)
{
GstMPEGParse *mpeg_parse;
if (GST_PAD_IS_SINK (pad))
return;
mpeg_parse = GST_MPEG_PARSE (element);
/* For each new added pad, send a discont so it knows about the current
* time. This is required because MPEG allows any sort of order of
* packets, including setting base time before defining streams or
* even adding streams halfway a stream. */
if (!mpeg_parse->scr_pending && !mpeg_parse->do_adjust) {
GstEvent *event = gst_event_new_discontinuous (FALSE,
GST_FORMAT_TIME,
(guint64) MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr +
mpeg_parse->adjust),
GST_FORMAT_UNDEFINED);
gst_pad_push (pad, GST_DATA (event));
}
}
static gboolean
gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
{
@ -419,11 +450,14 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
G_GUINT64_FORMAT " real:%" G_GINT64_FORMAT " adjust:%" G_GINT64_FORMAT,
mpeg_parse->next_scr, mpeg_parse->current_scr + mpeg_parse->adjust,
mpeg_parse->current_scr, mpeg_parse->adjust);
if (mpeg_parse->do_adjust) {
mpeg_parse->adjust +=
(gint64) mpeg_parse->next_scr - (gint64) mpeg_parse->current_scr;
GST_DEBUG ("new adjust: %" G_GINT64_FORMAT, mpeg_parse->adjust);
} else {
mpeg_parse->discont_pending = TRUE;
}
}