diff options
author | Jan Schmidt <thaytan@mad.scientist.com> | 2009-01-08 12:42:18 +0000 |
---|---|---|
committer | Jan Schmidt <thaytan@mad.scientist.com> | 2009-01-08 12:42:18 +0000 |
commit | 672051c5eb79ca9acaa6f2d056322d2ad0f3ea31 (patch) | |
tree | 1555e14719db3e7ed20f54d7b428c53df8a572f1 /ext | |
parent | acd634eafa71e5688ba707962612357470f6c97c (diff) | |
download | gst-plugins-bad-672051c5eb79ca9acaa6f2d056322d2ad0f3ea31.tar.gz gst-plugins-bad-672051c5eb79ca9acaa6f2d056322d2ad0f3ea31.tar.bz2 gst-plugins-bad-672051c5eb79ca9acaa6f2d056322d2ad0f3ea31.zip |
ext/resindvd/: Add support for time based seeking.
Original commit message from CVS:
* ext/resindvd/resindvdbin.c:
* ext/resindvd/resindvdsrc.c:
* ext/resindvd/resindvdsrc.h:
* ext/resindvd/rsnaudiomunge.c:
Add support for time based seeking.
Make setting dvd:// reset to the default device.
Make the 'audiomunge' element send any new segment start before
the 'gap filler' buffer it generates, and any segment closes
after.
Fixes: #566957
Diffstat (limited to 'ext')
-rw-r--r-- | ext/resindvd/resindvdbin.c | 5 | ||||
-rw-r--r-- | ext/resindvd/resindvdsrc.c | 91 | ||||
-rw-r--r-- | ext/resindvd/resindvdsrc.h | 1 | ||||
-rw-r--r-- | ext/resindvd/rsnaudiomunge.c | 22 |
4 files changed, 108 insertions, 11 deletions
diff --git a/ext/resindvd/resindvdbin.c b/ext/resindvd/resindvdbin.c index ac50fb14..c96ff944 100644 --- a/ext/resindvd/resindvdbin.c +++ b/ext/resindvd/resindvdbin.c @@ -230,7 +230,10 @@ rsn_dvdbin_uri_set_uri (GstURIHandler * handler, const gchar * uri) */ if (g_str_has_prefix (uri, "dvd://")) { g_free (dvdbin->device); - dvdbin->device = g_strdup (uri + 6); + if (strlen (uri) > 6) + dvdbin->device = g_strdup (uri + 6); + else + dvdbin->device = g_strdup (DEFAULT_DEVICE); } #if 0 /* diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 2c742120..5844bb72 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -337,6 +337,14 @@ rsn_dvdsrc_start (RsnBaseSrc * bsrc) goto fail; } + if (dvdnav_set_PGC_positioning_flag (src->dvdnav, 1) != DVDNAV_STATUS_OK) { + GST_ELEMENT_ERROR (src, LIBRARY, FAILED, + (_("Failed to set PGC based seeking.")), GST_ERROR_SYSTEM); + goto fail; + } + + + src->first_seek = TRUE; src->running = TRUE; src->branching = FALSE; src->discont = TRUE; @@ -767,10 +775,16 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock) case DVDNAV_VTS_CHANGE:{ dvdnav_vts_change_event_t *event = (dvdnav_vts_change_event_t *) data; - if (dvdnav_is_domain_vmgm (src->dvdnav)) + if (dvdnav_is_domain_vmgm (src->dvdnav)) { src->vts_n = 0; - else + } else { src->vts_n = event->new_vtsN; + if (src->vts_file) { + ifoClose (src->vts_file); + src->vts_file = NULL; + } + src->vts_file = ifoOpen (src->dvdread, src->vts_n); + } src->in_menu = !dvdnav_is_domain_vtsm (src->dvdnav); @@ -1873,23 +1887,90 @@ rsn_dvdsrc_prepare_seek (RsnBaseSrc * bsrc, GstEvent * event, event, segment); } +/* Find sector from time using time map if available */ +static gint +rsn_dvdsrc_get_sector_from_time_tmap (resinDvdSrc * src, GstClockTime ts) +{ + vts_tmapt_t *vts_tmapt; + vts_tmap_t *title_tmap; + gint32 title, part, vts_ttn; + guint32 entry; + + if (ts == 0) + return 0; + + if (src->vts_file == NULL) + return -1; + + if (dvdnav_current_title_info (src->dvdnav, &title, &part) != + DVDNAV_STATUS_OK) + return -1; + + /* To find the right tmap, we need the title number within this VTS (vts_ttn) + * from the VMG tt_srpt table... */ + if (title < 1 || title >= src->vmg_file->tt_srpt->nr_of_srpts) + return -1; + + vts_tmapt = src->vts_file->vts_tmapt; + if (vts_tmapt == NULL) + return -1; + + vts_ttn = src->vmg_file->tt_srpt->title[title - 1].vts_ttn; + + if (vts_ttn < 1 || vts_ttn > vts_tmapt->nr_of_tmaps) + return -1; + + title_tmap = vts_tmapt->tmap + vts_ttn - 1; + entry = ts / (title_tmap->tmu * GST_SECOND); + + if (entry < title_tmap->nr_of_entries) + return title_tmap->map_ent[entry] & 0x7fffffff; + + return -1; +} + +/* call with DVD lock held */ +static gboolean +rsn_dvdsrc_seek_to_time (resinDvdSrc * src, GstClockTime ts) +{ + gint sector; + dvdnav_status_t res; + + GST_DEBUG_OBJECT (src, "Time seek requested to ts %" GST_TIME_FORMAT, + GST_TIME_ARGS (ts)); + + sector = rsn_dvdsrc_get_sector_from_time_tmap (src, ts); + if (sector < 0) + return FALSE; + + src->discont = TRUE; + res = dvdnav_sector_search (src->dvdnav, sector, SEEK_SET); + + if (res != DVDNAV_STATUS_OK) + return FALSE; + + return TRUE; +} + static gboolean rsn_dvdsrc_do_seek (RsnBaseSrc * bsrc, GstSegment * segment) { resinDvdSrc *src = RESINDVDSRC (bsrc); gboolean ret = FALSE; - if (segment->format == rsndvd_format) { + if (segment->format == rsndvd_format || src->first_seek) { /* The internal format has alread served its purpose of waking * everything up and flushing, we just need to step to the next * data block (below) so we know our new position */ ret = TRUE; + src->first_seek = FALSE; } else { /* FIXME: Handle other formats: Time, title, chapter, angle */ /* HACK to make initial seek work: */ if (segment->format == GST_FORMAT_TIME) { - ret = TRUE; - src->discont = TRUE; + g_mutex_lock (src->dvd_lock); + ret = rsn_dvdsrc_seek_to_time (src, segment->start); + g_mutex_unlock (src->dvd_lock); } else if (segment->format == title_format) { gint titles; diff --git a/ext/resindvd/resindvdsrc.h b/ext/resindvd/resindvdsrc.h index ae88b134..9bd53413 100644 --- a/ext/resindvd/resindvdsrc.h +++ b/ext/resindvd/resindvdsrc.h @@ -85,6 +85,7 @@ struct _resinDvdSrc gboolean running; gboolean discont; + gboolean first_seek; gboolean flushing_seek; gboolean need_segment; gboolean active_highlight; diff --git a/ext/resindvd/rsnaudiomunge.c b/ext/resindvd/rsnaudiomunge.c index 457be163..500671c8 100644 --- a/ext/resindvd/rsnaudiomunge.c +++ b/ext/resindvd/rsnaudiomunge.c @@ -311,6 +311,15 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event) * Otherwise, send the buffer before the newsegment, so that it appears * in the closing segment. */ + if (!update) { + GST_DEBUG_OBJECT (munge, "Sending newsegment: start %" GST_TIME_FORMAT + " stop %" GST_TIME_FORMAT " accum now %" GST_TIME_FORMAT, + GST_TIME_ARGS (start), GST_TIME_ARGS (stop), + GST_TIME_ARGS (segment->accum)); + + ret = gst_pad_push_event (munge->srcpad, event); + } + if (segment->accum >= AUDIO_FILL_THRESHOLD || munge->in_still) { g_print ("*********** Sending audio fill: accum = %" GST_TIME_FORMAT " still-state=%d\n", GST_TIME_ARGS (segment->accum), @@ -326,12 +335,15 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event) GST_TIME_ARGS (segment->accum)); } - GST_DEBUG_OBJECT (munge, "Sending newsegment: start %" GST_TIME_FORMAT - " stop %" GST_TIME_FORMAT " accum now %" GST_TIME_FORMAT, - GST_TIME_ARGS (start), GST_TIME_ARGS (stop), - GST_TIME_ARGS (segment->accum)); + if (update) { + GST_DEBUG_OBJECT (munge, "Sending newsegment: start %" GST_TIME_FORMAT + " stop %" GST_TIME_FORMAT " accum now %" GST_TIME_FORMAT, + GST_TIME_ARGS (start), GST_TIME_ARGS (stop), + GST_TIME_ARGS (segment->accum)); + + ret = gst_pad_push_event (munge->srcpad, event); + } - ret = gst_pad_push_event (munge->srcpad, event); break; } case GST_EVENT_CUSTOM_DOWNSTREAM: |