mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-02 12:32:29 +00:00
ext/dvdnav/dvdnavsrc.*: Apply patch that adds some seeking support to dvdnav, and fixes it in various other ways. Thi...
Original commit message from CVS: * ext/dvdnav/dvdnavsrc.c: * ext/dvdnav/dvdnavsrc.h: Apply patch that adds some seeking support to dvdnav, and fixes it in various other ways. This doesn't make dvdnavsrc fully functional, but moves it forward. Fixes: #476149 Patch By: Simone Gotti <simone.gotti@email.it> * ext/dvdnav/gst-dvd: Update the simple dvdnavsrc gst-launch example to work for 0.10
This commit is contained in:
parent
fa749c8723
commit
b1fe467289
5 changed files with 576 additions and 80 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
||||||
|
2008-03-04 Jan Schmidt <jan.schmidt@sun.com>
|
||||||
|
|
||||||
|
* ext/dvdnav/dvdnavsrc.c:
|
||||||
|
* ext/dvdnav/dvdnavsrc.h:
|
||||||
|
Apply patch that adds some seeking support to dvdnav, and fixes it
|
||||||
|
in various other ways. This doesn't make dvdnavsrc fully functional,
|
||||||
|
but moves it forward.
|
||||||
|
|
||||||
|
Fixes: #476149
|
||||||
|
Patch By: Simone Gotti <simone.gotti@email.it>
|
||||||
|
|
||||||
|
* ext/dvdnav/gst-dvd:
|
||||||
|
Update the simple dvdnavsrc gst-launch example to work for 0.10
|
||||||
|
|
||||||
2008-03-03 Peter Kjellerstedt <pkj@axis.com>
|
2008-03-03 Peter Kjellerstedt <pkj@axis.com>
|
||||||
|
|
||||||
* configure.ac:
|
* configure.ac:
|
||||||
|
|
2
common
2
common
|
@ -1 +1 @@
|
||||||
Subproject commit 668c3f0b72d50813c30eb04be7048f638037c571
|
Subproject commit e02bd43fe6b9e45536eccbf5b7a5f9eae62030fd
|
|
@ -104,13 +104,14 @@ gst_dvd_nav_src_make_dvd_event (GstDvdNavSrc * src,
|
||||||
static void gst_dvd_nav_src_push_dvd_nav_packet_event (GstDvdNavSrc * src,
|
static void gst_dvd_nav_src_push_dvd_nav_packet_event (GstDvdNavSrc * src,
|
||||||
const pci_t * pci);
|
const pci_t * pci);
|
||||||
static void gst_dvd_nav_src_push_clut_change_event (GstDvdNavSrc * src,
|
static void gst_dvd_nav_src_push_clut_change_event (GstDvdNavSrc * src,
|
||||||
const guint * clut);
|
const guint32 * clut);
|
||||||
static GstFlowReturn gst_dvd_nav_src_create (GstPushSrc * pushsrc,
|
static GstFlowReturn gst_dvd_nav_src_create (GstPushSrc * pushsrc,
|
||||||
GstBuffer ** p_buf);
|
GstBuffer ** p_buf);
|
||||||
static gboolean gst_dvd_nav_src_src_event (GstBaseSrc * basesrc,
|
static gboolean gst_dvd_nav_src_src_event (GstBaseSrc * basesrc,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
static gboolean gst_dvd_nav_src_query (GstBaseSrc * basesrc,
|
static gboolean gst_dvd_nav_src_query (GstBaseSrc * basesrc,
|
||||||
GstQuery * query);
|
GstQuery * query);
|
||||||
|
static gboolean gst_dvd_nav_src_do_seek (GstBaseSrc * src, GstSegment * s);
|
||||||
static gboolean gst_dvd_nav_src_is_open (GstDvdNavSrc * src);
|
static gboolean gst_dvd_nav_src_is_open (GstDvdNavSrc * src);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -132,6 +133,11 @@ gst_dvd_nav_src_make_dvd_event (GstDvdNavSrc * src,
|
||||||
|
|
||||||
static void gst_dvd_nav_src_uri_handler_init (gpointer g_iface,
|
static void gst_dvd_nav_src_uri_handler_init (gpointer g_iface,
|
||||||
gpointer iface_data);
|
gpointer iface_data);
|
||||||
|
static gboolean gst_dvd_nav_src_query_position (GstDvdNavSrc * src,
|
||||||
|
GstFormat format, gint64 * p_val);
|
||||||
|
static gboolean gst_dvd_nav_src_query_duration (GstDvdNavSrc * src,
|
||||||
|
GstFormat format, gint64 * p_val);
|
||||||
|
|
||||||
|
|
||||||
static guint gst_dvd_nav_src_signals[LAST_SIGNAL];
|
static guint gst_dvd_nav_src_signals[LAST_SIGNAL];
|
||||||
|
|
||||||
|
@ -162,6 +168,13 @@ GST_BOILERPLATE_FULL (GstDvdNavSrc, gst_dvd_nav_src, GstPushSrc,
|
||||||
gst_element_class_set_details (element_class, &gst_dvd_nav_src_details);
|
gst_element_class_set_details (element_class, &gst_dvd_nav_src_details);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_dvd_nav_src_is_seekable (GstBaseSrc * src)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_dvd_nav_src_class_init (GstDvdNavSrcClass * klass)
|
gst_dvd_nav_src_class_init (GstDvdNavSrcClass * klass)
|
||||||
{
|
{
|
||||||
|
@ -229,7 +242,9 @@ gst_dvd_nav_src_class_init (GstDvdNavSrcClass * klass)
|
||||||
gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_dvd_nav_src_query);
|
gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_dvd_nav_src_query);
|
||||||
|
|
||||||
gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_dvd_nav_src_create);
|
gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_dvd_nav_src_create);
|
||||||
|
gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_dvd_nav_src_do_seek);
|
||||||
|
gstbasesrc_class->is_seekable =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_dvd_nav_src_is_seekable);
|
||||||
#if 0
|
#if 0
|
||||||
gstelement_class->set_clock = gst_dvd_nav_src_set_clock;
|
gstelement_class->set_clock = gst_dvd_nav_src_set_clock;
|
||||||
#endif
|
#endif
|
||||||
|
@ -248,10 +263,11 @@ gst_dvd_nav_src_init (GstDvdNavSrc * src, GstDvdNavSrcClass * klass)
|
||||||
src->last_uri = NULL;
|
src->last_uri = NULL;
|
||||||
|
|
||||||
src->pending_offset = -1;
|
src->pending_offset = -1;
|
||||||
src->did_seek = FALSE;
|
|
||||||
src->new_seek = FALSE;
|
src->new_seek = FALSE;
|
||||||
src->seek_pending = FALSE;
|
src->seek_pending = FALSE;
|
||||||
src->need_flush = FALSE;
|
src->need_flush = FALSE;
|
||||||
|
src->use_tmaps = FALSE;
|
||||||
|
src->still_frame = FALSE;
|
||||||
|
|
||||||
/* Pause mode is initially inactive. */
|
/* Pause mode is initially inactive. */
|
||||||
src->pause_mode = GST_DVD_NAV_SRC_PAUSE_OFF;
|
src->pause_mode = GST_DVD_NAV_SRC_PAUSE_OFF;
|
||||||
|
@ -280,7 +296,9 @@ gst_dvd_nav_src_init (GstDvdNavSrc * src, GstDvdNavSrcClass * klass)
|
||||||
src->cell_start = 0;
|
src->cell_start = 0;
|
||||||
src->pg_start = 0;
|
src->pg_start = 0;
|
||||||
|
|
||||||
|
src->vmg_file = NULL;
|
||||||
src->vts_attrs = NULL;
|
src->vts_attrs = NULL;
|
||||||
|
src->vts_file = NULL;
|
||||||
src->cur_vts = 0;
|
src->cur_vts = 0;
|
||||||
|
|
||||||
/* avoid unnecessary start/stop in gst_base_src_check_get_range() */
|
/* avoid unnecessary start/stop in gst_base_src_check_get_range() */
|
||||||
|
@ -337,11 +355,9 @@ gst_dvd_nav_src_set_property (GObject * object, guint prop_id,
|
||||||
#if 0
|
#if 0
|
||||||
case ARG_TITLE:
|
case ARG_TITLE:
|
||||||
src->uri_title = g_value_get_int (value);
|
src->uri_title = g_value_get_int (value);
|
||||||
src->did_seek = TRUE;
|
|
||||||
break;
|
break;
|
||||||
case ARG_CHAPTER:
|
case ARG_CHAPTER:
|
||||||
src->uri_chapter = g_value_get_int (value);
|
src->uri_chapter = g_value_get_int (value);
|
||||||
src->did_seek = TRUE;
|
|
||||||
break;
|
break;
|
||||||
case ARG_ANGLE:
|
case ARG_ANGLE:
|
||||||
src->uri_angle = g_value_get_int (value);
|
src->uri_angle = g_value_get_int (value);
|
||||||
|
@ -519,15 +535,368 @@ gst_dvd_nav_src_set_clock (GstElement * element, GstClock * clock)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* update the time map when the title change */
|
||||||
|
static gint
|
||||||
|
gst_dvd_nav_src_update_tmaps (GstDvdNavSrc * src)
|
||||||
|
{
|
||||||
|
int32_t title, part;
|
||||||
|
title_info_t *info;
|
||||||
|
gint title_set_nr, title_ttn;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
/* Reset stuffs */
|
||||||
|
src->use_tmaps = FALSE;
|
||||||
|
src->title_tmap = NULL;
|
||||||
|
|
||||||
|
/* FIXME: check if the title really changed, by now it's called on every
|
||||||
|
* DVDNAV_CELL_CHANGE event.
|
||||||
|
*/
|
||||||
|
if (dvdnav_current_title_info (src->dvdnav, &title,
|
||||||
|
&part) != DVDNAV_STATUS_OK) {
|
||||||
|
GST_LOG_OBJECT (src, "Failed getting current title informations!");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (src, "title = %d, part = %d", title, part);
|
||||||
|
|
||||||
|
/* load the VTS information for the title set our title is in */
|
||||||
|
|
||||||
|
/* Close old vts file */
|
||||||
|
if (src->vts_file) {
|
||||||
|
ifoClose (src->vts_file);
|
||||||
|
src->vts_file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There isn't a timemap for the menus */
|
||||||
|
if (title < 1) {
|
||||||
|
GST_LOG_OBJECT (src, "Time map not available for menus");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
info = &src->tt_srpt->title[title - 1];
|
||||||
|
title_set_nr = info->title_set_nr;
|
||||||
|
GST_LOG_OBJECT (src, "title_set_nr = %d", title_set_nr);
|
||||||
|
title_ttn = info->vts_ttn;
|
||||||
|
GST_LOG_OBJECT (src, "title_ttn= %d", title_ttn);
|
||||||
|
|
||||||
|
src->vts_file = ifoOpen (src->dvd, title_set_nr);
|
||||||
|
if (src->vts_file == NULL) {
|
||||||
|
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||||
|
(_("Could not open DVD")),
|
||||||
|
("ifoOpen() failed: %s", g_strerror (errno)));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
src->vts_tmapt = src->vts_file->vts_tmapt;
|
||||||
|
src->vts_ptt_srpt = src->vts_file->vts_ptt_srpt;
|
||||||
|
|
||||||
|
if (src->vts_file->vts_tmapt != NULL) {
|
||||||
|
i = title_ttn - 1;
|
||||||
|
if (i >= 0 && i < src->vts_tmapt->nr_of_tmaps) {
|
||||||
|
src->title_tmap = &src->vts_tmapt->tmap[i];
|
||||||
|
GST_LOG_OBJECT (src, "Time map table number: %d", i);
|
||||||
|
} else {
|
||||||
|
src->title_tmap = NULL;
|
||||||
|
GST_LOG_OBJECT (src, "Cannot find table number for title %d", title_ttn);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the max map entry sector size is >= then the length reported
|
||||||
|
* by dvdnav_get_position, as looks like this function doesn't compute
|
||||||
|
* correctly the pos and length values.
|
||||||
|
*/
|
||||||
|
guint32 pos;
|
||||||
|
guint32 dvdnav_length;
|
||||||
|
|
||||||
|
if (dvdnav_get_position (src->dvdnav, &pos,
|
||||||
|
&dvdnav_length) != DVDNAV_STATUS_OK) {
|
||||||
|
GST_WARNING_OBJECT (src,
|
||||||
|
"Cannot get stream length by dvdnav, "
|
||||||
|
"won't enable tmaps use as we cannot check if they're interaction with dvdnav is right");
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
if (src->title_tmap) {
|
||||||
|
int tmap_length;
|
||||||
|
|
||||||
|
tmap_length =
|
||||||
|
(src->title_tmap->map_ent[src->title_tmap->
|
||||||
|
nr_of_entries] & 0x7fffffff);
|
||||||
|
if (tmap_length >= dvdnav_length) {
|
||||||
|
GST_LOG_OBJECT (src, "Using time maps for seeking");
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (src,
|
||||||
|
"Time maps has max sector (%d) < than length (%d) reported by dvdnav: "
|
||||||
|
"tmap problem or dvdnav bug?", dvdnav_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dump all tmaps for title set for debugging */
|
||||||
|
if (src->vts_tmapt) {
|
||||||
|
gint i, j;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (src, "nr_of_tmaps = %d", src->vts_tmapt->nr_of_tmaps);
|
||||||
|
for (i = 0; i < src->vts_tmapt->nr_of_tmaps; ++i) {
|
||||||
|
GST_LOG_OBJECT (src, "======= Table %d ===================", i);
|
||||||
|
GST_LOG_OBJECT (src, "Offset relative to VTS_TMAPTI: %d",
|
||||||
|
src->vts_tmapt->tmap_offset[i]);
|
||||||
|
GST_LOG_OBJECT (src, "Time unit (seconds) : %d",
|
||||||
|
src->vts_tmapt->tmap[i].tmu);
|
||||||
|
GST_LOG_OBJECT (src, "Number of entries : %d",
|
||||||
|
src->vts_tmapt->tmap[i].nr_of_entries);
|
||||||
|
for (j = 0; j < src->vts_tmapt->tmap[i].nr_of_entries; j++) {
|
||||||
|
guint64 time;
|
||||||
|
|
||||||
|
time = src->vts_tmapt->tmap[i].tmu * (j + 1) * GST_SECOND;
|
||||||
|
GST_LOG_OBJECT (src, "Time: %" GST_TIME_FORMAT " VOBU "
|
||||||
|
"Sector: %d %s", GST_TIME_ARGS (time),
|
||||||
|
src->vts_tmapt->tmap[i].map_ent[j] & 0x7fffffff,
|
||||||
|
(src->vts_tmapt->tmap[i].map_ent[j] >> 31) ? "discontinuity" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_LOG_OBJECT (src, "no vts_tmapt to dump");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
src->use_tmaps = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find sector from time using time map if available */
|
||||||
|
/* FIXME: do interpolation as in gst_dvd_nav_src_get_time_for_sector_tmap */
|
||||||
|
static gint
|
||||||
|
gst_dvd_nav_src_get_sector_from_time_tmap (GstDvdNavSrc * src, GstClockTime ts)
|
||||||
|
{
|
||||||
|
gint sector, i;
|
||||||
|
|
||||||
|
if (src->vts_tmapt == NULL || src->vts_tmapt->nr_of_tmaps == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sector = 0;
|
||||||
|
for (i = 0; i < src->title_tmap->nr_of_entries; ++i) {
|
||||||
|
GstClockTime entry_time;
|
||||||
|
|
||||||
|
entry_time = src->title_tmap->tmu * (i + 1) * GST_SECOND;
|
||||||
|
if (entry_time <= ts) {
|
||||||
|
sector = src->title_tmap->map_ent[i] & 0x7fffffff;
|
||||||
|
}
|
||||||
|
if (entry_time >= ts) {
|
||||||
|
return sector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ts == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find time for sector using time map, does interpolation */
|
||||||
|
static GstClockTime
|
||||||
|
gst_dvd_nav_src_get_time_for_sector_tmap (GstDvdNavSrc * src, guint sector)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
guint prev_sector = 0;
|
||||||
|
guint cur_sector = 0;
|
||||||
|
GstClockTime target, diff;
|
||||||
|
|
||||||
|
if (src->vts_tmapt == NULL || src->vts_tmapt->nr_of_tmaps == 0) {
|
||||||
|
return GST_CLOCK_TIME_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < src->title_tmap->nr_of_entries; ++i) {
|
||||||
|
prev_sector = cur_sector;
|
||||||
|
cur_sector = src->title_tmap->map_ent[i] & 0x7fffffff;
|
||||||
|
if (sector >= prev_sector && sector <= cur_sector) {
|
||||||
|
target = src->title_tmap->tmu * i * GST_SECOND;
|
||||||
|
if (i < src->title_tmap->nr_of_entries - 1) {
|
||||||
|
diff =
|
||||||
|
src->title_tmap->tmu * GST_SECOND * (sector -
|
||||||
|
prev_sector) / (cur_sector - prev_sector);
|
||||||
|
target += diff;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sector == 0)
|
||||||
|
return (GstClockTime) 0;
|
||||||
|
|
||||||
|
return GST_CLOCK_TIME_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find time for sector */
|
||||||
|
static GstClockTime
|
||||||
|
gst_dvd_nav_src_get_time_for_sector (GstDvdNavSrc * src, guint sector)
|
||||||
|
{
|
||||||
|
GstClockTime time;
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (src);
|
||||||
|
if (src->use_tmaps) {
|
||||||
|
time = gst_dvd_nav_src_get_time_for_sector_tmap (src, sector);
|
||||||
|
if (time != GST_CLOCK_TIME_NONE) {
|
||||||
|
GST_OBJECT_UNLOCK (src);
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Fallback to average time calculation */
|
||||||
|
time = (GstClockTime) ((float) sector / src->sector_length * src->pgc_length);
|
||||||
|
|
||||||
|
GST_OBJECT_UNLOCK (src);
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find sector from time */
|
||||||
|
static GstClockTime
|
||||||
|
gst_dvd_nav_src_get_sector_from_time (GstDvdNavSrc * src, GstClockTime time)
|
||||||
|
{
|
||||||
|
gint sector;
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (src);
|
||||||
|
if (src->use_tmaps) {
|
||||||
|
sector = gst_dvd_nav_src_get_sector_from_time_tmap (src, time);
|
||||||
|
if (sector >= 0) {
|
||||||
|
GST_OBJECT_UNLOCK (src);
|
||||||
|
return sector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fallback to average sector calculation */
|
||||||
|
sector = (GstClockTime) ((float) time / src->pgc_length * src->sector_length);
|
||||||
|
GST_OBJECT_UNLOCK (src);
|
||||||
|
|
||||||
|
return sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_dvd_nav_src_do_convert_query (GstDvdNavSrc * src, GstQuery * query)
|
||||||
|
{
|
||||||
|
GstFormat src_format, dest_format;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
gint64 src_val, dest_val = -1;
|
||||||
|
|
||||||
|
gst_query_parse_convert (query, &src_format, &src_val, &dest_format, NULL);
|
||||||
|
|
||||||
|
if (src_format == dest_format) {
|
||||||
|
dest_val = src_val;
|
||||||
|
ret = TRUE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: handle also chapter format */
|
||||||
|
/* Formats to consider: TIME, DEFAULT, BYTES, title, chapter, sector.
|
||||||
|
* Note: title and chapter are counted as starting from 0 here, just like
|
||||||
|
* in the context of seek events. Another note: DEFAULT format is undefined */
|
||||||
|
|
||||||
|
if (src_format == GST_FORMAT_BYTES) {
|
||||||
|
src_format = sector_format;
|
||||||
|
src_val /= DVD_SECTOR_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_format == sector_format) {
|
||||||
|
/* SECTOR => xyz */
|
||||||
|
if (dest_format == GST_FORMAT_TIME && src_val < G_MAXUINT) {
|
||||||
|
dest_val = gst_dvd_nav_src_get_time_for_sector (src, src_val);
|
||||||
|
ret = (dest_val >= 0);
|
||||||
|
} else if (dest_format == GST_FORMAT_BYTES) {
|
||||||
|
dest_val = src_val * DVD_SECTOR_SIZE;
|
||||||
|
ret = TRUE;
|
||||||
|
} else {
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
} else if (src_format == title_format) {
|
||||||
|
/* TITLE => xyz */
|
||||||
|
if (dest_format == GST_FORMAT_TIME) {
|
||||||
|
/* not really true, but we use this to trick the base source into
|
||||||
|
* handling seeks in title-format for us (the source won't know that
|
||||||
|
* we changed the title in this case) (changing titles should really
|
||||||
|
* be done with an interface rather than a seek, but for now we're
|
||||||
|
* stuck with this mechanism. Fix in 0.11) */
|
||||||
|
dest_val = (GstClockTime) 0;
|
||||||
|
ret = TRUE;
|
||||||
|
} else {
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
} else if (src_format == GST_FORMAT_TIME) {
|
||||||
|
/* TIME => sectors */
|
||||||
|
if (dest_format == sector_format || dest_format == GST_FORMAT_BYTES) {
|
||||||
|
dest_val = gst_dvd_nav_src_get_sector_from_time (src, src_val);
|
||||||
|
ret = (dest_val >= 0);
|
||||||
|
/* TIME => bytes */
|
||||||
|
if (dest_format == GST_FORMAT_BYTES) {
|
||||||
|
dest_val *= DVD_VIDEO_LB_LEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
gst_query_set_convert (query, src_format, src_val, dest_format, dest_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: handle also title, chapter, angle format */
|
||||||
|
static gboolean
|
||||||
|
gst_dvd_nav_src_do_seek (GstBaseSrc * basesrc, GstSegment * s)
|
||||||
|
{
|
||||||
|
GstDvdNavSrc *src;
|
||||||
|
|
||||||
|
src = GST_DVD_NAV_SRC (basesrc);
|
||||||
|
|
||||||
|
/* On the first call of do_seek in gstbasesrc during gst_base_src_activate_push the dvdnav vm
|
||||||
|
* isn't running. Return TRUE as the seek was done.
|
||||||
|
*/
|
||||||
|
if (src->first_seek == TRUE) {
|
||||||
|
src->first_seek = FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (src, "Seeking to %s: %12" G_GINT64_FORMAT,
|
||||||
|
gst_format_get_name (s->format), s->last_stop);
|
||||||
|
|
||||||
|
if (s->format == sector_format || s->format == GST_FORMAT_BYTES
|
||||||
|
|| s->format == GST_FORMAT_TIME) {
|
||||||
|
gint sector = 0;
|
||||||
|
|
||||||
|
/* Convert in sector format */
|
||||||
|
if (s->format == GST_FORMAT_BYTES) {
|
||||||
|
sector = s->last_stop / DVD_SECTOR_SIZE;
|
||||||
|
} else if (s->format == GST_FORMAT_TIME) {
|
||||||
|
sector = gst_dvd_nav_src_get_sector_from_time (src, s->last_stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dvdnav_sector_search (src->dvdnav, sector,
|
||||||
|
SEEK_SET) != DVDNAV_STATUS_OK) {
|
||||||
|
GST_DEBUG_OBJECT (src, "seek to %s %d failed",
|
||||||
|
gst_format_get_name (s->format), s->last_stop);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
GST_LOG_OBJECT (src, "seek to %s %d ok", gst_format_get_name (s->format),
|
||||||
|
s->last_stop);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_return_val_if_reached (FALSE);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_dvd_nav_src_tca_seek (GstDvdNavSrc * src, gint title, gint chapter,
|
gst_dvd_nav_src_tca_seek (GstDvdNavSrc * src, gint title, gint chapter,
|
||||||
gint angle)
|
gint angle)
|
||||||
{
|
{
|
||||||
int titles, programs, curangle, angles;
|
int titles, chapters, curangle, angles;
|
||||||
|
|
||||||
g_return_val_if_fail (src != NULL, FALSE);
|
g_return_val_if_fail (src != NULL, FALSE);
|
||||||
g_return_val_if_fail (src->dvdnav != NULL, FALSE);
|
g_return_val_if_fail (src->dvdnav != NULL, FALSE);
|
||||||
g_return_val_if_fail (gst_dvd_nav_src_is_open (src), FALSE);
|
// g_return_val_if_fail (gst_dvd_nav_src_is_open (src), FALSE);
|
||||||
|
|
||||||
/* Dont try to seek to track 0 - First Play program chain */
|
/* Dont try to seek to track 0 - First Play program chain */
|
||||||
g_return_val_if_fail (src->title > 0, FALSE);
|
g_return_val_if_fail (src->title > 0, FALSE);
|
||||||
|
@ -556,14 +925,14 @@ gst_dvd_nav_src_tca_seek (GstDvdNavSrc * src, gint title, gint chapter,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the chapter number is valid for this title */
|
/* Make sure the chapter number is valid for this title */
|
||||||
if (dvdnav_get_number_of_titles (src->dvdnav, &programs)
|
if (dvdnav_get_number_of_parts (src->dvdnav, title, &chapters)
|
||||||
!= DVDNAV_STATUS_OK) {
|
!= DVDNAV_STATUS_OK) {
|
||||||
GST_ERROR ("dvdnav_get_number_of_programs: %s",
|
GST_ERROR ("dvdnav_get_number_of_programs: %s",
|
||||||
dvdnav_err_to_string (src->dvdnav));
|
dvdnav_err_to_string (src->dvdnav));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
GST_INFO_OBJECT (src, "there are %d chapters in this title", programs);
|
GST_INFO_OBJECT (src, "there are %d chapters in this title", chapters);
|
||||||
if (chapter < 0 || chapter > programs) {
|
if (chapter < 0 || chapter > chapters) {
|
||||||
GST_ERROR_OBJECT (src, "invalid chapter %d", chapter);
|
GST_ERROR_OBJECT (src, "invalid chapter %d", chapter);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -601,7 +970,6 @@ gst_dvd_nav_src_tca_seek (GstDvdNavSrc * src, gint title, gint chapter,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
src->did_seek = TRUE;
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -743,7 +1111,10 @@ gst_dvd_nav_src_update_highlight (GstDvdNavSrc * src, gboolean force)
|
||||||
src->button = button;
|
src->button = button;
|
||||||
|
|
||||||
GST_DEBUG ("Sending dvd-spu-highlight for button %d", button);
|
GST_DEBUG ("Sending dvd-spu-highlight for button %d", button);
|
||||||
gst_pad_push_event (GST_BASE_SRC_PAD (src), event);
|
int ret = gst_pad_push_event (GST_BASE_SRC_PAD (src), event);
|
||||||
|
|
||||||
|
GST_DEBUG ("End Sending dvd-spu-highlight for button %d, ret: %d", button,
|
||||||
|
ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1019,7 +1390,7 @@ gst_dvd_nav_src_make_dvd_event (GstDvdNavSrc * src, const gchar * event_name,
|
||||||
va_end (varargs);
|
va_end (varargs);
|
||||||
|
|
||||||
/* Create the DVD event and put the structure into it. */
|
/* Create the DVD event and put the structure into it. */
|
||||||
event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, structure);
|
event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure);
|
||||||
|
|
||||||
GST_LOG_OBJECT (src, "created event %" GST_PTR_FORMAT, event);
|
GST_LOG_OBJECT (src, "created event %" GST_PTR_FORMAT, event);
|
||||||
|
|
||||||
|
@ -1065,7 +1436,8 @@ gst_dvd_nav_src_push_dvd_nav_packet_event (GstDvdNavSrc * src,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_dvd_nav_src_push_clut_change_event (GstDvdNavSrc * src, const guint * clut)
|
gst_dvd_nav_src_push_clut_change_event (GstDvdNavSrc * src,
|
||||||
|
const guint32 * clut)
|
||||||
{
|
{
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
|
@ -1254,6 +1626,11 @@ gst_dvd_nav_src_process_next_block (GstDvdNavSrc * src, GstBuffer ** p_buf)
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the next block is not DVDNAV_STILL_FRAME we can seek */
|
||||||
|
if (event != DVDNAV_STILL_FRAME) {
|
||||||
|
src->still_frame = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case DVDNAV_NOP:
|
case DVDNAV_NOP:
|
||||||
break;
|
break;
|
||||||
|
@ -1263,8 +1640,11 @@ gst_dvd_nav_src_process_next_block (GstDvdNavSrc * src, GstBuffer ** p_buf)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DVDNAV_STILL_FRAME:{
|
case DVDNAV_STILL_FRAME:{
|
||||||
|
src->still_frame = TRUE;
|
||||||
dvdnav_still_event_t *info = (dvdnav_still_event_t *) data;
|
dvdnav_still_event_t *info = (dvdnav_still_event_t *) data;
|
||||||
|
|
||||||
|
gst_dvd_nav_src_print_event (src, data, event, len);
|
||||||
|
|
||||||
if (src->pause_mode == GST_DVD_NAV_SRC_PAUSE_OFF) {
|
if (src->pause_mode == GST_DVD_NAV_SRC_PAUSE_OFF) {
|
||||||
gst_dvd_nav_src_print_event (src, data, event, len);
|
gst_dvd_nav_src_print_event (src, data, event, len);
|
||||||
|
|
||||||
|
@ -1276,12 +1656,12 @@ gst_dvd_nav_src_process_next_block (GstDvdNavSrc * src, GstBuffer ** p_buf)
|
||||||
} else {
|
} else {
|
||||||
src->pause_mode = GST_DVD_NAV_SRC_PAUSE_LIMITED;
|
src->pause_mode = GST_DVD_NAV_SRC_PAUSE_LIMITED;
|
||||||
src->pause_remain = info->length * GST_SECOND;
|
src->pause_remain = info->length * GST_SECOND;
|
||||||
/* FIXME */
|
gint64 val;
|
||||||
#if 0
|
|
||||||
|
gst_dvd_nav_src_query_position (src, GST_FORMAT_TIME, &val);
|
||||||
GST_INFO_OBJECT (src,
|
GST_INFO_OBJECT (src,
|
||||||
"starting limited pause: %d seconds at %llu",
|
"starting limited pause: %d seconds at %" GST_TIME_FORMAT,
|
||||||
info->length, gst_element_get_time (GST_ELEMENT (src)));
|
info->length, GST_TIME_ARGS (val));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For the moment, send the first empty event to let
|
/* For the moment, send the first empty event to let
|
||||||
|
@ -1297,22 +1677,18 @@ gst_dvd_nav_src_process_next_block (GstDvdNavSrc * src, GstBuffer ** p_buf)
|
||||||
|
|
||||||
if (src->pause_mode == GST_DVD_NAV_SRC_PAUSE_UNLIMITED ||
|
if (src->pause_mode == GST_DVD_NAV_SRC_PAUSE_UNLIMITED ||
|
||||||
src->pause_remain > 0) {
|
src->pause_remain > 0) {
|
||||||
/* FIXME */
|
|
||||||
#if 0
|
|
||||||
GstEvent *event;
|
|
||||||
|
|
||||||
/* Send a filler event to keep the pipeline going */
|
GST_DEBUG_OBJECT (src, "sleeping %d during still frame",
|
||||||
event = gst_event_new_filler_stamped (GST_CLOCK_TIME_NONE,
|
GST_DVD_NAV_SRC_PAUSE_INTERVAL);
|
||||||
MIN (src->pause_remain, DVD_NAV_SRC_PAUSE_INTERVAL));
|
GstClock *system_clock = gst_system_clock_obtain ();
|
||||||
send_data = GST_DATA (event);
|
GstClockTime cur_time = gst_clock_get_internal_time (system_clock);
|
||||||
|
GstClockID id =
|
||||||
|
gst_clock_new_single_shot_id (system_clock,
|
||||||
|
cur_time + GST_DVD_NAV_SRC_PAUSE_INTERVAL);
|
||||||
|
gst_clock_id_wait (id, NULL);
|
||||||
|
gst_clock_id_unref (id);
|
||||||
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src,
|
|
||||||
"Pause mode %d, Sending filler at %" G_GUINT64_FORMAT
|
|
||||||
", dur %" G_GINT64_FORMAT ", remain %" G_GINT64_FORMAT,
|
|
||||||
src->pause_mode, gst_element_get_time (GST_ELEMENT (src)),
|
|
||||||
MIN (src->pause_remain, DVD_NAV_SRC_PAUSE_INTERVAL),
|
|
||||||
src->pause_remain);
|
|
||||||
#endif
|
|
||||||
if (src->pause_mode == GST_DVD_NAV_SRC_PAUSE_LIMITED) {
|
if (src->pause_mode == GST_DVD_NAV_SRC_PAUSE_LIMITED) {
|
||||||
if (src->pause_remain < GST_DVD_NAV_SRC_PAUSE_INTERVAL)
|
if (src->pause_remain < GST_DVD_NAV_SRC_PAUSE_INTERVAL)
|
||||||
src->pause_remain = 0;
|
src->pause_remain = 0;
|
||||||
|
@ -1324,7 +1700,6 @@ gst_dvd_nav_src_process_next_block (GstDvdNavSrc * src, GstBuffer ** p_buf)
|
||||||
* advancing */
|
* advancing */
|
||||||
if (src->pause_mode == GST_DVD_NAV_SRC_PAUSE_UNLIMITED ||
|
if (src->pause_mode == GST_DVD_NAV_SRC_PAUSE_UNLIMITED ||
|
||||||
src->pause_remain > 0)
|
src->pause_remain > 0)
|
||||||
src->did_seek = TRUE;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1334,8 +1709,8 @@ gst_dvd_nav_src_process_next_block (GstDvdNavSrc * src, GstBuffer ** p_buf)
|
||||||
GST_WARNING_OBJECT (src, "dvdnav_still_skip failed: %s",
|
GST_WARNING_OBJECT (src, "dvdnav_still_skip failed: %s",
|
||||||
dvdnav_err_to_string (src->dvdnav));
|
dvdnav_err_to_string (src->dvdnav));
|
||||||
}
|
}
|
||||||
/* Schedule a discont to reset the time */
|
/* Flush to ensure that data after the wait is played correctly */
|
||||||
src->did_seek = TRUE;
|
src->need_flush = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1380,7 +1755,20 @@ gst_dvd_nav_src_process_next_block (GstDvdNavSrc * src, GstBuffer ** p_buf)
|
||||||
" cell_start %" GST_TIME_FORMAT ", pg_start %" GST_TIME_FORMAT,
|
" cell_start %" GST_TIME_FORMAT ", pg_start %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (src->pgc_length),
|
GST_TIME_ARGS (src->pgc_length),
|
||||||
GST_TIME_ARGS (src->cell_start), GST_TIME_ARGS (src->pg_start));
|
GST_TIME_ARGS (src->cell_start), GST_TIME_ARGS (src->pg_start));
|
||||||
|
|
||||||
|
/* Update the current length in sectors */
|
||||||
|
guint32 pos;
|
||||||
|
|
||||||
|
if (dvdnav_get_position (src->dvdnav, &pos,
|
||||||
|
&src->sector_length) != DVDNAV_STATUS_OK)
|
||||||
|
GST_WARNING_OBJECT (src,
|
||||||
|
"Cannot get new stream length after DVDNAV_CELL_CHANGE");
|
||||||
|
|
||||||
|
/* Update the time maps */
|
||||||
|
gst_dvd_nav_src_update_tmaps (src);
|
||||||
|
|
||||||
gst_dvd_nav_src_update_streaminfo (src);
|
gst_dvd_nav_src_update_streaminfo (src);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DVDNAV_NAV_PACKET:{
|
case DVDNAV_NAV_PACKET:{
|
||||||
|
@ -1399,11 +1787,16 @@ gst_dvd_nav_src_process_next_block (GstDvdNavSrc * src, GstBuffer ** p_buf)
|
||||||
|
|
||||||
/* Send a dvd nav packet event. */
|
/* Send a dvd nav packet event. */
|
||||||
gst_dvd_nav_src_push_dvd_nav_packet_event (src, pci);
|
gst_dvd_nav_src_push_dvd_nav_packet_event (src, pci);
|
||||||
|
|
||||||
|
/* The NAV packet contains also data, so send it */
|
||||||
|
*p_buf = src->cur_buf;
|
||||||
|
src->cur_buf = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DVDNAV_SPU_CLUT_CHANGE:{
|
case DVDNAV_SPU_CLUT_CHANGE:{
|
||||||
/* FIXME: does this work on 64-bit/big-endian machines? (tpm) */
|
/* Does this work on 64-bit/big-endian machines? (tpm) -
|
||||||
gst_dvd_nav_src_push_clut_change_event (src, (guint *) data);
|
* Should do! (jan) */
|
||||||
|
gst_dvd_nav_src_push_clut_change_event (src, (const guint32 *) data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DVDNAV_VTS_CHANGE:{
|
case DVDNAV_VTS_CHANGE:{
|
||||||
|
@ -1506,6 +1899,8 @@ gst_dvd_nav_src_process_next_block (GstDvdNavSrc * src, GstBuffer ** p_buf)
|
||||||
|
|
||||||
src->button = 0;
|
src->button = 0;
|
||||||
src->pause_mode = GST_DVD_NAV_SRC_PAUSE_OFF;
|
src->pause_mode = GST_DVD_NAV_SRC_PAUSE_OFF;
|
||||||
|
/* If seeking the flush is already sent by the basesrc parent class */
|
||||||
|
if (!src->seek_pending)
|
||||||
src->need_flush = TRUE;
|
src->need_flush = TRUE;
|
||||||
/* was commented out already: */
|
/* was commented out already: */
|
||||||
/* send_data = GST_DATA (gst_event_new_flush ()); */
|
/* send_data = GST_DATA (gst_event_new_flush ()); */
|
||||||
|
@ -1550,36 +1945,10 @@ gst_dvd_nav_src_create (GstPushSrc * pushsrc, GstBuffer ** p_buf)
|
||||||
GST_INFO_OBJECT (src, "sending flush");
|
GST_INFO_OBJECT (src, "sending flush");
|
||||||
gst_pad_push_event (GST_BASE_SRC_PAD (src), gst_event_new_flush_start ());
|
gst_pad_push_event (GST_BASE_SRC_PAD (src), gst_event_new_flush_start ());
|
||||||
gst_pad_push_event (GST_BASE_SRC_PAD (src), gst_event_new_flush_stop ());
|
gst_pad_push_event (GST_BASE_SRC_PAD (src), gst_event_new_flush_stop ());
|
||||||
|
|
||||||
gst_dvd_nav_src_update_highlight (src, TRUE);
|
gst_dvd_nav_src_update_highlight (src, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src->pause_mode == GST_DVD_NAV_SRC_PAUSE_OFF) {
|
|
||||||
/* FIXME */
|
|
||||||
if (src->did_seek) {
|
|
||||||
GstEvent *event;
|
|
||||||
|
|
||||||
src->did_seek = FALSE;
|
|
||||||
GST_INFO_OBJECT (src, "sending newsegment event with offset %"
|
|
||||||
G_GINT64_FORMAT, src->pending_offset);
|
|
||||||
|
|
||||||
if (src->pending_offset != -1) {
|
|
||||||
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
|
|
||||||
src->pending_offset, -1, src->pending_offset);
|
|
||||||
src->pending_offset = -1;
|
|
||||||
} else {
|
|
||||||
/* g_warning ("dvdnav: FIXME - what newsegment to send here?"); */
|
|
||||||
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
|
|
||||||
0, -1, 0);
|
|
||||||
/* was: gst_event_new_discontinuous (FALSE, GST_FORMAT_UNDEFINED); */
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_pad_push_event (GST_BASE_SRC_PAD (src), event);
|
|
||||||
|
|
||||||
/* Sent a discont, make sure to enable highlight */
|
|
||||||
src->button = 0;
|
|
||||||
gst_dvd_nav_src_update_highlight (src, TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = gst_dvd_nav_src_process_next_block (src, p_buf);
|
ret = gst_dvd_nav_src_process_next_block (src, p_buf);
|
||||||
}
|
}
|
||||||
while (ret == GST_FLOW_OK && *p_buf == NULL);
|
while (ret == GST_FLOW_OK && *p_buf == NULL);
|
||||||
|
@ -1601,6 +1970,22 @@ gst_dvd_nav_src_start (GstBaseSrc * basesrc)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load the video manager to find out the information about the titles */
|
||||||
|
src->dvd = DVDOpen (src->device);
|
||||||
|
if (!src->dvd)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (src, "Loading VMG info");
|
||||||
|
|
||||||
|
if (!(src->vmg_file = ifoOpen (src->dvd, 0))) {
|
||||||
|
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||||
|
(_("Could not open DVD")),
|
||||||
|
("ifoOpen() failed: %s", g_strerror (errno)));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
src->tt_srpt = src->vmg_file->tt_srpt;
|
||||||
|
|
||||||
if (dvdnav_open (&src->dvdnav, src->device) != DVDNAV_STATUS_OK) {
|
if (dvdnav_open (&src->dvdnav, src->device) != DVDNAV_STATUS_OK) {
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
|
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
|
||||||
(_("Failed to open DVD device '%s'."), src->device));
|
(_("Failed to open DVD device '%s'."), src->device));
|
||||||
|
@ -1664,7 +2049,8 @@ gst_dvd_nav_src_start (GstBaseSrc * basesrc)
|
||||||
}
|
}
|
||||||
|
|
||||||
src->streaminfo = NULL;
|
src->streaminfo = NULL;
|
||||||
src->did_seek = TRUE;
|
src->use_tmaps = FALSE;
|
||||||
|
src->first_seek = TRUE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1680,6 +2066,15 @@ gst_dvd_nav_src_stop (GstBaseSrc * basesrc)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Close old vts file if opened */
|
||||||
|
if (src->vts_file)
|
||||||
|
ifoClose (src->vts_file);
|
||||||
|
|
||||||
|
/* Close the video manager */
|
||||||
|
ifoClose (src->vmg_file);
|
||||||
|
|
||||||
|
DVDClose (src->dvd);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1726,7 +2121,6 @@ gst_dvd_nav_src_handle_navigation_event (GstDvdNavSrc * src, GstEvent * event)
|
||||||
if (dvdnav_current_title_info (src->dvdnav, &title, &part) && title > 0
|
if (dvdnav_current_title_info (src->dvdnav, &title, &part) && title > 0
|
||||||
&& part > 1) {
|
&& part > 1) {
|
||||||
dvdnav_part_play (src->dvdnav, title, part - 1);
|
dvdnav_part_play (src->dvdnav, title, part - 1);
|
||||||
src->did_seek = TRUE;
|
|
||||||
}
|
}
|
||||||
} else if (g_str_equal (key, "period")) {
|
} else if (g_str_equal (key, "period")) {
|
||||||
gint title = 0;
|
gint title = 0;
|
||||||
|
@ -1734,7 +2128,6 @@ gst_dvd_nav_src_handle_navigation_event (GstDvdNavSrc * src, GstEvent * event)
|
||||||
|
|
||||||
if (dvdnav_current_title_info (src->dvdnav, &title, &part) && title > 0) {
|
if (dvdnav_current_title_info (src->dvdnav, &title, &part) && title > 0) {
|
||||||
dvdnav_part_play (src->dvdnav, title, part + 1);
|
dvdnav_part_play (src->dvdnav, title, part + 1);
|
||||||
src->did_seek = TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1763,11 +2156,73 @@ gst_dvd_nav_src_handle_navigation_event (GstDvdNavSrc * src, GstEvent * event)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: handle also angle format */
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_dvd_nav_src_handle_seek_event (GstDvdNavSrc * src, GstEvent * event)
|
gst_dvd_nav_src_handle_seek_event (GstDvdNavSrc * src, GstEvent * event)
|
||||||
{
|
{
|
||||||
/* FIXME: */
|
GstSeekFlags flags;
|
||||||
|
GstSeekType cur_type, end_type;
|
||||||
|
gint64 new_off;
|
||||||
|
GstFormat format;
|
||||||
|
gdouble rate;
|
||||||
|
|
||||||
|
gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &new_off,
|
||||||
|
&end_type, NULL);
|
||||||
|
|
||||||
|
/* Cannot seek during another seek */
|
||||||
|
if (src->seek_pending) {
|
||||||
|
GST_WARNING_OBJECT (src, "Cannot seek during another seek");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we are in a still frame we cannot seek */
|
||||||
|
if (src->still_frame) {
|
||||||
|
GST_WARNING_OBJECT (src, "Cannot seek during a still frame");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rate <= 0.0) {
|
||||||
|
GST_DEBUG_OBJECT (src, "cannot do backwards playback yet");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & GST_SEEK_FLAG_SEGMENT) != 0) {
|
||||||
|
GST_DEBUG_OBJECT (src, "segment seek not supported");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & GST_SEEK_FLAG_FLUSH) == 0) {
|
||||||
|
GST_DEBUG_OBJECT (src, "can only do flushing seeks at the moment");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end_type != GST_SEEK_TYPE_NONE) {
|
||||||
|
GST_DEBUG_OBJECT (src, "end seek type not supported");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur_type != GST_SEEK_TYPE_SET) {
|
||||||
|
GST_DEBUG_OBJECT (src, "only SEEK_TYPE_SET is supported");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format != chapter_format && format != title_format &&
|
||||||
|
format != GST_FORMAT_BYTES && format != GST_FORMAT_TIME) {
|
||||||
|
GST_DEBUG_OBJECT (src, "unsupported seek format %d (%s)", format,
|
||||||
|
gst_format_get_name (format));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
src->seek_pending = TRUE;
|
||||||
|
|
||||||
|
return GST_BASE_SRC_CLASS (parent_class)->event (GST_BASE_SRC (src), event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: please remove me, I use disk space without a reason. thanks. */
|
||||||
#if 0
|
#if 0
|
||||||
|
static gboolean
|
||||||
|
gst_dvd_nav_src_handle_seek_event (GstDvdNavSrc * src, GstEvent * event)
|
||||||
|
{
|
||||||
gint64 offset;
|
gint64 offset;
|
||||||
gint format;
|
gint format;
|
||||||
int titles, title, new_title;
|
int titles, title, new_title;
|
||||||
|
@ -1914,9 +2369,9 @@ gst_dvd_nav_src_handle_seek_event (GstDvdNavSrc * src, GstEvent * event)
|
||||||
error:
|
error:
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src, "seek failed");
|
GST_DEBUG_OBJECT (src, "seek failed");
|
||||||
#endif
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_dvd_nav_src_src_event (GstBaseSrc * basesrc, GstEvent * event)
|
gst_dvd_nav_src_src_event (GstBaseSrc * basesrc, GstEvent * event)
|
||||||
|
@ -1964,6 +2419,16 @@ gst_dvd_nav_src_query_position (GstDvdNavSrc * src, GstFormat format,
|
||||||
} else if (format == GST_FORMAT_BYTES) {
|
} else if (format == GST_FORMAT_BYTES) {
|
||||||
if (dvdnav_get_position (src->dvdnav, &pos, &len) == DVDNAV_STATUS_OK)
|
if (dvdnav_get_position (src->dvdnav, &pos, &len) == DVDNAV_STATUS_OK)
|
||||||
*p_val = (gint64) pos *DVD_SECTOR_SIZE;
|
*p_val = (gint64) pos *DVD_SECTOR_SIZE;
|
||||||
|
} else if (format == GST_FORMAT_TIME) {
|
||||||
|
if (dvdnav_get_position (src->dvdnav, &pos, &len) == DVDNAV_STATUS_OK)
|
||||||
|
*p_val = (gint64) gst_dvd_nav_src_get_time_for_sector (src, pos);
|
||||||
|
/* libdvnav from svn at at least 20070503 provide this new function
|
||||||
|
* dvdnav_get_current_time, I used it just to test that the values
|
||||||
|
* provided by the timemap were rights but I won't use it as the values
|
||||||
|
* it return changes only every ~0.5 seconds or less depending on how
|
||||||
|
* much sectors are contained in a cell.
|
||||||
|
*p_val = dvdnav_get_current_time(src->dvdnav) * GST_SECOND / 90000;
|
||||||
|
*/
|
||||||
} else if (format == title_format) {
|
} else if (format == title_format) {
|
||||||
if (dvdnav_current_title_info (src->dvdnav, &title, &x) == DVDNAV_STATUS_OK)
|
if (dvdnav_current_title_info (src->dvdnav, &title, &x) == DVDNAV_STATUS_OK)
|
||||||
*p_val = title;
|
*p_val = title;
|
||||||
|
@ -2041,6 +2506,10 @@ gst_dvd_nav_src_query (GstBaseSrc * basesrc, GstQuery * query)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GST_QUERY_CONVERT:{
|
||||||
|
res = gst_dvd_nav_src_do_convert_query (src, query);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:{
|
default:{
|
||||||
res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
|
res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
|
||||||
break;
|
break;
|
||||||
|
@ -2176,7 +2645,7 @@ gst_dvd_nav_src_do_init (GType dvdnavsrc_type)
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_init (GstPlugin * plugin)
|
plugin_init (GstPlugin * plugin)
|
||||||
{
|
{
|
||||||
if (!gst_element_register (plugin, "dvdnavsrc", GST_RANK_NONE,
|
if (!gst_element_register (plugin, "dvdnavsrc", GST_RANK_PRIMARY,
|
||||||
/* GST_RANK_PRIMARY + 1, */ GST_TYPE_DVD_NAV_SRC)) {
|
/* GST_RANK_PRIMARY + 1, */ GST_TYPE_DVD_NAV_SRC)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,10 +66,12 @@ struct _GstDvdNavSrc
|
||||||
gchar *last_uri;
|
gchar *last_uri;
|
||||||
|
|
||||||
gint64 pending_offset; /* Next newsegment event offset */
|
gint64 pending_offset; /* Next newsegment event offset */
|
||||||
gboolean did_seek;
|
|
||||||
gboolean new_seek;
|
gboolean new_seek;
|
||||||
gboolean seek_pending;
|
gboolean seek_pending;
|
||||||
gboolean need_flush;
|
gboolean need_flush;
|
||||||
|
gboolean first_seek;
|
||||||
|
gboolean use_tmaps;
|
||||||
|
gboolean still_frame;
|
||||||
|
|
||||||
/* Timing */
|
/* Timing */
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -123,6 +125,15 @@ struct _GstDvdNavSrc
|
||||||
GArray *vts_attrs; /* Array of vts_attributes_t *
|
GArray *vts_attrs; /* Array of vts_attributes_t *
|
||||||
* structures cached from *
|
* structures cached from *
|
||||||
* the VMG ifo */
|
* the VMG ifo */
|
||||||
|
guint32 sector_length;
|
||||||
|
|
||||||
|
dvd_reader_t *dvd;
|
||||||
|
ifo_handle_t *vmg_file;
|
||||||
|
tt_srpt_t *tt_srpt;
|
||||||
|
vts_ptt_srpt_t *vts_ptt_srpt;
|
||||||
|
ifo_handle_t *vts_file;
|
||||||
|
vts_tmapt_t *vts_tmapt;
|
||||||
|
vts_tmap_t *title_tmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstDvdNavSrcClass
|
struct _GstDvdNavSrcClass
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
AUDIOSINK=`gconftool-2 -g /system/gstreamer/0.8/default/audiosink`
|
AUDIOSINK=`gconftool-2 -g /system/gstreamer/0.10/default/audiosink`
|
||||||
VIDEOSINK=`gconftool-2 -g /system/gstreamer/0.8/default/videosink`
|
VIDEOSINK=`gconftool-2 -g /system/gstreamer/0.10/default/videosink`
|
||||||
gst-launch dvdnavsrc ! dvddemux name=demux .current_video ! { queue max-size-buffers=10 ! mpeg2dec ! mpeg2subt name=sub ! \
|
gst-launch dvdnavsrc ! dvddemux name=demux multiqueue name=mq \
|
||||||
navseek ! $VIDEOSINK } demux.current_subpicture ! queue max-size-buffers=5 block-timeout=100000 ! sub.subtitle \
|
demux.current_video ! mq.sink0 mq.src0 ! mpeg2dec ! dvdspu name=sub ! \
|
||||||
demux.current_audio ! { queue ! a52dec ! audioconvert ! audioscale ! $AUDIOSINK } $@
|
navseek ! ffmpegcolorspace ! videoscale ! $VIDEOSINK \
|
||||||
|
demux.current_subpicture ! mq.sink1 mq.src1 ! sub.subpicture \
|
||||||
|
demux.current_audio ! mq.sink2 mq.src2 ! a52dec ! audioconvert ! audioresample ! $AUDIOSINK $@
|
||||||
|
|
Loading…
Reference in a new issue