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> 2004-09-29 Wim Taymans <wim@fluendo.com>
* gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_packet), * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_packet),

View file

@ -64,7 +64,6 @@
struct _DVDReadSrcPrivate struct _DVDReadSrcPrivate
{ {
GstElement element;
/* pads */ /* pads */
GstPad *srcpad; GstPad *srcpad;
@ -73,6 +72,8 @@ struct _DVDReadSrcPrivate
gboolean new_seek; gboolean new_seek;
gboolean new_cell;
int title, chapter, angle; int title, chapter, angle;
int pgc_id, start_cell, cur_cell, cur_pack; int pgc_id, start_cell, cur_cell, cur_pack;
int ttn, pgn, next_cell; int ttn, pgn, next_cell;
@ -85,6 +86,8 @@ struct _DVDReadSrcPrivate
pgc_t *cur_pgc; pgc_t *cur_pgc;
}; };
GST_DEBUG_CATEGORY_STATIC (gstdvdreadsrc_debug);
#define GST_CAT_DEFAULT (gstdvdreadsrc_debug)
GstElementDetails dvdreadsrc_details = { GstElementDetails dvdreadsrc_details = {
"DVD Source", "DVD Source",
@ -113,14 +116,14 @@ enum
static void dvdreadsrc_base_init (gpointer g_class); static void dvdreadsrc_base_init (gpointer g_class);
static void dvdreadsrc_class_init (DVDReadSrcClass * klass); static void dvdreadsrc_class_init (DVDReadSrcClass * klass);
static void dvdreadsrc_init (DVDReadSrc * dvdreadsrc); static void dvdreadsrc_init (DVDReadSrc * dvdreadsrc);
static void dvdreadsrc_dispose (GObject * object);
static void dvdreadsrc_set_property (GObject * object, guint prop_id, static void dvdreadsrc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void dvdreadsrc_get_property (GObject * object, guint prop_id, static void dvdreadsrc_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
/*static GstData * dvdreadsrc_get (GstPad *pad); */ static GstData *dvdreadsrc_get (GstPad * pad);
static void dvdreadsrc_loop (GstElement * element);
/*static GstBuffer * dvdreadsrc_get_region (GstPad *pad,gulong offset,gulong size); */ /*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->set_property = GST_DEBUG_FUNCPTR (dvdreadsrc_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (dvdreadsrc_get_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (dvdreadsrc_get_property);
gobject_class->dispose = dvdreadsrc_dispose;
gstelement_class->change_state = dvdreadsrc_change_state; gstelement_class->change_state = dvdreadsrc_change_state;
GST_DEBUG_CATEGORY_INIT (gstdvdreadsrc_debug, "dvdreadsrc", 0,
"DVD reader element based on dvdreadsrc");
} }
static void static void
@ -199,27 +207,28 @@ dvdreadsrc_init (DVDReadSrc * dvdreadsrc)
{ {
dvdreadsrc->priv = g_new (DVDReadSrcPrivate, 1); dvdreadsrc->priv = g_new (DVDReadSrcPrivate, 1);
dvdreadsrc->priv->srcpad = gst_pad_new ("src", GST_PAD_SRC); 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_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->location = g_strdup ("/dev/dvd");
dvdreadsrc->priv->new_seek = FALSE; dvdreadsrc->priv->new_seek = TRUE;
dvdreadsrc->priv->title = 1; dvdreadsrc->priv->new_cell = TRUE;
dvdreadsrc->priv->chapter = 1; dvdreadsrc->priv->title = 0;
dvdreadsrc->priv->angle = 1; dvdreadsrc->priv->chapter = 0;
dvdreadsrc->priv->angle = 0;
} }
/* FIXME: this code is not being used */
#ifdef PLEASEFIXTHISCODE
static void static void
dvdreadsrc_destroy (DVDReadSrc * dvdreadsrc) dvdreadsrc_dispose (GObject * object)
{ {
/* FIXME */ DVDReadSrc *dvdreadsrc = DVDREADSRC (object);
g_print ("FIXME\n");
g_free (dvdreadsrc->priv); if (dvdreadsrc->priv) {
g_free (dvdreadsrc->priv->location);
g_free (dvdreadsrc->priv);
dvdreadsrc->priv = NULL;
}
} }
#endif
static void static void
dvdreadsrc_set_property (GObject * object, guint prop_id, const GValue * value, 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)); priv->location = g_strdup (g_value_get_string (value));
break; break;
case ARG_TITLE: case ARG_TITLE:
priv->title = g_value_get_int (value) - 1; priv->title = g_value_get_int (value);
priv->new_seek = TRUE; priv->new_seek = TRUE;
break; break;
case ARG_CHAPTER: case ARG_CHAPTER:
priv->chapter = g_value_get_int (value) - 1; priv->chapter = g_value_get_int (value);
priv->new_seek = TRUE; priv->new_seek = TRUE;
break; break;
case ARG_ANGLE: case ARG_ANGLE:
priv->angle = g_value_get_int (value) - 1; priv->angle = g_value_get_int (value);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 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); g_value_set_string (value, priv->location);
break; break;
case ARG_TITLE: case ARG_TITLE:
g_value_set_int (value, priv->title + 1); g_value_set_int (value, priv->title);
break; break;
case ARG_CHAPTER: case ARG_CHAPTER:
g_value_set_int (value, priv->chapter + 1); g_value_set_int (value, priv->chapter);
break; break;
case ARG_ANGLE: case ARG_ANGLE:
g_value_set_int (value, priv->angle + 1); g_value_set_int (value, priv->angle);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -320,7 +329,7 @@ _open (DVDReadSrcPrivate * priv, const gchar * location)
*/ */
priv->dvd = DVDOpen (location); priv->dvd = DVDOpen (location);
if (!priv->dvd) { if (!priv->dvd) {
fprintf (stderr, "Couldn't open DVD: %s\n", location); GST_ERROR ("Couldn't open DVD: %s", location);
return -1; return -1;
} }
@ -331,7 +340,7 @@ _open (DVDReadSrcPrivate * priv, const gchar * location)
*/ */
priv->vmg_file = ifoOpen (priv->dvd, 0); priv->vmg_file = ifoOpen (priv->dvd, 0);
if (!priv->vmg_file) { if (!priv->vmg_file) {
fprintf (stderr, "Can't open VMG info.\n"); GST_ERROR ("Can't open VMG info");
DVDClose (priv->dvd); DVDClose (priv->dvd);
return -1; return -1;
} }
@ -356,10 +365,10 @@ _seek (DVDReadSrcPrivate * priv, int title, int chapter, int angle)
/** /**
* Make sure our title number is valid. * Make sure our title number is valid.
*/ */
fprintf (stderr, "There are %d titles on this DVD.\n", GST_LOG ("There are %d titles on this DVD", priv->tt_srpt->nr_of_srpts);
priv->tt_srpt->nr_of_srpts);
if (title < 0 || title >= 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); ifoClose (priv->vmg_file);
DVDClose (priv->dvd); DVDClose (priv->dvd);
return -1; 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. * 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); priv->tt_srpt->title[title].nr_of_ptts);
if (chapter < 0 || chapter >= 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); ifoClose (priv->vmg_file);
DVDClose (priv->dvd); DVDClose (priv->dvd);
return -1; 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. * 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); priv->tt_srpt->title[title].nr_of_angles);
if (angle < 0 || angle >= 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); ifoClose (priv->vmg_file);
DVDClose (priv->dvd); DVDClose (priv->dvd);
return -1; return -1;
@ -399,7 +410,7 @@ _seek (DVDReadSrcPrivate * priv, int title, int chapter, int angle)
priv->vts_file = priv->vts_file =
ifoOpen (priv->dvd, priv->tt_srpt->title[title].title_set_nr); ifoOpen (priv->dvd, priv->tt_srpt->title[title].title_set_nr);
if (!priv->vts_file) { 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); priv->tt_srpt->title[title].title_set_nr);
ifoClose (priv->vmg_file); ifoClose (priv->vmg_file);
DVDClose (priv->dvd); 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->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; priv->start_cell = priv->cur_pgc->program_map[priv->pgn - 1] - 1;
/** /**
* We've got enough info, time to open the title set data. * 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, DVDOpenFile (priv->dvd, priv->tt_srpt->title[title].title_set_nr,
DVD_READ_TITLE_VOBS); DVD_READ_TITLE_VOBS);
if (!priv->dvd_title) { 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); priv->tt_srpt->title[title].title_set_nr);
ifoClose (priv->vts_file); ifoClose (priv->vts_file);
ifoClose (priv->vmg_file); ifoClose (priv->vmg_file);
@ -437,141 +447,11 @@ _seek (DVDReadSrcPrivate * priv, int title, int chapter, int angle)
return 0; return 0;
} }
static void /*
dvdreadsrc_loop (GstElement * element) * Read function.
{ * -1: error, -2: eos, -3: try again, 0: ok.
DVDReadSrc *dvdreadsrc; */
DVDReadSrcPrivate *priv;
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 static int
_read (DVDReadSrcPrivate * priv, int angle, int new_seek, GstBuffer * buf) _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->next_cell = priv->start_cell;
priv->cur_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. */ /* Check if we're entering an angle block. */
if (priv->cur_pgc->cell_playback[priv->cur_cell].block_type 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 < 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; dsi_t dsi_pack;
unsigned int next_vobu, next_ilvu_start, cur_output_size; unsigned int next_vobu, next_ilvu_start, cur_output_size;
int len; int len;
/** /**
* Read NAV packet. * 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) { if (len == 0) {
fprintf (stderr, "Read failed for block %d\n", priv->cur_pack); GST_ERROR ("Read failed for block %d", priv->cur_pack);
_close (priv);
return -1; return -1;
} }
assert (is_nav_pack (data)); assert (is_nav_pack (data));
@ -640,7 +518,7 @@ _read (DVDReadSrcPrivate * priv, int angle, int new_seek, GstBuffer * buf)
/** /**
* Parse the contained dsi packet. * 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); 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. * 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) { 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); cur_output_size, priv->cur_pack);
_close (priv);
return -1; return -1;
} }
GST_BUFFER_SIZE (buf) = cur_output_size * DVD_VIDEO_LB_LEN; GST_BUFFER_SIZE (buf) = cur_output_size * DVD_VIDEO_LB_LEN;
priv->cur_pack = next_vobu; priv->cur_pack = next_vobu;
return 0;
} else {
priv->new_cell = TRUE;
} }
} else { } else {
return -1; return -2;
} }
return 0; /* again */
return -3;
} }
static GstData * static GstData *
dvdreadsrc_get (GstPad * pad) dvdreadsrc_get (GstPad * pad)
{ {
gint res;
DVDReadSrc *dvdreadsrc; DVDReadSrc *dvdreadsrc;
DVDReadSrcPrivate *priv; DVDReadSrcPrivate *priv;
GstBuffer *buf; GstBuffer *buf;
@ -708,30 +593,33 @@ dvdreadsrc_get (GstPad * pad)
/* create the buffer */ /* create the buffer */
/* FIXME: should eventually use a bufferpool for this */ /* FIXME: should eventually use a bufferpool for this */
buf = gst_buffer_new (); buf = gst_buffer_new_and_alloc (1024 * DVD_VIDEO_LB_LEN);
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);
if (priv->new_seek) { 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 */ /* read it in from the file */
if (_read (priv, priv->angle, priv->new_seek, buf)) { while ((res = _read (priv, priv->angle, priv->new_seek, buf)) == -3);
gst_element_signal_eos (GST_ELEMENT (dvdreadsrc)); switch (res) {
return NULL; 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 */ /* open the file, necessary to go to RUNNING state */
static gboolean 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_IS_DVDREADSRC (src), FALSE);
g_return_val_if_fail (!GST_FLAG_IS_SET (src, DVDREADSRC_OPEN), 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; 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; return FALSE;
}
GST_FLAG_SET (src, DVDREADSRC_OPEN); GST_FLAG_SET (src, DVDREADSRC_OPEN);
@ -765,20 +657,29 @@ dvdreadsrc_close_file (DVDReadSrc * src)
static GstElementStateReturn static GstElementStateReturn
dvdreadsrc_change_state (GstElement * element) dvdreadsrc_change_state (GstElement * element)
{ {
DVDReadSrc *dvdreadsrc = DVDREADSRC (element);
g_return_val_if_fail (GST_IS_DVDREADSRC (element), GST_STATE_FAILURE); g_return_val_if_fail (GST_IS_DVDREADSRC (element), GST_STATE_FAILURE);
GST_DEBUG ("gstdvdreadsrc: state pending %d", GST_STATE_PENDING (element)); GST_DEBUG ("gstdvdreadsrc: state pending %d", GST_STATE_PENDING (element));
/* if going down into NULL state, close the file if it's open */ /* if going down into NULL state, close the file if it's open */
if (GST_STATE_PENDING (element) == GST_STATE_NULL) { switch (GST_STATE_TRANSITION (element)) {
if (GST_FLAG_IS_SET (element, DVDREADSRC_OPEN)) case GST_STATE_NULL_TO_READY:
dvdreadsrc_close_file (DVDREADSRC (element));
/* otherwise (READY or higher) we need to open the file */
} else {
if (!GST_FLAG_IS_SET (element, DVDREADSRC_OPEN)) {
if (!dvdreadsrc_open_file (DVDREADSRC (element))) if (!dvdreadsrc_open_file (DVDREADSRC (element)))
return GST_STATE_FAILURE; 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 ;-) */ /* 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"); GST_WARNING ("Unexpected event before seek");
if (!gst_riff_read_use_event (riff, event)) if (!gst_riff_read_use_event (riff, event))
return NULL; return NULL;
event = NULL;
} }
if (remaining) if (remaining)

View file

@ -60,6 +60,13 @@ enum
/* Define the capabilities separately, to be able to reuse them. */ /* 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 \ #define VIDEO_CAPS \
GST_STATIC_CAPS ("video/mpeg, " \ GST_STATIC_CAPS ("video/mpeg, " \
"mpegversion = (int) { 1, 2 }, " \ "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; 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); demux_class->audio_template = gst_static_pad_template_get (&audio_template);
klass->cur_video_template = gst_static_pad_template_get (&cur_video_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) gst_dvd_demux_init (GstDVDDemux * dvd_demux)
{ {
GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (dvd_demux); GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (dvd_demux);
GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (dvd_demux);
gint i; gint i;
GST_FLAG_SET (dvd_demux, GST_ELEMENT_EVENT_AWARE); GST_FLAG_SET (dvd_demux, GST_ELEMENT_EVENT_AWARE);
@ -256,12 +266,15 @@ gst_dvd_demux_init (GstDVDDemux * dvd_demux)
dvd_demux->cur_video = dvd_demux->cur_video =
DEMUX_CLASS (dvd_demux)->new_output_pad (mpeg_demux, "current_video", DEMUX_CLASS (dvd_demux)->new_output_pad (mpeg_demux, "current_video",
CLASS (dvd_demux)->cur_video_template); CLASS (dvd_demux)->cur_video_template);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), dvd_demux->cur_video);
dvd_demux->cur_audio = dvd_demux->cur_audio =
DEMUX_CLASS (dvd_demux)->new_output_pad (mpeg_demux, "current_audio", DEMUX_CLASS (dvd_demux)->new_output_pad (mpeg_demux, "current_audio",
CLASS (dvd_demux)->cur_audio_template); CLASS (dvd_demux)->cur_audio_template);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), dvd_demux->cur_audio);
dvd_demux->cur_subpicture = dvd_demux->cur_subpicture =
DEMUX_CLASS (dvd_demux)->new_output_pad (mpeg_demux, "current_subpicture", DEMUX_CLASS (dvd_demux)->new_output_pad (mpeg_demux, "current_subpicture",
CLASS (dvd_demux)->cur_subpicture_template); 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->mpeg_version = 0;
dvd_demux->cur_video_nr = 0; dvd_demux->cur_video_nr = 0;
@ -271,10 +284,24 @@ gst_dvd_demux_init (GstDVDDemux * dvd_demux)
/* Start the timestamp sequence in 0. */ /* Start the timestamp sequence in 0. */
dvd_demux->last_end_ptm = 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 /* Try to prevent the mpegparse infrastructure from doing timestamp
adjustment. */ adjustment. */
mpeg_parse->do_adjust = FALSE; mpeg_parse->do_adjust = FALSE;
mpeg_parse->adjust = 0; mpeg_parse->adjust = 0;
#endif
dvd_demux->just_flushed = FALSE; dvd_demux->just_flushed = FALSE;
dvd_demux->discont_time = GST_CLOCK_TIME_NONE; 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; guint8 sample_info = 0;
GstMPEGStream *str; GstMPEGStream *str;
GstDVDLPCMStream *lpcm_str = NULL; GstDVDLPCMStream *lpcm_str = NULL;
gchar *name;
GstCaps *caps; GstCaps *caps;
gint width, rate, channels; 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 (stream_nr < GST_MPEG_DEMUX_NUM_AUDIO_STREAMS, NULL);
g_return_val_if_fail (type > GST_MPEG_DEMUX_AUDIO_UNKNOWN && 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]; str = mpeg_demux->audio_stream[stream_nr];
if (str == NULL) { if (str == NULL) {
gchar *name;
if (type != GST_DVD_DEMUX_AUDIO_LPCM) { if (type != GST_DVD_DEMUX_AUDIO_LPCM) {
str = g_new0 (GstMPEGStream, 1); str = g_new0 (GstMPEGStream, 1);
} else { } else {
@ -515,6 +544,7 @@ gst_dvd_demux_get_audio_stream (GstMPEGDemux * mpeg_demux,
/* update caps */ /* update caps */
str->type = GST_MPEG_DEMUX_AUDIO_UNKNOWN; str->type = GST_MPEG_DEMUX_AUDIO_UNKNOWN;
g_free (name); g_free (name);
add_pad = TRUE;
mpeg_demux->audio_stream[stream_nr] = str; mpeg_demux->audio_stream[stream_nr] = str;
} else { } else {
@ -587,6 +617,8 @@ gst_dvd_demux_get_audio_stream (GstMPEGDemux * mpeg_demux,
/* This is the current audio stream. Use the same caps. */ /* This is the current audio stream. Use the same caps. */
gst_pad_set_explicit_caps (dvd_demux->cur_audio, gst_caps_copy (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; str->type = type;
} }
@ -603,6 +635,7 @@ gst_dvd_demux_get_subpicture_stream (GstMPEGDemux * mpeg_demux,
GstMPEGStream *str; GstMPEGStream *str;
gchar *name; gchar *name;
GstCaps *caps; 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 (stream_nr < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS, NULL);
g_return_val_if_fail (type > GST_DVD_DEMUX_SUBP_UNKNOWN && 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, DEMUX_CLASS (dvd_demux)->init_stream (mpeg_demux, type, str, stream_nr,
name, CLASS (dvd_demux)->subpicture_template); name, CLASS (dvd_demux)->subpicture_template);
g_free (name); g_free (name);
add_pad = TRUE;
dvd_demux->subpicture_stream[stream_nr] = str; dvd_demux->subpicture_stream[stream_nr] = str;
} else { } else {
@ -637,6 +671,8 @@ gst_dvd_demux_get_subpicture_stream (GstMPEGDemux * mpeg_demux,
} }
gst_caps_free (caps); gst_caps_free (caps);
if (add_pad)
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
str->type = GST_DVD_DEMUX_SUBP_DVD; str->type = GST_DVD_DEMUX_SUBP_DVD;
} }
@ -891,5 +927,5 @@ gboolean
gst_dvd_demux_plugin_init (GstPlugin * plugin) gst_dvd_demux_plugin_init (GstPlugin * plugin)
{ {
return gst_element_register (plugin, "dvddemux", 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); 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->video_template = gst_static_pad_template_get (&video_template);
klass->audio_template = gst_static_pad_template_get (&audio_template); klass->audio_template = gst_static_pad_template_get (&audio_template);
klass->private_template = gst_static_pad_template_get (&private_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->get_private_stream = gst_mpeg_demux_get_private_stream;
klass->send_subbuffer = gst_mpeg_demux_send_subbuffer; klass->send_subbuffer = gst_mpeg_demux_send_subbuffer;
klass->process_private = gst_mpeg_demux_process_private; 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 static void
gst_mpeg_demux_init (GstMPEGDemux * mpeg_demux) gst_mpeg_demux_init (GstMPEGDemux * mpeg_demux)
{ {
gint i; 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 */ /* i think everything is already zero'd, but oh well */
for (i = 0; i < GST_MPEG_DEMUX_NUM_VIDEO_STREAMS; i++) { 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_set_query_function (pad, gst_mpeg_parse_handle_src_query);
gst_pad_use_explicit_caps (pad); gst_pad_use_explicit_caps (pad);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), pad);
return pad; return pad;
} }
@ -406,9 +397,11 @@ gst_mpeg_demux_get_video_stream (GstMPEGDemux * mpeg_demux,
GST_ELEMENT_ERROR (GST_ELEMENT (mpeg_demux), GST_ELEMENT_ERROR (GST_ELEMENT (mpeg_demux),
CORE, NEGOTIATION, (NULL), ("failed to set caps")); CORE, NEGOTIATION, (NULL), ("failed to set caps"));
gst_caps_free (caps); gst_caps_free (caps);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
return str; return str;
} }
gst_caps_free (caps); gst_caps_free (caps);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
/* Store the current values. */ /* Store the current values. */
video_str->mpeg_version = mpeg_version; 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), GST_ELEMENT_ERROR (GST_ELEMENT (mpeg_demux),
CORE, NEGOTIATION, (NULL), ("failed to set caps")); CORE, NEGOTIATION, (NULL), ("failed to set caps"));
gst_caps_free (caps); gst_caps_free (caps);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
return str; return str;
} }
gst_caps_free (caps); gst_caps_free (caps);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
} }
return str; 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)->init_stream (mpeg_demux, type, str, stream_nr, name,
CLASS (mpeg_demux)->private_template); CLASS (mpeg_demux)->private_template);
g_free (name); g_free (name);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
mpeg_demux->private_stream[stream_nr] = str; mpeg_demux->private_stream[stream_nr] = str;
} }
@ -784,7 +780,7 @@ gst_mpeg_demux_parse_pes (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
guint16 datalen; guint16 datalen;
guint16 headerlen; guint16 headerlen;
GstClockTime timestamp = GST_CLOCK_TIME_NONE; GstClockTime timestamp;
GstMPEGStream *outstream = NULL; GstMPEGStream *outstream = NULL;
guint8 *buf; guint8 *buf;
@ -828,7 +824,7 @@ gst_mpeg_demux_parse_pes (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
id, pts, MPEGTIME_TO_GSTTIME (pts)); id, pts, MPEGTIME_TO_GSTTIME (pts));
pts += mpeg_parse->adjust; pts += mpeg_parse->adjust;
timestamp = MPEGTIME_TO_GSTTIME (pts) + mpeg_demux->adjust;; timestamp = MPEGTIME_TO_GSTTIME (pts) + mpeg_demux->adjust;
} else { } else {
timestamp = GST_CLOCK_TIME_NONE; 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. */ /* constant corresponds to the 2 bytes of the packet length. */
headerlen = 2; headerlen = 2;
datalen = packet_length; datalen = packet_length;
timestamp = GST_CLOCK_TIME_NONE;
} }
GST_DEBUG_OBJECT (mpeg_demux, "headerlen is %d, datalen is %d", GST_DEBUG_OBJECT (mpeg_demux, "headerlen is %d, datalen is %d",
@ -1096,5 +1094,5 @@ gboolean
gst_mpeg_demux_plugin_init (GstPlugin * plugin) gst_mpeg_demux_plugin_init (GstPlugin * plugin)
{ {
return gst_element_register (plugin, "mpegdemux", 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, static void gst_mpeg_parse_send_discont (GstMPEGParse * mpeg_parse,
GstClockTime time); 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_loop (GstElement * element);
static void gst_mpeg_parse_get_property (GObject * object, guint prop_id, 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->get_property = gst_mpeg_parse_get_property;
gobject_class->set_property = gst_mpeg_parse_set_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->change_state = gst_mpeg_parse_change_state;
gstelement_class->set_clock = gst_mpeg_parse_set_clock; gstelement_class->set_clock = gst_mpeg_parse_set_clock;
gstelement_class->get_index = gst_mpeg_parse_get_index; gstelement_class->get_index = gst_mpeg_parse_get_index;
@ -198,31 +201,34 @@ gst_mpeg_parse_class_init (GstMPEGParseClass * klass)
static void static void
gst_mpeg_parse_init (GstMPEGParse * mpeg_parse) gst_mpeg_parse_init (GstMPEGParse * mpeg_parse)
{ {
mpeg_parse->sinkpad = GstElementClass *klass = GST_ELEMENT_GET_CLASS (mpeg_parse);
gst_pad_new_from_template (gst_static_pad_template_get (&sink_factory), GstPadTemplate *templ;
"sink");
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_element_add_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->sinkpad);
gst_pad_set_formats_function (mpeg_parse->sinkpad, gst_pad_set_formats_function (mpeg_parse->sinkpad,
gst_mpeg_parse_get_src_formats); gst_mpeg_parse_get_src_formats);
gst_pad_set_convert_function (mpeg_parse->sinkpad, gst_pad_set_convert_function (mpeg_parse->sinkpad,
gst_mpeg_parse_convert_src); gst_mpeg_parse_convert_src);
mpeg_parse->srcpad = if ((templ = gst_element_class_get_pad_template (klass, "src"))) {
gst_pad_new_from_template (gst_static_pad_template_get (&src_factory), mpeg_parse->srcpad = gst_pad_new_from_template (templ, "src");
"src"); gst_element_add_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->srcpad);
gst_element_add_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->srcpad); gst_pad_set_formats_function (mpeg_parse->srcpad,
gst_pad_set_formats_function (mpeg_parse->srcpad, gst_mpeg_parse_get_src_formats);
gst_mpeg_parse_get_src_formats); gst_pad_set_convert_function (mpeg_parse->srcpad,
gst_pad_set_convert_function (mpeg_parse->srcpad, gst_mpeg_parse_convert_src); gst_mpeg_parse_convert_src);
gst_pad_set_event_mask_function (mpeg_parse->srcpad, gst_pad_set_event_mask_function (mpeg_parse->srcpad,
gst_mpeg_parse_get_src_event_masks); gst_mpeg_parse_get_src_event_masks);
gst_pad_set_event_function (mpeg_parse->srcpad, gst_pad_set_event_function (mpeg_parse->srcpad,
gst_mpeg_parse_handle_src_event); gst_mpeg_parse_handle_src_event);
gst_pad_set_query_type_function (mpeg_parse->srcpad, gst_pad_set_query_type_function (mpeg_parse->srcpad,
gst_mpeg_parse_get_src_query_types); gst_mpeg_parse_get_src_query_types);
gst_pad_set_query_function (mpeg_parse->srcpad, gst_pad_set_query_function (mpeg_parse->srcpad,
gst_mpeg_parse_handle_src_query); gst_mpeg_parse_handle_src_query);
gst_pad_use_explicit_caps (mpeg_parse->srcpad); gst_pad_use_explicit_caps (mpeg_parse->srcpad);
}
gst_element_set_loop_function (GST_ELEMENT (mpeg_parse), gst_mpeg_parse_loop); 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 static gboolean
gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer) 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, G_GUINT64_FORMAT " real:%" G_GINT64_FORMAT " adjust:%" G_GINT64_FORMAT,
mpeg_parse->next_scr, mpeg_parse->current_scr + mpeg_parse->adjust, mpeg_parse->next_scr, mpeg_parse->current_scr + mpeg_parse->adjust,
mpeg_parse->current_scr, mpeg_parse->adjust); mpeg_parse->current_scr, mpeg_parse->adjust);
if (mpeg_parse->do_adjust) { if (mpeg_parse->do_adjust) {
mpeg_parse->adjust += mpeg_parse->adjust +=
(gint64) mpeg_parse->next_scr - (gint64) mpeg_parse->current_scr; (gint64) mpeg_parse->next_scr - (gint64) mpeg_parse->current_scr;
GST_DEBUG ("new adjust: %" G_GINT64_FORMAT, mpeg_parse->adjust); GST_DEBUG ("new adjust: %" G_GINT64_FORMAT, mpeg_parse->adjust);
} else {
mpeg_parse->discont_pending = TRUE;
} }
} }