From: <tp...@ke...> - 2006-08-06 19:47:52
|
CVS Root: /cvs/gstreamer Module: gst-plugins-ugly Changes by: tpm Date: Sun Aug 06 2006 19:47:52 UTC Log message: * ext/dvdread/dvdreadsrc.c: (gst_dvd_read_src_stop), (gst_dvd_read_src_goto_chapter), (gst_dvd_read_src_get_chapter_starts), (gst_dvd_read_src_goto_title), (gst_dvd_read_src_get_next_cell), (gst_dvd_read_src_get_time_for_sector), (gst_dvd_read_src_get_sector_from_time), (gst_dvd_read_src_read), (gst_dvd_read_src_handle_seek_event), (gst_dvd_read_src_do_seek), (gst_dvd_read_src_goto_sector): * ext/dvdread/dvdreadsrc.h: Add basic support for time-based seeking; set timestamps on outgoing buffers if we have them; create table with chapter to time mapping when opening a title; rename gst_dvd_read_src_get_next_cell_for() to _get_next_cell() and make it take an explicit pgc argument; fix up some debugging messages so that title/chapter numbers are printed as starting from 1 for easier readability. Modified files: . : ChangeLog ext/dvdread : dvdreadsrc.c dvdreadsrc.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-ugly/ChangeLog.diff?r1=1.2075&r2=1.2076 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-ugly/ext/dvdread/dvdreadsrc.c.diff?r1=1.39&r2=1.40 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-ugly/ext/dvdread/dvdreadsrc.h.diff?r1=1.10&r2=1.11 ====Begin Diffs==== Index: ChangeLog =================================================================== RCS file: /cvs/gstreamer/gst-plugins-ugly/ChangeLog,v retrieving revision 1.2075 retrieving revision 1.2076 diff -u -d -r1.2075 -r1.2076 --- ChangeLog 4 Aug 2006 13:05:01 -0000 1.2075 +++ ChangeLog 6 Aug 2006 19:47:39 -0000 1.2076 @@ -1,3 +1,22 @@ +2006-08-06 Tim-Philipp Müller <tim at centricular dot net> + + * ext/dvdread/dvdreadsrc.c: (gst_dvd_read_src_stop), + (gst_dvd_read_src_goto_chapter), + (gst_dvd_read_src_get_chapter_starts), + (gst_dvd_read_src_goto_title), (gst_dvd_read_src_get_next_cell), + (gst_dvd_read_src_get_time_for_sector), + (gst_dvd_read_src_get_sector_from_time), (gst_dvd_read_src_read), + (gst_dvd_read_src_handle_seek_event), (gst_dvd_read_src_do_seek), + (gst_dvd_read_src_goto_sector): + * ext/dvdread/dvdreadsrc.h: + Add basic support for time-based seeking; set timestamps on + outgoing buffers if we have them; create table with + chapter to time mapping when opening a title; rename + gst_dvd_read_src_get_next_cell_for() to _get_next_cell() and + make it take an explicit pgc argument; fix up some debugging + messages so that title/chapter numbers are printed as starting + from 1 for easier readability. 2006-08-04 Tim-Philipp Müller <tim at centricular dot net> * gst/realmedia/Makefile.am: Index: dvdreadsrc.c RCS file: /cvs/gstreamer/gst-plugins-ugly/ext/dvdread/dvdreadsrc.c,v retrieving revision 1.39 retrieving revision 1.40 diff -u -d -r1.39 -r1.40 --- dvdreadsrc.c 29 Jul 2006 11:20:30 -0000 1.39 +++ dvdreadsrc.c 6 Aug 2006 19:47:40 -0000 1.40 @@ -1,6 +1,7 @@ -/* GStreamer +/* GStreamer DVD title source * Copyright (C) 1999 Erik Walthinsen <om...@cs...> * Copyright (C) 2001 Billy Biggs <ve...@du...>. + * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -86,6 +87,13 @@ const guint * clut); static gboolean gst_dvd_read_src_get_size (GstDvdReadSrc * src, gint64 * size); static gboolean gst_dvd_read_src_do_seek (GstBaseSrc * src, GstSegment * s); +static gint64 gst_dvd_read_src_convert_timecode (dvd_time_t * time); +static gint gst_dvd_read_src_get_next_cell (GstDvdReadSrc * src, + pgc_t * pgc, gint cell); +static GstClockTime gst_dvd_read_src_get_time_for_sector (GstDvdReadSrc * src, + guint sector); +static gint gst_dvd_read_src_get_sector_from_time (GstDvdReadSrc * src, + GstClockTime ts); GST_BOILERPLATE_FULL (GstDvdReadSrc, gst_dvd_read_src, GstPushSrc, GST_TYPE_PUSH_SRC, gst_dvd_read_src_do_init); @@ -270,6 +278,7 @@ src->chapter = 0; src->title = 0; src->need_newsegment = TRUE; + src->vts_tmapt = NULL; if (src->title_lang_event_pending) { gst_event_unref (src->title_lang_event_pending); src->title_lang_event_pending = NULL; @@ -278,6 +287,10 @@ gst_event_unref (src->pending_clut_event); src->pending_clut_event = NULL; } + if (src->chapter_starts) { + g_free (src->chapter_starts); + src->chapter_starts = NULL; + } GST_LOG_OBJECT (src, "closed DVD"); @@ -342,7 +355,7 @@ cur_title_get_chapter_bounds (src, chapter, &src->start_cell, &src->last_cell); - GST_LOG_OBJECT (src, "Opened chapter %d - cell %d-%d", chapter, + GST_LOG_OBJECT (src, "Opened chapter %d - cell %d-%d", chapter + 1, src->start_cell, src->last_cell); /* retrieve position */ @@ -375,6 +388,45 @@ return TRUE; } +static void +gst_dvd_read_src_get_chapter_starts (GstDvdReadSrc * src) +{ + GstClockTime uptohere; + guint c; + g_free (src->chapter_starts); + src->chapter_starts = g_new (GstClockTime, src->num_chapters); + uptohere = (GstClockTime) 0; + for (c = 0; c < src->num_chapters; ++c) { + GstClockTime chapter_duration = 0; + gint cell_start, cell_end, cell; + gint pgn, pgc_id; + pgc_t *pgc; + cur_title_get_chapter_pgc (src, c, &pgn, &pgc_id, &pgc); + cur_title_get_chapter_bounds (src, c, &cell_start, &cell_end); + cell = cell_start; + while (cell < cell_end) { + dvd_time_t *cell_duration; + cell_duration = &pgc->cell_playback[cell].playback_time; + chapter_duration += gst_dvd_read_src_convert_timecode (cell_duration); + cell = gst_dvd_read_src_get_next_cell (src, pgc, cell); + } + src->chapter_starts[c] = uptohere; + GST_INFO_OBJECT (src, "[%02u] Chapter %02u starts at %" GST_TIME_FORMAT + ", dur = %" GST_TIME_FORMAT ", cells %d-%d", src->title + 1, c + 1, + GST_TIME_ARGS (uptohere), GST_TIME_ARGS (chapter_duration), + cell_start, cell_end); + uptohere += chapter_duration; +} static gboolean gst_dvd_read_src_goto_title (GstDvdReadSrc * src, gint title, gint angle) { @@ -391,11 +443,12 @@ goto invalid_title; src->num_chapters = src->tt_srpt->title[title].nr_of_ptts; - GST_INFO_OBJECT (src, "Title %d has %d chapters", title, src->num_chapters); + GST_INFO_OBJECT (src, "Title %d has %d chapters", title + 1, + src->num_chapters); /* make sure the angle number is valid for this title */ src->num_angles = src->tt_srpt->title[title].nr_of_angles; - GST_LOG_OBJECT (src, "Title %d has %d angles", title, src->num_angles); + GST_LOG_OBJECT (src, "Title %d has %d angles", title + 1, src->num_angles); if (angle < 0 || angle >= src->num_angles) { GST_WARNING_OBJECT (src, "Invalid angle %d (only %d available)", angle, src->num_angles); @@ -416,7 +469,7 @@ if (src->dvd_title == NULL) goto title_open_failed; - GST_INFO_OBJECT (src, "Opened title %d, angle %d", title, angle); + GST_INFO_OBJECT (src, "Opened title %d, angle %d", title + 1, angle); src->title = title; src->angle = angle; @@ -449,7 +502,7 @@ } GST_INFO_OBJECT (src, "[%02d] Audio %02d: lang='%s', format=%d", - src->title, i, lang_code, (gint) a->audio_format); + src->title + 1, i, lang_code, (gint) a->audio_format); /* subtitle */ @@ -467,12 +520,42 @@ GST_INFO_OBJECT (src, "[%02d] Subtitle %02d: lang='%s', format=%d", - src->title, i, lang_code); + src->title + 1, i, lang_code); src->title_lang_event_pending = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s); + /* dump seek tables */ + src->vts_tmapt = src->vts_file->vts_tmapt; + 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: 0x%08x %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_WARNING_OBJECT (src, "no vts_tmapt - seeking will suck"); + gst_dvd_read_src_get_chapter_starts (src); /* ERRORS */ @@ -500,13 +583,13 @@ /* FIXME: double-check this function, compare against original */ static gint -gst_dvd_read_src_get_next_cell_for (GstDvdReadSrc * src, gint cell) +gst_dvd_read_src_get_next_cell (GstDvdReadSrc * src, pgc_t * pgc, gint cell) /* Check if we're entering an angle block. */ - if (src->cur_pgc->cell_playback[cell].block_type != BLOCK_TYPE_ANGLE_BLOCK) + if (pgc->cell_playback[cell].block_type != BLOCK_TYPE_ANGLE_BLOCK) return (cell + 1); - while (src->cur_pgc->cell_playback[cell].block_mode == BLOCK_MODE_LAST_CELL) + while (pgc->cell_playback[cell].block_mode == BLOCK_MODE_LAST_CELL) ++cell; return cell + 1; /* really +1? (tpm) */ @@ -540,6 +623,58 @@ +/* find time for sector from index, returns NONE if there is no exact match */ +static GstClockTime +gst_dvd_read_src_get_time_for_sector (GstDvdReadSrc * src, guint sector) + gint i, j; + if (src->vts_tmapt == NULL || src->vts_tmapt->nr_of_tmaps == 0) + return GST_CLOCK_TIME_NONE; + for (i = 0; i < src->vts_tmapt->nr_of_tmaps; ++i) { + for (j = 0; j < src->vts_tmapt->tmap[i].nr_of_entries; ++j) { + if ((src->vts_tmapt->tmap[i].map_ent[j] & 0x7fffffff) == sector) + return src->vts_tmapt->tmap[i].tmu * (j + 1) * GST_SECOND; + if (sector == 0) + return (GstClockTime) 0; + return GST_CLOCK_TIME_NONE; +/* returns the sector in the index at (or before) the given time, or -1 */ +static gint +gst_dvd_read_src_get_sector_from_time (GstDvdReadSrc * src, GstClockTime ts) + gint sector, i, j; + return -1; + sector = 0; + GstClockTime entry_time; + entry_time = src->vts_tmapt->tmap[i].tmu * (j + 1) * GST_SECOND; + if (entry_time <= ts) { + sector = src->vts_tmapt->tmap[i].map_ent[j] & 0x7fffffff; + if (entry_time >= ts) { + return sector; + if (ts == 0) + return 0; + return -1; typedef enum GST_DVD_READ_OK = 0, @@ -569,7 +704,8 @@ if (src->chapter == (src->num_chapters - 1)) goto eos; - GST_INFO_OBJECT (src, "end of chapter %d, switch to next", src->chapter); + GST_INFO_OBJECT (src, "end of chapter %d, switch to next", + src->chapter + 1); ++src->chapter; gst_dvd_read_src_goto_chapter (src, src->chapter); @@ -592,7 +728,8 @@ src->cur_cell += angle; /* calculate next cell */ - src->next_cell = gst_dvd_read_src_get_next_cell_for (src, src->cur_cell); + src->next_cell = + gst_dvd_read_src_get_next_cell (src, src->cur_pgc, src->cur_cell); /* we loop until we're out of this cell */ src->cur_pack = src->cur_pgc->cell_playback[src->cur_cell].first_sector; @@ -655,6 +792,8 @@ GST_BUFFER_SIZE (buf) = cur_output_size * DVD_VIDEO_LB_LEN; /* GST_BUFFER_OFFSET (buf) = priv->cur_pack * DVD_VIDEO_LB_LEN; */ + GST_BUFFER_TIMESTAMP (buf) = + gst_dvd_read_src_get_time_for_sector (src, src->cur_pack); gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (src))); @@ -903,12 +1042,12 @@ src->angle = (gint) new_off; GST_OBJECT_UNLOCK (src); - GST_DEBUG_OBJECT (src, "switched to angle %d", (gint) new_off); + GST_DEBUG_OBJECT (src, "switched to angle %d", (gint) new_off + 1); return TRUE; if (format != chapter_format && format != title_format && - format != GST_FORMAT_BYTES) { + 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; @@ -920,6 +1059,10 @@ } else if (format == GST_FORMAT_TIME) { GST_DEBUG_OBJECT (src, "Requested seek to time %" GST_TIME_FORMAT, GST_TIME_ARGS (new_off)); + if (gst_dvd_read_src_get_sector_from_time (src, new_off) < 0) { + GST_DEBUG_OBJECT (src, "Can't find sector for requested time"); + return FALSE; srcpad = GST_BASE_SRC_PAD (src); @@ -973,13 +1116,26 @@ 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) { + if (s->format == sector_format || s->format == GST_FORMAT_BYTES + || s->format == GST_FORMAT_TIME) { guint old; old = src->cur_pack; if (s->format == sector_format) { src->cur_pack = s->last_stop; + } else if (s->format == GST_FORMAT_TIME) { + gint sector; + sector = gst_dvd_read_src_get_sector_from_time (src, s->last_stop); + GST_DEBUG_OBJECT (src, "Time %" GST_TIME_FORMAT " => sector %d", + GST_TIME_ARGS (s->last_stop), sector); + /* really shouldn't happen, we've checked this earlier ... */ + g_return_val_if_fail (sector >= 0, FALSE); + src->cur_pack = sector; } else { /* byte format */ src->cur_pack = s->last_stop / DVD_VIDEO_LB_LEN; @@ -999,10 +1155,11 @@ GST_LOG_OBJECT (src, "seek to sector 0x%08x ok", src->cur_pack); } else if (s->format == chapter_format) { if (!gst_dvd_read_src_goto_chapter (src, (gint) s->last_stop)) { - GST_DEBUG_OBJECT (src, "seek to chapter %d failed", (gint) s->last_stop); + GST_DEBUG_OBJECT (src, "seek to chapter %d failed", + (gint) s->last_stop + 1); return FALSE; - GST_INFO_OBJECT (src, "seek to chapter %d ok", (gint) s->last_stop); + GST_INFO_OBJECT (src, "seek to chapter %d ok", (gint) s->last_stop + 1); src->chapter = s->last_stop; } else if (s->format == title_format) { if (!gst_dvd_read_src_goto_title (src, (gint) s->last_stop, src->angle) || @@ -1012,7 +1169,7 @@ src->title = (gint) s->last_stop; src->chapter = 0; - GST_INFO_OBJECT (src, "seek to title %d ok", src->title); + GST_INFO_OBJECT (src, "seek to title %d ok", src->title + 1); } else { g_return_val_if_reached (FALSE); @@ -1233,7 +1390,7 @@ cur = next; if (src->cur_pgc->cell_playback[cur].block_type == BLOCK_TYPE_ANGLE_BLOCK) cur += angle; - next = gst_dvd_read_src_get_next_cell_for (src, cur); + next = gst_dvd_read_src_get_next_cell (src, src->cur_pgc, cur); @@ -1246,7 +1403,7 @@ /* so chapter $chapter and cell $cur contain our sector * of interest. Let's go there! */ GST_INFO_OBJECT (src, "Seek succeeded, going to chapter %u, cell %u", - chapter, cur); + chapter + 1, cur); gst_dvd_read_src_goto_chapter (src, chapter); src->cur_cell = cur; Index: dvdreadsrc.h RCS file: /cvs/gstreamer/gst-plugins-ugly/ext/dvdread/dvdreadsrc.h,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- dvdreadsrc.h 30 Jun 2006 11:26:22 -0000 1.10 +++ dvdreadsrc.h 6 Aug 2006 19:47:40 -0000 1.11 @@ -1,5 +1,7 @@ * Copyright (C) <1999> Erik Walthinsen <om...@cs...> + * Copyright (C) <2001> Billy Biggs <ve...@du...>. + * Copyright (C) <2006> Tim-Philipp Müller <tim centricular net> @@ -71,10 +73,13 @@ tt_srpt_t *tt_srpt; ifo_handle_t *vts_file; vts_ptt_srpt_t *vts_ptt_srpt; + vts_tmapt_t *vts_tmapt; dvd_file_t *dvd_title; gint num_chapters; gint num_angles; + GstClockTime *chapter_starts; /* start time of chapters within title */ /* which program chain to watch (based on title and chapter number) */ pgc_t *cur_pgc; gint pgc_id; |