mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-20 15:27:07 +00:00
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:
parent
1fc1f89e91
commit
97148ae7cd
6 changed files with 254 additions and 244 deletions
40
ChangeLog
40
ChangeLog
|
@ -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),
|
||||
|
|
|
@ -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 ;-) */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue