From 874549b5360ad897e11f809e929d62803a7b5f2f Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Tue, 5 May 2009 11:34:26 +0100 Subject: resindvd: Make the next/prev angle switching cycle at the ends When the current angle is 1 and prev_angle is requested, loop to the maximum angle and vice versa for next_angle --- ext/resindvd/resindvdsrc.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index a2f31610..ab0fdef9 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -1172,6 +1172,7 @@ static RsnNavResult rsn_dvdsrc_do_command (resinDvdSrc * src, GstNavigationCommand command) { RsnNavResult result = RSN_NAV_RESULT_NONE; + gint new_angle = 0; switch (command) { case GST_NAVIGATION_COMMAND_DVD_MENU: @@ -1212,25 +1213,40 @@ rsn_dvdsrc_do_command (resinDvdSrc * src, GstNavigationCommand command) case GST_NAVIGATION_COMMAND_PREV_ANGLE:{ gint32 cur, agls; - if (dvdnav_get_angle_info (src->dvdnav, &cur, &agls) == DVDNAV_STATUS_OK - && cur > 0 - && dvdnav_angle_change (src->dvdnav, cur - 1) == DVDNAV_STATUS_OK) - GST_INFO_OBJECT (src, "Switched to angle %d", cur - 1); - /* Angle switches are seamless and involve no branching */ + if (dvdnav_get_angle_info (src->dvdnav, &cur, &agls) == DVDNAV_STATUS_OK) { + if (cur > 0 && + dvdnav_angle_change (src->dvdnav, cur - 1) == DVDNAV_STATUS_OK) { + new_angle = cur - 1; + } else if (cur == 1 && + dvdnav_angle_change (src->dvdnav, agls) == DVDNAV_STATUS_OK) { + new_angle = agls; + } + /* Angle switches are seamless and involve no branching */ + } break; } case GST_NAVIGATION_COMMAND_NEXT_ANGLE:{ gint32 cur, agls; - if (dvdnav_get_angle_info (src->dvdnav, &cur, &agls) == DVDNAV_STATUS_OK - && dvdnav_angle_change (src->dvdnav, cur + 1) == DVDNAV_STATUS_OK) - GST_INFO_OBJECT (src, "Switched to angle %d", cur + 1); - /* Angle switches are seamless and involve no branching */ + if (dvdnav_get_angle_info (src->dvdnav, &cur, &agls) == DVDNAV_STATUS_OK) { + if (cur < agls + && dvdnav_angle_change (src->dvdnav, cur + 1) == DVDNAV_STATUS_OK) { + new_angle = cur + 1; + } else if (cur == agls + && dvdnav_angle_change (src->dvdnav, 1) == DVDNAV_STATUS_OK) { + new_angle = 1; + } + /* Angle switches are seamless and involve no branching */ + } break; } default: break; } + if (new_angle) { + GST_INFO_OBJECT (src, "Switched to angle %d", new_angle); + } + return result; } -- cgit v1.2.1 From 491583b6482fd6287653b8c6fb49494dd44b4261 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Tue, 5 May 2009 13:14:47 +0100 Subject: resindvd: send angles-changed messages when appropriate When the current angle changes, or the number of available angles changes, send an angles-changed message to let the app know. --- ext/resindvd/resindvdsrc.c | 59 ++++++++++++++++++++++++++++++++++++++++++---- ext/resindvd/resindvdsrc.h | 3 +++ 2 files changed, 57 insertions(+), 5 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index ab0fdef9..35cf8e15 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -391,6 +391,9 @@ rsn_dvdsrc_start (RsnBaseSrc * bsrc) src->active_button = -1; + src->angles_changed = FALSE; + src->n_angles = 0; + src->cur_spu_phys_stream = -1; src->cur_spu_forced_only = FALSE; memset (src->cur_clut, 0, sizeof (guint32) * 16); @@ -859,6 +862,7 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock) break; case DVDNAV_CELL_CHANGE:{ dvdnav_cell_change_event_t *event = (dvdnav_cell_change_event_t *) data; + gint n_angles, cur; src->pgc_duration = MPEGTIME_TO_GSTTIME (event->pgc_length); /* event->cell_start has the wrong time - it doesn't handle @@ -874,6 +878,12 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock) rsn_dvdsrc_prepare_streamsinfo_event (src); + if (dvdnav_get_angle_info (src->dvdnav, &cur, + &n_angles) == DVDNAV_STATUS_OK && src->n_angles != n_angles) { + src->angles_changed = TRUE; + src->n_angles = n_angles; + } + break; } case DVDNAV_SPU_CLUT_CHANGE: @@ -998,6 +1008,7 @@ rsn_dvdsrc_create (RsnPushSrc * psrc, GstBuffer ** outbuf) GstEvent *spu_select_event = NULL; GstEvent *audio_select_event = NULL; GstEvent *highlight_event = NULL; + GstMessage *angles_msg = NULL; *outbuf = NULL; @@ -1020,6 +1031,18 @@ rsn_dvdsrc_create (RsnPushSrc * psrc, GstBuffer ** outbuf) clut_event = src->clut_event; src->clut_event = NULL; + if (src->angles_changed) { + gint cur, agls; + if (dvdnav_get_angle_info (src->dvdnav, &cur, &agls) == DVDNAV_STATUS_OK) { + + angles_msg = + gst_navigation_message_new_angles_changed (GST_OBJECT_CAST (src), + cur, agls); + src->n_angles = agls; + } + src->angles_changed = FALSE; + } + g_mutex_unlock (src->dvd_lock); /* Push in-band events now that we've dropped the dvd_lock, before @@ -1089,6 +1112,10 @@ rsn_dvdsrc_create (RsnPushSrc * psrc, GstBuffer ** outbuf) gst_pad_push_event (GST_BASE_SRC_PAD (src), highlight_event); } + if (angles_msg) { + gst_element_post_message (GST_ELEMENT_CAST (src), angles_msg); + } + return ret; } @@ -1172,7 +1199,6 @@ static RsnNavResult rsn_dvdsrc_do_command (resinDvdSrc * src, GstNavigationCommand command) { RsnNavResult result = RSN_NAV_RESULT_NONE; - gint new_angle = 0; switch (command) { case GST_NAVIGATION_COMMAND_DVD_MENU: @@ -1213,6 +1239,7 @@ rsn_dvdsrc_do_command (resinDvdSrc * src, GstNavigationCommand command) case GST_NAVIGATION_COMMAND_PREV_ANGLE:{ gint32 cur, agls; + gint new_angle = 0; if (dvdnav_get_angle_info (src->dvdnav, &cur, &agls) == DVDNAV_STATUS_OK) { if (cur > 0 && dvdnav_angle_change (src->dvdnav, cur - 1) == DVDNAV_STATUS_OK) { @@ -1222,11 +1249,16 @@ rsn_dvdsrc_do_command (resinDvdSrc * src, GstNavigationCommand command) new_angle = agls; } /* Angle switches are seamless and involve no branching */ + if (new_angle) { + src->angles_changed = TRUE; + GST_INFO_OBJECT (src, "Switched to angle %d", new_angle); + } } break; } case GST_NAVIGATION_COMMAND_NEXT_ANGLE:{ gint32 cur, agls; + gint new_angle = 0; if (dvdnav_get_angle_info (src->dvdnav, &cur, &agls) == DVDNAV_STATUS_OK) { if (cur < agls && dvdnav_angle_change (src->dvdnav, cur + 1) == DVDNAV_STATUS_OK) { @@ -1236,6 +1268,10 @@ rsn_dvdsrc_do_command (resinDvdSrc * src, GstNavigationCommand command) new_angle = 1; } /* Angle switches are seamless and involve no branching */ + if (new_angle) { + src->angles_changed = TRUE; + GST_INFO_OBJECT (src, "Switched to angle %d", new_angle); + } } break; } @@ -1243,10 +1279,6 @@ rsn_dvdsrc_do_command (resinDvdSrc * src, GstNavigationCommand command) break; } - if (new_angle) { - GST_INFO_OBJECT (src, "Switched to angle %d", new_angle); - } - return result; } @@ -1258,6 +1290,7 @@ rsn_dvdsrc_handle_navigation_event (resinDvdSrc * src, GstEvent * event) RsnNavResult nav_res = RSN_NAV_RESULT_NONE; GstNavigationEventType etype = gst_navigation_event_get_type (event); GstMessage *mouse_over_msg = NULL; + GstMessage *angles_msg = NULL; switch (etype) { case GST_NAVIGATION_EVENT_KEY_PRESS:{ @@ -1438,6 +1471,18 @@ rsn_dvdsrc_handle_navigation_event (resinDvdSrc * src, GstEvent * event) hl_event = src->highlight_event; src->highlight_event = NULL; + if (src->angles_changed) { + gint cur, agls; + if (dvdnav_get_angle_info (src->dvdnav, &cur, &agls) == DVDNAV_STATUS_OK) { + + angles_msg = + gst_navigation_message_new_angles_changed (GST_OBJECT_CAST (src), + cur, agls); + src->n_angles = agls; + } + src->angles_changed = FALSE; + } + g_mutex_unlock (src->dvd_lock); if (hl_event) { @@ -1451,6 +1496,10 @@ rsn_dvdsrc_handle_navigation_event (resinDvdSrc * src, GstEvent * event) gst_element_post_message (GST_ELEMENT_CAST (src), mouse_over_msg); } + if (angles_msg) { + gst_element_post_message (GST_ELEMENT_CAST (src), angles_msg); + } + return TRUE; not_running: if (have_lock) diff --git a/ext/resindvd/resindvdsrc.h b/ext/resindvd/resindvdsrc.h index 61fa5d19..bfcb7497 100644 --- a/ext/resindvd/resindvdsrc.h +++ b/ext/resindvd/resindvdsrc.h @@ -114,6 +114,8 @@ struct _resinDvdSrc GstEvent *audio_select_event; GstEvent *highlight_event; + gboolean angles_changed; + /* GList of NAV packets awaiting activation, and the * running times to activate them. */ GSList *pending_nav_blocks; @@ -129,6 +131,7 @@ struct _resinDvdSrc gint8 cur_spu_phys_stream; gboolean cur_spu_forced_only; guint32 cur_clut[16]; + gint n_angles; }; struct _resinDvdSrcClass -- cgit v1.2.1 From f7fad4a88b56dd74b14070886c8e86bb14942b20 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Tue, 5 May 2009 13:18:20 +0100 Subject: resindvd: Don't send highlight-reset messages when not needed Fix a small bug that results in the SPU highlight being reset more often than is necessary - ie, clearing it when it's already cleared. --- ext/resindvd/resindvdsrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 35cf8e15..389b9016 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -1798,7 +1798,7 @@ rsn_dvdsrc_update_highlight (resinDvdSrc * src) if (button == 0) { /* No highlight available, or no button selected - clear the SPU */ - if (src->active_button < 1) { + if (src->active_button != 0) { src->active_button = 0; s = gst_structure_new ("application/x-gst-dvd", "event", -- cgit v1.2.1 From a5fbb123cab57358325b9cd94d2e8de50361f0c1 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Wed, 6 May 2009 21:19:13 +0100 Subject: resindvd: Send a title tag when we change chapter/menu/angle Allow apps like Totem to display a nicer title that reflects the current position on the disc. --- ext/resindvd/resindvdsrc.c | 78 ++++++++++++++++++++++++++++++++++++++++++---- ext/resindvd/resindvdsrc.h | 4 +++ 2 files changed, 76 insertions(+), 6 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 389b9016..ba800efe 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -374,6 +374,8 @@ rsn_dvdsrc_start (RsnBaseSrc * bsrc) } } + dvdnav_get_title_string (src->dvdnav, &src->disc_name); + src->first_seek = TRUE; src->running = TRUE; src->branching = FALSE; @@ -388,6 +390,8 @@ rsn_dvdsrc_start (RsnBaseSrc * bsrc) src->vts_n = 0; src->in_menu = FALSE; + src->title_n = -1; + src->part_n = -1; src->active_button = -1; @@ -519,6 +523,8 @@ rsn_dvdsrc_stop (RsnBaseSrc * bsrc) src->highlight_event = NULL; } + src->disc_name = NULL; + if (src->dvdnav) { if (dvdnav_close (src->dvdnav) != DVDNAV_STATUS_OK) { GST_ELEMENT_ERROR (src, RESOURCE, CLOSE, (NULL), @@ -725,6 +731,71 @@ get_current_pgc (resinDvdSrc * src) return pgc; } +static void +update_title_info (resinDvdSrc * src) +{ + gint n_angles, cur_agl; + gint title_n, part_n; + + if (dvdnav_get_angle_info (src->dvdnav, &cur_agl, + &n_angles) == DVDNAV_STATUS_OK && src->n_angles != n_angles) { + src->angles_changed = TRUE; + src->n_angles = n_angles; + } + + if (dvdnav_current_title_info (src->dvdnav, &title_n, + &part_n) == DVDNAV_STATUS_OK) { + if (title_n != src->title_n || part_n != src->part_n || src->angles_changed) { + gchar *title_str = NULL; + + src->title_n = title_n; + src->part_n = part_n; + + if (title_n == 0) { + static const char *dvd_menu_map[] = { + NULL, NULL, "Title", "Root", + "Subpicture", "Audio", "Angle", "Part" + }; + + /* In a menu */ + if (part_n >= 0 && part_n < G_N_ELEMENTS (dvd_menu_map) + && dvd_menu_map[part_n]) { + title_str = g_strdup_printf ("DVD %s Menu", dvd_menu_map[part_n]); + } else { + title_str = g_strdup ("DVD Menu"); + } + } else { + /* In a title */ + if (n_angles > 1) { + title_str = g_strdup_printf ("Title %i, Chapter %i, Angle %i of %i", + title_n, part_n, cur_agl, n_angles); + + } else { + title_str = g_strdup_printf ("Title %i, Chapter %i", title_n, part_n); + } + } + + if (src->disc_name && src->disc_name[0]) { + /* We have a name for this disc, publish it */ + if (title_str) { + gchar *new_title_str = + g_strdup_printf ("%s, %s", title_str, src->disc_name); + g_free (title_str); + title_str = new_title_str; + } else { + title_str = g_strdup (src->disc_name); + } + } + if (title_str) { + GstTagList *tags = gst_tag_list_new (); + gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, + title_str, NULL); + gst_element_found_tags (GST_ELEMENT_CAST (src), tags); + } + } + } +} + static GstFlowReturn rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock) { @@ -862,7 +933,6 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock) break; case DVDNAV_CELL_CHANGE:{ dvdnav_cell_change_event_t *event = (dvdnav_cell_change_event_t *) data; - gint n_angles, cur; src->pgc_duration = MPEGTIME_TO_GSTTIME (event->pgc_length); /* event->cell_start has the wrong time - it doesn't handle @@ -878,11 +948,7 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock) rsn_dvdsrc_prepare_streamsinfo_event (src); - if (dvdnav_get_angle_info (src->dvdnav, &cur, - &n_angles) == DVDNAV_STATUS_OK && src->n_angles != n_angles) { - src->angles_changed = TRUE; - src->n_angles = n_angles; - } + update_title_info (src); break; } diff --git a/ext/resindvd/resindvdsrc.h b/ext/resindvd/resindvdsrc.h index bfcb7497..f55b454f 100644 --- a/ext/resindvd/resindvdsrc.h +++ b/ext/resindvd/resindvdsrc.h @@ -58,6 +58,8 @@ struct _resinDvdSrc gchar *device; dvdnav_t *dvdnav; + const char *disc_name; + /* dvd_reader instance is used to load and cache VTS/VMG ifo info */ dvd_reader_t *dvdread; @@ -72,6 +74,8 @@ struct _resinDvdSrc /* Current playback location: VTS 0 = VMG, plus in_menu or not */ gint vts_n; gboolean in_menu; + gint title_n; /* Title num */ + gint part_n; /* Part num */ gboolean running; gboolean discont; -- cgit v1.2.1 From 77aefd58709b2151b59430f944eec80f18201b7f Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Wed, 6 May 2009 21:48:30 +0100 Subject: resindvd: Don't open all VTS ifo at the start Load each VTS ifo the first time the disc enters that VTS, rather than scanning them all at the start. --- ext/resindvd/resindvdsrc.c | 53 +++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 20 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index ba800efe..54a39be1 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -421,7 +421,6 @@ fail: static gboolean read_vts_info (resinDvdSrc * src) { - gint i; gint n_vts; if (src->vts_attrs) { @@ -450,28 +449,48 @@ read_vts_info (resinDvdSrc * src) return FALSE; g_array_set_size (src->vts_attrs, n_vts + 1); - for (i = 1; i <= n_vts; i++) { - ifo_handle_t *ifo = ifoOpen (src->dvdread, i); + return TRUE; +} + +static vtsi_mat_t * +get_vts_attr (resinDvdSrc * src, gint n) +{ + vtsi_mat_t *vts_attr; + + if (src->vts_attrs == NULL || n >= src->vts_attrs->len) { + if (src->vts_attrs) + GST_ERROR_OBJECT (src, "No stream info for VTS %d (have %d)", n, + src->vts_attrs->len); + else + GST_ERROR_OBJECT (src, "No stream info"); + return NULL; + } + + vts_attr = &g_array_index (src->vts_attrs, vtsi_mat_t, src->vts_n); + + /* Check if we have read this VTS ifo yet */ + if (vts_attr->vtsm_vobs == 0) { + ifo_handle_t *ifo = ifoOpen (src->dvdread, n); if (!ifo) { - GST_ERROR ("Can't open VTS %d", i); - return FALSE; + GST_ERROR ("Can't open VTS %d", n); + return NULL; } GST_DEBUG ("VTS %d, Menu has %d audio %d subpictures. " - "Title has %d and %d", i, + "Title has %d and %d", n, ifo->vtsi_mat->nr_of_vtsm_audio_streams, ifo->vtsi_mat->nr_of_vtsm_subp_streams, ifo->vtsi_mat->nr_of_vts_audio_streams, ifo->vtsi_mat->nr_of_vts_subp_streams); - memcpy (&g_array_index (src->vts_attrs, vtsi_mat_t, i), + memcpy (&g_array_index (src->vts_attrs, vtsi_mat_t, n), ifo->vtsi_mat, sizeof (vtsi_mat_t)); ifoClose (ifo); - } + }; - return TRUE; + return vts_attr; } static gboolean @@ -1646,15 +1665,6 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src) gboolean have_audio; gboolean have_subp; - if (src->vts_attrs == NULL || src->vts_n >= src->vts_attrs->len) { - if (src->vts_attrs) - GST_ERROR_OBJECT (src, "No stream info for VTS %d (have %d)", src->vts_n, - src->vts_attrs->len); - else - GST_ERROR_OBJECT (src, "No stream info"); - return FALSE; - } - if (src->vts_n == 0) { /* VMGM info */ vts_attr = NULL; @@ -1665,7 +1675,7 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src) n_subp = MIN (1, src->vmgm_attr.nr_of_vmgm_subp_streams); } else if (src->in_menu) { /* VTSM attrs */ - vts_attr = &g_array_index (src->vts_attrs, vtsi_mat_t, src->vts_n); + vts_attr = get_vts_attr (src, src->vts_n); v_attr = &vts_attr->vtsm_video_attr; a_attrs = &vts_attr->vtsm_audio_attr; n_audio = vts_attr->nr_of_vtsm_audio_streams; @@ -1673,7 +1683,7 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src) n_subp = vts_attr->nr_of_vtsm_subp_streams; } else { /* VTS domain */ - vts_attr = &g_array_index (src->vts_attrs, vtsi_mat_t, src->vts_n); + vts_attr = get_vts_attr (src, src->vts_n); v_attr = &vts_attr->vts_video_attr; a_attrs = vts_attr->vts_audio_attr; n_audio = vts_attr->nr_of_vts_audio_streams; @@ -1681,6 +1691,9 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src) n_subp = vts_attr->nr_of_vts_subp_streams; } + if (src->vts_n > 0 && vts_attr == NULL) + return FALSE; + GST_DEBUG_OBJECT (src, "Preparing streamsinfo for %d audio and " "%d subpicture streams", n_audio, n_subp); -- cgit v1.2.1 From 270cd7c421118af2d6f86535c495e216b5e821d2 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 8 May 2009 10:43:27 +0100 Subject: resindvd: Implement navigation command change message and query Send messages when the available DVD navigation commands changes, and handle navigation commands and angles queries. --- ext/resindvd/resindvdsrc.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++ ext/resindvd/resindvdsrc.h | 1 + 2 files changed, 73 insertions(+) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 54a39be1..22f6430b 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -134,6 +134,7 @@ static gboolean rsn_dvdsrc_src_event (RsnBaseSrc * basesrc, GstEvent * event); static gboolean rsn_dvdsrc_src_query (RsnBaseSrc * basesrc, GstQuery * query); static GstClockTime ifotime_to_gsttime (dvd_time_t * ifo_time); +static void rsn_dvdsrc_send_commands_changed (resinDvdSrc * src); static GstClockTime ifotime_to_gsttime (dvd_time_t * ifo_time) @@ -398,6 +399,8 @@ rsn_dvdsrc_start (RsnBaseSrc * bsrc) src->angles_changed = FALSE; src->n_angles = 0; + src->commands_changed = TRUE; + src->cur_spu_phys_stream = -1; src->cur_spu_forced_only = FALSE; memset (src->cur_clut, 0, sizeof (guint32) * 16); @@ -1062,6 +1065,57 @@ branching: return GST_FLOW_WRONG_STATE; } +/* Send app a bus message that the available commands have changed */ +static void +rsn_dvdsrc_send_commands_changed (resinDvdSrc * src) +{ + GstMessage *cmds_msg = + gst_navigation_message_new_commands_changed (GST_OBJECT_CAST (src)); + gst_element_post_message (GST_ELEMENT_CAST (src), cmds_msg); +} + +static gboolean +rsn_dvdsrc_handle_cmds_query (resinDvdSrc * src, GstQuery * query) +{ + return FALSE; +} + +static gboolean +rsn_dvdsrc_handle_angles_query (resinDvdSrc * src, GstQuery * query) +{ + gint cur_agl, n_angles; + gboolean res = FALSE; + + g_mutex_lock (src->dvd_lock); + if (dvdnav_get_angle_info (src->dvdnav, &cur_agl, + &n_angles) == DVDNAV_STATUS_OK) { + gst_navigation_query_set_angles (query, cur_agl, n_angles); + res = TRUE; + } + g_mutex_unlock (src->dvd_lock); + + return res; +} + +static gboolean +rsn_dvdsrc_handle_navigation_query (resinDvdSrc * src, + GstNavigationQueryType nq_type, GstQuery * query) +{ + gboolean res; + switch (nq_type) { + case GST_NAVIGATION_QUERY_COMMANDS: + res = rsn_dvdsrc_handle_cmds_query (src, query); + break; + case GST_NAVIGATION_QUERY_ANGLES: + res = rsn_dvdsrc_handle_angles_query (src, query); + break; + default: + res = FALSE; + } + + return res; +} + static GstFlowReturn rsn_dvdsrc_prepare_next_block (resinDvdSrc * src, gboolean have_dvd_lock) { @@ -1094,6 +1148,7 @@ rsn_dvdsrc_create (RsnPushSrc * psrc, GstBuffer ** outbuf) GstEvent *audio_select_event = NULL; GstEvent *highlight_event = NULL; GstMessage *angles_msg = NULL; + gboolean cmds_changed = FALSE; *outbuf = NULL; @@ -1128,6 +1183,11 @@ rsn_dvdsrc_create (RsnPushSrc * psrc, GstBuffer ** outbuf) src->angles_changed = FALSE; } + if (src->commands_changed) { + cmds_changed = TRUE; + src->commands_changed = FALSE; + } + g_mutex_unlock (src->dvd_lock); /* Push in-band events now that we've dropped the dvd_lock, before @@ -1201,6 +1261,9 @@ rsn_dvdsrc_create (RsnPushSrc * psrc, GstBuffer ** outbuf) gst_element_post_message (GST_ELEMENT_CAST (src), angles_msg); } + if (cmds_changed) + rsn_dvdsrc_send_commands_changed (src); + return ret; } @@ -2261,6 +2324,15 @@ rsn_dvdsrc_src_query (RsnBaseSrc * basesrc, GstQuery * query) } g_mutex_unlock (src->dvd_lock); break; + case GST_QUERY_CUSTOM: + { + GstNavigationQueryType nq_type = gst_navigation_query_get_type (query); + if (nq_type != GST_NAVIGATION_QUERY_INVALID) + res = rsn_dvdsrc_handle_navigation_query (src, nq_type, query); + else + res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query); + break; + } default: res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query); break; diff --git a/ext/resindvd/resindvdsrc.h b/ext/resindvd/resindvdsrc.h index f55b454f..fd03466a 100644 --- a/ext/resindvd/resindvdsrc.h +++ b/ext/resindvd/resindvdsrc.h @@ -119,6 +119,7 @@ struct _resinDvdSrc GstEvent *highlight_event; gboolean angles_changed; + gboolean commands_changed; /* GList of NAV packets awaiting activation, and the * running times to activate them. */ -- cgit v1.2.1 From 86d908589c4ef2d715e4f015c2455a19de322a51 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 8 May 2009 14:20:32 +0100 Subject: resindvd: Send title info message when current angle is switched. Make sure we send an update title tag when the current angle or available angles changes. --- ext/resindvd/resindvdsrc.c | 12 ++++++++---- ext/resindvd/resindvdsrc.h | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 22f6430b..b95e5c4a 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -398,6 +398,7 @@ rsn_dvdsrc_start (RsnBaseSrc * bsrc) src->angles_changed = FALSE; src->n_angles = 0; + src->cur_angle = 0; src->commands_changed = TRUE; @@ -761,17 +762,20 @@ update_title_info (resinDvdSrc * src) if (dvdnav_get_angle_info (src->dvdnav, &cur_agl, &n_angles) == DVDNAV_STATUS_OK && src->n_angles != n_angles) { + /* Make sure we send an angles-changed message soon */ src->angles_changed = TRUE; - src->n_angles = n_angles; } if (dvdnav_current_title_info (src->dvdnav, &title_n, &part_n) == DVDNAV_STATUS_OK) { - if (title_n != src->title_n || part_n != src->part_n || src->angles_changed) { + if (title_n != src->title_n || part_n != src->part_n || + src->n_angles != n_angles || src->cur_angle != cur_agl) { gchar *title_str = NULL; src->title_n = title_n; src->part_n = part_n; + src->n_angles = n_angles; + src->cur_angle = cur_agl; if (title_n == 0) { static const char *dvd_menu_map[] = { @@ -1178,7 +1182,6 @@ rsn_dvdsrc_create (RsnPushSrc * psrc, GstBuffer ** outbuf) angles_msg = gst_navigation_message_new_angles_changed (GST_OBJECT_CAST (src), cur, agls); - src->n_angles = agls; } src->angles_changed = FALSE; } @@ -1626,9 +1629,10 @@ rsn_dvdsrc_handle_navigation_event (resinDvdSrc * src, GstEvent * event) angles_msg = gst_navigation_message_new_angles_changed (GST_OBJECT_CAST (src), cur, agls); - src->n_angles = agls; } src->angles_changed = FALSE; + + update_title_info (src); } g_mutex_unlock (src->dvd_lock); diff --git a/ext/resindvd/resindvdsrc.h b/ext/resindvd/resindvdsrc.h index fd03466a..0d883744 100644 --- a/ext/resindvd/resindvdsrc.h +++ b/ext/resindvd/resindvdsrc.h @@ -76,6 +76,8 @@ struct _resinDvdSrc gboolean in_menu; gint title_n; /* Title num */ gint part_n; /* Part num */ + gint n_angles; /* number of angles */ + gint cur_angle; /* current angle */ gboolean running; gboolean discont; @@ -136,7 +138,6 @@ struct _resinDvdSrc gint8 cur_spu_phys_stream; gboolean cur_spu_forced_only; guint32 cur_clut[16]; - gint n_angles; }; struct _resinDvdSrcClass -- cgit v1.2.1 From 9f01bd64349cc14c25991cea5e054f286ab732bf Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 8 May 2009 14:23:48 +0100 Subject: resindvd: Remove per-menu description from the TITLE tag The part number reported while in a menu doesn't reflect the selected menu, so it's pointless to use it to report which menu we're in (Audio, Angle etc). Just report "DVD Menu" in the title tag instead. --- ext/resindvd/resindvdsrc.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index b95e5c4a..7b6a7415 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -778,18 +778,8 @@ update_title_info (resinDvdSrc * src) src->cur_angle = cur_agl; if (title_n == 0) { - static const char *dvd_menu_map[] = { - NULL, NULL, "Title", "Root", - "Subpicture", "Audio", "Angle", "Part" - }; - /* In a menu */ - if (part_n >= 0 && part_n < G_N_ELEMENTS (dvd_menu_map) - && dvd_menu_map[part_n]) { - title_str = g_strdup_printf ("DVD %s Menu", dvd_menu_map[part_n]); - } else { - title_str = g_strdup ("DVD Menu"); - } + title_str = g_strdup ("DVD Menu"); } else { /* In a title */ if (n_angles > 1) { -- cgit v1.2.1 From f2f79cd4108add0071f868c5d8e8857d3421c707 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 8 May 2009 16:06:01 +0100 Subject: resindvd: Simplify some stuff. Remove an unnecessary LOG message. Skip attempting to schedule a nav block unless we're in PLAYING. Take a lock slightly later, when we actually need it. Remove a noisy LOG message. --- ext/resindvd/resindvdsrc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 7b6a7415..479a883a 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -665,7 +665,7 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration) /* FIXME: Implement timed stills by sleeping on the clock, possibly * in multiple steps if we get paused/unpaused */ g_mutex_unlock (src->dvd_lock); - GST_LOG_OBJECT (src, "cond_timed_wait still"); + GST_LOG_OBJECT (src, "cond_timed_wait still for %d sec", duration); was_signalled = g_cond_timed_wait (src->still_cond, src->branch_lock, &end_time); was_signalled |= src->branching; @@ -2109,19 +2109,19 @@ rsn_dvdsrc_nav_clock_cb (GstClock * clock, GstClockTime time, GstClockID id, return TRUE; } +/* Called with dvd_lock held */ static void rsn_dvdsrc_schedule_nav_cb (resinDvdSrc * src, RsnDvdPendingNav * next_nav) { GstClock *clock; GstClockTime base_ts; - GST_OBJECT_LOCK (src); if (!src->in_playing) { GST_LOG_OBJECT (src, "Not scheduling NAV block - state != PLAYING"); - GST_OBJECT_UNLOCK (src); return; /* Not in playing state yet */ } + GST_OBJECT_LOCK (src); clock = GST_ELEMENT_CLOCK (src); base_ts = GST_ELEMENT (src)->base_time; @@ -2144,6 +2144,7 @@ rsn_dvdsrc_schedule_nav_cb (resinDvdSrc * src, RsnDvdPendingNav * next_nav) gst_object_unref (clock); } +/* Called with dvd_lock held */ static void rsn_dvdsrc_check_nav_blocks (resinDvdSrc * src) { @@ -2154,9 +2155,10 @@ rsn_dvdsrc_check_nav_blocks (resinDvdSrc * src) return; /* Something already scheduled */ } if (src->pending_nav_blocks == NULL) { - GST_LOG_OBJECT (src, "No NAV blocks to schedule"); return; /* No nav blocks available yet */ } + if (!src->in_playing) + return; /* Not in playing state yet */ GST_LOG_OBJECT (src, "Installing NAV callback"); next_nav = (RsnDvdPendingNav *) src->pending_nav_blocks->data; @@ -2164,8 +2166,6 @@ rsn_dvdsrc_check_nav_blocks (resinDvdSrc * src) rsn_dvdsrc_schedule_nav_cb (src, next_nav); } -/* Use libdvdread to read and cache info from the IFO file about - * streams in each VTS */ static gboolean rsn_dvdsrc_src_event (RsnBaseSrc * basesrc, GstEvent * event) { -- cgit v1.2.1 From c0854113a18003cc4a717a49b674f7a2038fa602 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 8 May 2009 16:27:31 +0100 Subject: resindvd: Ensure we send a title tag in the first play section. --- ext/resindvd/resindvdsrc.c | 79 ++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 37 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 479a883a..f479da2a 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -767,48 +767,54 @@ update_title_info (resinDvdSrc * src) } if (dvdnav_current_title_info (src->dvdnav, &title_n, - &part_n) == DVDNAV_STATUS_OK) { - if (title_n != src->title_n || part_n != src->part_n || - src->n_angles != n_angles || src->cur_angle != cur_agl) { - gchar *title_str = NULL; - - src->title_n = title_n; - src->part_n = part_n; - src->n_angles = n_angles; - src->cur_angle = cur_agl; - - if (title_n == 0) { - /* In a menu */ - title_str = g_strdup ("DVD Menu"); - } else { - /* In a title */ - if (n_angles > 1) { - title_str = g_strdup_printf ("Title %i, Chapter %i, Angle %i of %i", - title_n, part_n, cur_agl, n_angles); + &part_n) != DVDNAV_STATUS_OK) { + if (!src->in_menu) + return; /* Can't update now */ + /* Must be in the first play sequence */ + title_n = -1; + part_n = 0; + } + + if (title_n != src->title_n || part_n != src->part_n || + src->n_angles != n_angles || src->cur_angle != cur_agl) { + gchar *title_str = NULL; + + src->title_n = title_n; + src->part_n = part_n; + src->n_angles = n_angles; + src->cur_angle = cur_agl; + + if (title_n == 0) { + /* In a menu */ + title_str = g_strdup ("DVD Menu"); + } else if (title_n > 0) { + /* In a title */ + if (n_angles > 1) { + title_str = g_strdup_printf ("Title %i, Chapter %i, Angle %i of %i", + title_n, part_n, cur_agl, n_angles); - } else { - title_str = g_strdup_printf ("Title %i, Chapter %i", title_n, part_n); - } + } else { + title_str = g_strdup_printf ("Title %i, Chapter %i", title_n, part_n); } + } - if (src->disc_name && src->disc_name[0]) { - /* We have a name for this disc, publish it */ - if (title_str) { - gchar *new_title_str = - g_strdup_printf ("%s, %s", title_str, src->disc_name); - g_free (title_str); - title_str = new_title_str; - } else { - title_str = g_strdup (src->disc_name); - } - } + if (src->disc_name && src->disc_name[0]) { + /* We have a name for this disc, publish it */ if (title_str) { - GstTagList *tags = gst_tag_list_new (); - gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, - title_str, NULL); - gst_element_found_tags (GST_ELEMENT_CAST (src), tags); + gchar *new_title_str = + g_strdup_printf ("%s, %s", title_str, src->disc_name); + g_free (title_str); + title_str = new_title_str; + } else { + title_str = g_strdup (src->disc_name); } } + if (title_str) { + GstTagList *tags = gst_tag_list_new (); + gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, + title_str, NULL); + gst_element_found_tags (GST_ELEMENT_CAST (src), tags); + } } } @@ -911,7 +917,6 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock) src->next_is_nav_block = FALSE; src->next_nav_ts = GST_CLOCK_TIME_NONE; } - break; } case DVDNAV_STOP: -- cgit v1.2.1 From 64b6d247d4428ce3dadcbe8729cc891a8891c7db Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 8 May 2009 16:29:20 +0100 Subject: resindvd: Rename the audio munger debug category Rename a debug category: rsn_audiomunge -> rsnaudiomunge. --- ext/resindvd/rsnaudiomunge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/rsnaudiomunge.c b/ext/resindvd/rsnaudiomunge.c index fc7e552f..c44d7d2e 100644 --- a/ext/resindvd/rsnaudiomunge.c +++ b/ext/resindvd/rsnaudiomunge.c @@ -86,8 +86,8 @@ rsn_audiomunge_class_init (RsnAudioMungeClass * klass) "Jan Schmidt " }; - GST_DEBUG_CATEGORY_INIT (rsn_audiomunge_debug, "rsn_audiomunge", - 0, "Resin audio stream regulator"); + GST_DEBUG_CATEGORY_INIT (rsn_audiomunge_debug, "rsnaudiomunge", + 0, "ResinDVD audio stream regulator"); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_template)); -- cgit v1.2.1 From 79f653fde8d6ff1ecee3147ca8afb42f8cec981a Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 11 May 2009 11:06:03 +0100 Subject: resindvd: Change the audiomunge debug output. Make sure we always show information about the segment events passing through, even when pre-roll audio buffers aren't going to be needed. --- ext/resindvd/rsnaudiomunge.c | 51 +++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/rsnaudiomunge.c b/ext/resindvd/rsnaudiomunge.c index c44d7d2e..6368c49a 100644 --- a/ext/resindvd/rsnaudiomunge.c +++ b/ext/resindvd/rsnaudiomunge.c @@ -288,15 +288,12 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event) gst_segment_set_newsegment_full (segment, update, rate, arate, format, start, stop, time); - if (munge->have_audio) { - ret = gst_pad_push_event (munge->srcpad, event); - break; - } - /* * FIXME: - * If the accum >= threshold or we're in a still frame and there's been - * no audio received, then we need to generate some audio data. + * If this is a segment update and accum >= threshold, + * or we're in a still frame and there's been no audio received, + * then we need to generate some audio data. + * * If caused by a segment start update (time advancing in a gap) adjust * the new-segment and send the buffer. * @@ -304,32 +301,38 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event) * 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_DEBUG_OBJECT (munge, + "Sending newsegment: update %d start %" GST_TIME_FORMAT " stop %" + GST_TIME_FORMAT " accum now %" GST_TIME_FORMAT, update, 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) { - GST_DEBUG_OBJECT (munge, - "Sending audio fill: accum = %" GST_TIME_FORMAT " still-state=%d", - GST_TIME_ARGS (segment->accum), munge->in_still); - - /* Just generate a 100ms silence buffer for now. FIXME: Fill the gap */ - if (rsn_audiomunge_make_audio (munge, segment->start, - GST_SECOND / 10) == GST_FLOW_OK) - munge->have_audio = TRUE; - } else { - GST_LOG_OBJECT (munge, "Not sending audio fill buffer: " - "segment accum below thresh: accum = %" GST_TIME_FORMAT, - GST_TIME_ARGS (segment->accum)); + if (!munge->have_audio) { + if ((update && segment->accum >= AUDIO_FILL_THRESHOLD) + || munge->in_still) { + GST_DEBUG_OBJECT (munge, + "Sending audio fill with ts %" GST_TIME_FORMAT ": accum = %" + GST_TIME_FORMAT " still-state=%d", GST_TIME_ARGS (segment->start), + GST_TIME_ARGS (segment->accum), munge->in_still); + + /* Just generate a 100ms silence buffer for now. FIXME: Fill the gap */ + if (rsn_audiomunge_make_audio (munge, segment->start, + GST_SECOND / 10) == GST_FLOW_OK) + munge->have_audio = TRUE; + } else { + GST_LOG_OBJECT (munge, "Not sending audio fill buffer: " + "Not segment update, or segment accum below thresh: accum = %" + GST_TIME_FORMAT, 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_DEBUG_OBJECT (munge, + "Sending newsegment: update %d start %" GST_TIME_FORMAT " stop %" + GST_TIME_FORMAT " accum now %" GST_TIME_FORMAT, update, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (segment->accum)); -- cgit v1.2.1 From 4204b644ef31c498ba27847dec3e8d6dbfd4eedd Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 11 May 2009 14:17:42 +0100 Subject: resindvd: Manage timed still sequences better Make timed still frames work better by extending the current segment when needed, and restarting the still sequence with the correct remaining duration when the wait it interrupted by activation of a highlight NAV packet. --- ext/resindvd/resindvdsrc.c | 71 +++++++++++++++++++++++++++++++++------------- ext/resindvd/resindvdsrc.h | 3 ++ 2 files changed, 54 insertions(+), 20 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index f479da2a..15a2408d 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -590,6 +590,12 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration) if (src->in_still_state == FALSE) { GST_DEBUG_OBJECT (src, "**** Start STILL FRAME. Duration %d ****", duration); + + if (duration == 255) + src->still_time_remaining = GST_CLOCK_TIME_NONE; + else + src->still_time_remaining = GST_SECOND * duration; + /* Send a close-segment event, and a dvd-still start * event, then sleep */ s = gst_structure_new ("application/x-gst-dvd", @@ -622,7 +628,9 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration) src->in_still_state = TRUE; } else { - GST_DEBUG_OBJECT (src, "Re-entering still wait"); + GST_DEBUG_OBJECT (src, + "Re-entering still wait with %" GST_TIME_FORMAT " remaining", + GST_TIME_ARGS (src->still_time_remaining)); g_mutex_lock (src->branch_lock); } @@ -659,26 +667,42 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration) GTimeVal end_time; gboolean was_signalled; - g_get_current_time (&end_time); - g_time_val_add (&end_time, duration * G_USEC_PER_SEC); + if (src->still_time_remaining > 0) { + g_get_current_time (&end_time); + g_time_val_add (&end_time, src->still_time_remaining / GST_USECOND); - /* FIXME: Implement timed stills by sleeping on the clock, possibly - * in multiple steps if we get paused/unpaused */ - g_mutex_unlock (src->dvd_lock); - GST_LOG_OBJECT (src, "cond_timed_wait still for %d sec", duration); - was_signalled = - g_cond_timed_wait (src->still_cond, src->branch_lock, &end_time); - was_signalled |= src->branching; + /* Implement timed stills by sleeping, possibly + * in multiple steps if we get paused/unpaused */ + g_mutex_unlock (src->dvd_lock); + GST_LOG_OBJECT (src, "cond_timed_wait still for %d sec", duration); + was_signalled = + g_cond_timed_wait (src->still_cond, src->branch_lock, &end_time); + was_signalled |= src->branching; - g_mutex_unlock (src->branch_lock); - g_mutex_lock (src->dvd_lock); + g_mutex_unlock (src->branch_lock); + g_mutex_lock (src->dvd_lock); - if (was_signalled) { - /* Signalled - must be flushing */ - GST_LOG_OBJECT (src, - "cond_timed_wait still over. Signalled, branching = %d", - src->branching); - return TRUE; + if (was_signalled) { + /* Signalled - must be flushing */ + GTimeVal cur_time; + GstClockTimeDiff remain; + + g_get_current_time (&cur_time); + remain = + (end_time.tv_sec - cur_time.tv_sec) * GST_SECOND + + (end_time.tv_usec - cur_time.tv_usec) * GST_USECOND; + if (remain < 0) + src->still_time_remaining = 0; + else + src->still_time_remaining = remain; + + GST_LOG_OBJECT (src, + "cond_timed_wait still aborted by signal with %" GST_TIME_FORMAT + " remaining. branching = %d", + GST_TIME_ARGS (src->still_time_remaining), src->branching); + + return TRUE; + } } /* Else timed out, end the still */ @@ -690,12 +714,17 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration) } /* Tell downstream the still is over. - * Later: We'll only do this if the still isn't interrupted: */ + * We only do this if the still isn't interrupted: */ s = gst_structure_new ("application/x-gst-dvd", "event", G_TYPE_STRING, "dvd-still", "still-state", G_TYPE_BOOLEAN, FALSE, NULL); still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s); + /* If the segment was too short in a timed still, it may need extending */ + if (segment->last_stop < segment->start + GST_SECOND * duration) + gst_segment_set_last_stop (segment, GST_FORMAT_TIME, + segment->start + (GST_SECOND * duration)); + g_mutex_unlock (src->dvd_lock); gst_pad_push_event (GST_BASE_SRC_PAD (src), still_event); g_mutex_lock (src->dvd_lock); @@ -2040,8 +2069,10 @@ rsn_dvdsrc_activate_nav_block (resinDvdSrc * src, GstBuffer * nav_buf) /* highlight might change, let's check */ rsn_dvdsrc_update_highlight (src); - if (src->highlight_event) + if (src->highlight_event && src->in_still_state) { + GST_LOG_OBJECT (src, "Signalling still condition due to highlight change"); g_cond_broadcast (src->still_cond); + } } static void diff --git a/ext/resindvd/resindvdsrc.h b/ext/resindvd/resindvdsrc.h index 0d883744..d30140ea 100644 --- a/ext/resindvd/resindvdsrc.h +++ b/ext/resindvd/resindvdsrc.h @@ -90,6 +90,9 @@ struct _resinDvdSrc gboolean was_mouse_over; + /* Remaining time to wait in a timed still: */ + GstClockTime still_time_remaining; + GstBuffer *alloc_buf; GstBuffer *next_buf; /* TRUE if the next_buf is a nav block that needs enqueueing */ -- cgit v1.2.1 From d7cabb080134403871f7962bf226b36197b4d6c3 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 11 May 2009 16:09:56 +0100 Subject: resindvd: Increase the amount of filler audio generated When creating a filler audio buffer in rsnaudiomunge, generate a bit more, as audio sinks don't seem to preroll otherwise. This needs a better algorithm in general, to intelligently fill the gap, rather than hard-coding a value. --- ext/resindvd/rsnaudiomunge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/rsnaudiomunge.c b/ext/resindvd/rsnaudiomunge.c index 6368c49a..50d33be7 100644 --- a/ext/resindvd/rsnaudiomunge.c +++ b/ext/resindvd/rsnaudiomunge.c @@ -318,9 +318,9 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event) GST_TIME_FORMAT " still-state=%d", GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->accum), munge->in_still); - /* Just generate a 100ms silence buffer for now. FIXME: Fill the gap */ + /* Just generate a 200ms silence buffer for now. FIXME: Fill the gap */ if (rsn_audiomunge_make_audio (munge, segment->start, - GST_SECOND / 10) == GST_FLOW_OK) + GST_SECOND / 5) == GST_FLOW_OK) munge->have_audio = TRUE; } else { GST_LOG_OBJECT (munge, "Not sending audio fill buffer: " -- cgit v1.2.1 From 11a7e37325cae90f43a02d61cedd4ad09a2b21fd Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 11 May 2009 17:50:41 +0100 Subject: resindvd: Modify the segment update logic Send segment updates to the audio and subpicture pads more frequently, but less often to the video pad, where timestamps appear less often. This helps with gap filling on some DVDs. --- ext/resindvd/gstmpegdemux.c | 12 ++++++++++-- ext/resindvd/gstmpegdemux.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/gstmpegdemux.c b/ext/resindvd/gstmpegdemux.c index d41ded0b..ed4b3d93 100644 --- a/ext/resindvd/gstmpegdemux.c +++ b/ext/resindvd/gstmpegdemux.c @@ -28,7 +28,8 @@ #include "gstmpegdefs.h" #include "gstmpegdemux.h" -#define SEGMENT_THRESHOLD (GST_SECOND/2) +#define SEGMENT_THRESHOLD (300*GST_MSECOND) +#define VIDEO_SEGMENT_THRESHOLD (500*GST_MSECOND) /* The SCR_MUNGE value is used to offset the scr_adjust value, to avoid * ever generating a negative timestamp */ @@ -248,6 +249,7 @@ gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type) gchar *name; GstFluPSDemuxClass *klass = GST_FLUPS_DEMUX_GET_CLASS (demux); GstCaps *caps; + GstClockTime threshold = SEGMENT_THRESHOLD; name = NULL; template = NULL; @@ -277,6 +279,7 @@ gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type) caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, mpeg_version, "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); + threshold = VIDEO_SEGMENT_THRESHOLD; break; } case ST_AUDIO_MPEG1: @@ -296,6 +299,7 @@ gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type) template = klass->video_template; name = g_strdup_printf ("video_%02x", id); caps = gst_caps_new_simple ("video/x-h264", NULL); + threshold = VIDEO_SEGMENT_THRESHOLD; break; case ST_PS_AUDIO_AC3: template = klass->audio_template; @@ -335,6 +339,7 @@ gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type) stream->notlinked = FALSE; stream->type = stream_type; stream->pad = gst_pad_new_from_template (template, name); + stream->segment_thresh = threshold; gst_pad_set_event_function (stream->pad, gst_flups_demux_src_event); gst_pad_set_query_function (stream->pad, gst_flups_demux_src_query); gst_pad_use_fixed_caps (stream->pad); @@ -487,11 +492,14 @@ gst_flups_demux_send_segment_updates (GstFluPSDemux * demux, if (stream->last_ts == GST_CLOCK_TIME_NONE || stream->last_ts < demux->src_segment.start) stream->last_ts = demux->src_segment.start; - if (stream->last_ts + SEGMENT_THRESHOLD < new_time) { + if (stream->last_ts + stream->segment_thresh < new_time) { #if 0 g_print ("Segment update to pad %s time %" GST_TIME_FORMAT "\n", GST_PAD_NAME (stream->pad), GST_TIME_ARGS (new_time)); #endif + GST_DEBUG_OBJECT (demux, + "Segment update to pad %s time %" GST_TIME_FORMAT, + GST_PAD_NAME (stream->pad), GST_TIME_ARGS (new_time)); if (event == NULL) { event = gst_event_new_new_segment_full (TRUE, demux->src_segment.rate, demux->src_segment.applied_rate, diff --git a/ext/resindvd/gstmpegdemux.h b/ext/resindvd/gstmpegdemux.h index 3f38b088..b7b2d9fc 100644 --- a/ext/resindvd/gstmpegdemux.h +++ b/ext/resindvd/gstmpegdemux.h @@ -64,6 +64,7 @@ struct _GstFluPSStream { gboolean need_segment; GstClockTime last_ts; + GstClockTime segment_thresh; }; struct _GstFluPSDemux { -- cgit v1.2.1 From b769f22404ca1d566b38b50854f184b5eda628fd Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Wed, 13 May 2009 10:29:36 +0100 Subject: resindvd: Fix raciness in rsndvdbin when initially creating pads Protect pad exposure with a preroll lock to avoid situations where no-more-pads is fired more than once, or fired just before the last pad is actually added. --- ext/resindvd/resindvdbin.c | 28 ++++++++++++++++------------ ext/resindvd/resindvdbin.h | 1 + 2 files changed, 17 insertions(+), 12 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdbin.c b/ext/resindvd/resindvdbin.c index 310fac7f..e5f28288 100644 --- a/ext/resindvd/resindvdbin.c +++ b/ext/resindvd/resindvdbin.c @@ -44,6 +44,9 @@ GST_DEBUG_CATEGORY_EXTERN (resindvd_debug); #define DVDBIN_LOCK(d) g_mutex_lock((d)->dvd_lock) #define DVDBIN_UNLOCK(d) g_mutex_unlock((d)->dvd_lock) +#define DVDBIN_PREROLL_LOCK(d) g_mutex_lock((d)->preroll_lock) +#define DVDBIN_PREROLL_UNLOCK(d) g_mutex_unlock((d)->preroll_lock) + #define DEFAULT_DEVICE "/dev/dvd" enum { @@ -159,6 +162,7 @@ static void rsn_dvdbin_init (RsnDvdBin * dvdbin, RsnDvdBinClass * gclass) { dvdbin->dvd_lock = g_mutex_new (); + dvdbin->preroll_lock = g_mutex_new (); } static void @@ -167,6 +171,7 @@ rsn_dvdbin_finalize (GObject * object) RsnDvdBin *dvdbin = RESINDVDBIN (object); g_mutex_free (dvdbin->dvd_lock); + g_mutex_free (dvdbin->preroll_lock); g_free (dvdbin->last_uri); g_free (dvdbin->device); @@ -741,58 +746,57 @@ failed: static void dvdbin_pad_blocked_cb (GstPad * pad, gboolean blocked, RsnDvdBin * dvdbin) { - gboolean changed = FALSE; + gboolean added_last_pad = FALSE; gboolean added = FALSE; if (!blocked) return; if (pad == dvdbin->subpicture_pad) { GST_DEBUG_OBJECT (dvdbin, "Pad block -> subpicture pad"); - GST_OBJECT_LOCK (dvdbin); + DVDBIN_PREROLL_LOCK (dvdbin); added = dvdbin->subpicture_added; dvdbin->subpicture_added = TRUE; - GST_OBJECT_UNLOCK (dvdbin); if (!added) { gst_element_add_pad (GST_ELEMENT (dvdbin), dvdbin->subpicture_pad); - changed = TRUE; + added_last_pad = (dvdbin->audio_added && dvdbin->video_added); } + DVDBIN_PREROLL_UNLOCK (dvdbin); gst_pad_set_blocked_async (pad, FALSE, (GstPadBlockCallback) dvdbin_pad_blocked_cb, dvdbin); } else if (pad == dvdbin->audio_pad) { GST_DEBUG_OBJECT (dvdbin, "Pad block -> audio pad"); - GST_OBJECT_LOCK (dvdbin); + DVDBIN_PREROLL_LOCK (dvdbin); added = dvdbin->audio_added; dvdbin->audio_added = TRUE; - GST_OBJECT_UNLOCK (dvdbin); if (!added) { gst_element_add_pad (GST_ELEMENT (dvdbin), dvdbin->audio_pad); - changed = TRUE; + added_last_pad = (dvdbin->subpicture_added && dvdbin->video_added); } + DVDBIN_PREROLL_UNLOCK (dvdbin); gst_pad_set_blocked_async (pad, FALSE, (GstPadBlockCallback) dvdbin_pad_blocked_cb, dvdbin); } else if (pad == dvdbin->video_pad) { GST_DEBUG_OBJECT (dvdbin, "Pad block -> video pad"); - GST_OBJECT_LOCK (dvdbin); + DVDBIN_PREROLL_LOCK (dvdbin); added = dvdbin->video_added; dvdbin->video_added = TRUE; - GST_OBJECT_UNLOCK (dvdbin); if (!added) { gst_element_add_pad (GST_ELEMENT (dvdbin), dvdbin->video_pad); - changed = TRUE; + added_last_pad = (dvdbin->subpicture_added && dvdbin->audio_added); } + DVDBIN_PREROLL_UNLOCK (dvdbin); gst_pad_set_blocked_async (pad, FALSE, (GstPadBlockCallback) dvdbin_pad_blocked_cb, dvdbin); } - if (changed && - dvdbin->video_added && dvdbin->audio_added && dvdbin->subpicture_added) { + if (added_last_pad) { GST_DEBUG_OBJECT (dvdbin, "Firing no more pads from pad-blocked cb"); gst_element_no_more_pads (GST_ELEMENT (dvdbin)); } diff --git a/ext/resindvd/resindvdbin.h b/ext/resindvd/resindvdbin.h index 5a063f4f..d9aa1078 100644 --- a/ext/resindvd/resindvdbin.h +++ b/ext/resindvd/resindvdbin.h @@ -58,6 +58,7 @@ struct _RsnDvdBin /* Protects pieces list and properties */ GMutex *dvd_lock; + GMutex *preroll_lock; gchar *device; gchar *last_uri; -- cgit v1.2.1 From d9fef92ea03961f2bf7a1fc75c99223ecf35f168 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 14 May 2009 08:42:24 +0100 Subject: resindvd: Fix a leak of the DVD title string --- ext/resindvd/resindvdsrc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 15a2408d..37fc9da9 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -842,6 +842,7 @@ update_title_info (resinDvdSrc * src) GstTagList *tags = gst_tag_list_new (); gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, title_str, NULL); + g_free (title_str); gst_element_found_tags (GST_ELEMENT_CAST (src), tags); } } -- cgit v1.2.1 From 73f77c04aacd5e6ad97e34546a7a9517b430a901 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Tue, 12 May 2009 23:42:00 +0100 Subject: resindvd: Send commands-changed on button change and handle commands query Send the commands-changed navigation message when the set of available DVD menu button actions changes, and handle the commands navigation query so that (e.g.) Totem can know about the available navigation commands. --- ext/resindvd/resindvdsrc.c | 95 +++++++++++++++++++++++++++++++++++++++++++--- ext/resindvd/resindvdsrc.h | 2 + 2 files changed, 92 insertions(+), 5 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 37fc9da9..3b635abc 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -53,6 +53,15 @@ typedef enum RSN_NAV_RESULT_BRANCH_AND_HIGHLIGHT } RsnNavResult; +typedef enum +{ + RSN_BTN_NONE = 0x00, + RSN_BTN_LEFT = 0x01, + RSN_BTN_RIGHT = 0x02, + RSN_BTN_UP = 0x04, + RSN_BTN_DOWN = 0x04 +} RsnBtnMask; + enum { /* FILL ME */ @@ -395,6 +404,7 @@ rsn_dvdsrc_start (RsnBaseSrc * bsrc) src->part_n = -1; src->active_button = -1; + src->cur_btn_mask = RSN_BTN_NONE; src->angles_changed = FALSE; src->n_angles = 0; @@ -583,6 +593,7 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration) { GstEvent *still_event; GstEvent *hl_event; + gboolean cmds_changed; GstStructure *s; GstEvent *seg_event; GstSegment *segment = &(GST_BASE_SRC (src)->segment); @@ -612,6 +623,8 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration) /* Grab any pending highlight event to send too */ hl_event = src->highlight_event; src->highlight_event = NULL; + cmds_changed = src->commands_changed; + src->commands_changed = FALSE; /* Now, send the events. We need to drop the dvd lock while doing so, * and then check after if we got flushed */ @@ -622,6 +635,9 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration) GST_LOG_OBJECT (src, "Sending highlight event before still"); gst_pad_push_event (GST_BASE_SRC_PAD (src), hl_event); } + if (cmds_changed) + rsn_dvdsrc_send_commands_changed (src); + g_mutex_lock (src->dvd_lock); g_mutex_lock (src->branch_lock); @@ -1106,7 +1122,46 @@ rsn_dvdsrc_send_commands_changed (resinDvdSrc * src) static gboolean rsn_dvdsrc_handle_cmds_query (resinDvdSrc * src, GstQuery * query) { - return FALSE; + /* Expand this array if we have more commands in the future: */ + GstNavigationCommand cmds[16]; + gint n_cmds = 0; + + /* Fill out the standard set of commands we support */ + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_DVD_MENU; + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_DVD_TITLE_MENU; + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_DVD_ROOT_MENU; + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_DVD_SUBPICTURE_MENU; + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_DVD_AUDIO_MENU; + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_DVD_ANGLE_MENU; + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_DVD_CHAPTER_MENU; + + g_mutex_lock (src->dvd_lock); + + /* Multiple angles available? */ + if (src->n_angles > 1) { + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_PREV_ANGLE; + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_NEXT_ANGLE; + } + + /* Add button selection commands if we have them */ + if (src->active_button > 0) { + /* We have a valid current button */ + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_ACTIVATE; + } + /* Check for buttons in each direction */ + if (src->cur_btn_mask & RSN_BTN_LEFT) + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_LEFT; + if (src->cur_btn_mask & RSN_BTN_RIGHT) + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_RIGHT; + if (src->cur_btn_mask & RSN_BTN_UP) + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_UP; + if (src->cur_btn_mask & RSN_BTN_DOWN) + cmds[n_cmds++] = GST_NAVIGATION_COMMAND_DOWN; + g_mutex_unlock (src->dvd_lock); + + gst_navigation_query_set_commandsv (query, n_cmds, cmds); + + return TRUE; } static gboolean @@ -1131,6 +1186,9 @@ rsn_dvdsrc_handle_navigation_query (resinDvdSrc * src, GstNavigationQueryType nq_type, GstQuery * query) { gboolean res; + + GST_LOG_OBJECT (src, "Have Navigation query of type %d", nq_type); + switch (nq_type) { case GST_NAVIGATION_QUERY_COMMANDS: res = rsn_dvdsrc_handle_cmds_query (src, query); @@ -1211,10 +1269,8 @@ rsn_dvdsrc_create (RsnPushSrc * psrc, GstBuffer ** outbuf) src->angles_changed = FALSE; } - if (src->commands_changed) { - cmds_changed = TRUE; - src->commands_changed = FALSE; - } + cmds_changed = src->commands_changed; + src->commands_changed = FALSE; g_mutex_unlock (src->dvd_lock); @@ -1600,6 +1656,7 @@ rsn_dvdsrc_handle_navigation_event (resinDvdSrc * src, GstEvent * event) if (have_lock) { gboolean channel_hop = FALSE; + gboolean cmds_changed; if (nav_res != RSN_NAV_RESULT_NONE) { if (nav_res == RSN_NAV_RESULT_BRANCH) { @@ -1660,6 +1717,9 @@ rsn_dvdsrc_handle_navigation_event (resinDvdSrc * src, GstEvent * event) update_title_info (src); } + cmds_changed = src->commands_changed; + src->commands_changed = FALSE; + g_mutex_unlock (src->dvd_lock); if (hl_event) { @@ -1667,6 +1727,9 @@ rsn_dvdsrc_handle_navigation_event (resinDvdSrc * src, GstEvent * event) src->active_button); gst_pad_push_event (GST_BASE_SRC_PAD (src), hl_event); } + + if (cmds_changed) + rsn_dvdsrc_send_commands_changed (src); } if (mouse_over_msg) { @@ -1978,6 +2041,10 @@ rsn_dvdsrc_update_highlight (resinDvdSrc * src) if (src->highlight_event) gst_event_unref (src->highlight_event); src->highlight_event = event; + if (src->cur_btn_mask != RSN_BTN_NONE) { + src->cur_btn_mask = RSN_BTN_NONE; + src->commands_changed = TRUE; + } } return; } @@ -1996,6 +2063,8 @@ rsn_dvdsrc_update_highlight (resinDvdSrc * src) area.sx != src->area.sx || area.sy != src->area.sy || area.ex != src->area.ex || area.ey != src->area.ey || area.palette != src->area.palette) { + btni_t *btn_info = pci->hli.btnit + button - 1; + guint32 btn_mask; GST_DEBUG_OBJECT (src, "Setting highlight. Button %d @ %d,%d " "active %d palette 0x%x (from button %d @ %d,%d palette 0x%x)", @@ -2026,6 +2095,22 @@ rsn_dvdsrc_update_highlight (resinDvdSrc * src) if (src->highlight_event) gst_event_unref (src->highlight_event); src->highlight_event = event; + + /* Calculate whether the available set of button motions is changed */ + btn_mask = 0; + if (btn_info->left && btn_info->left != button) + btn_mask |= RSN_BTN_LEFT; + if (btn_info->right && btn_info->right != button) + btn_mask |= RSN_BTN_RIGHT; + if (btn_info->up && btn_info->up != button) + btn_mask |= RSN_BTN_UP; + if (btn_info->down && btn_info->down != button) + btn_mask |= RSN_BTN_DOWN; + + if (btn_mask != src->cur_btn_mask) { + src->cur_btn_mask = btn_mask; + src->commands_changed = TRUE; + } } } diff --git a/ext/resindvd/resindvdsrc.h b/ext/resindvd/resindvdsrc.h index d30140ea..263c7afb 100644 --- a/ext/resindvd/resindvdsrc.h +++ b/ext/resindvd/resindvdsrc.h @@ -141,6 +141,8 @@ struct _resinDvdSrc gint8 cur_spu_phys_stream; gboolean cur_spu_forced_only; guint32 cur_clut[16]; + + guint32 cur_btn_mask; }; struct _resinDvdSrcClass -- cgit v1.2.1 From cae9db0d8c4c3ff939ac6ac1d4d574b2c030b536 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Wed, 13 May 2009 12:47:43 +0100 Subject: resindvd: Rework button highlight calculation slightly When the current button number is higher than the number of available buttons, switch to the highest numbered button rather than the lowest. Also, don't throw errors when we fail to retrieve some button info from libdvdnav, just reset the highlight. --- ext/resindvd/resindvdsrc.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 3b635abc..bdf74ced 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -1069,6 +1069,9 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock) break; } case DVDNAV_HIGHLIGHT:{ + dvdnav_highlight_event_t *event = (dvdnav_highlight_event_t *) data; + GST_DEBUG_OBJECT (src, "highlight change event, button %d", + event->buttonN); rsn_dvdsrc_update_highlight (src); break; } @@ -2011,21 +2014,26 @@ rsn_dvdsrc_update_highlight (resinDvdSrc * src) int button = 0; pci_t *pci = &src->cur_pci; dvdnav_highlight_area_t area; - int mode = 0; + int mode = src->active_highlight ? 1 : 0; GstEvent *event = NULL; GstStructure *s; if (src->have_pci) { - if (dvdnav_get_current_highlight (src->dvdnav, &button) != DVDNAV_STATUS_OK) { - GST_ELEMENT_ERROR (src, LIBRARY, FAILED, (NULL), - ("dvdnav_get_current_highlight: %s", - dvdnav_err_to_string (src->dvdnav))); - return; + if (dvdnav_get_current_highlight (src->dvdnav, &button) == DVDNAV_STATUS_OK) { + GST_LOG_OBJECT (src, "current dvdnav button is %d, we have %d", + button, src->active_button); } - if (pci->hli.hl_gi.hli_ss == 0 || (button > pci->hli.hl_gi.btn_ns) || - (button < 1)) { + if (pci->hli.hl_gi.hli_ss == 0 || button < 0) { + button = 0; + } else if (button > pci->hli.hl_gi.btn_ns) { /* button is out of the range of possible buttons. */ + button = pci->hli.hl_gi.btn_ns; + dvdnav_button_select (src->dvdnav, &src->cur_pci, button); + } + + if (button > 0 && dvdnav_get_highlight_area (pci, button, mode, + &area) != DVDNAV_STATUS_OK) { button = 0; } } @@ -2049,15 +2057,6 @@ rsn_dvdsrc_update_highlight (resinDvdSrc * src) return; } - if (src->active_highlight) - mode = 1; - - if (dvdnav_get_highlight_area (pci, button, mode, &area) != DVDNAV_STATUS_OK) { - GST_ELEMENT_ERROR (src, LIBRARY, FAILED, (NULL), - ("dvdnav_get_highlight_area: %s", dvdnav_err_to_string (src->dvdnav))); - return; - } - /* Check if we have a new button number, or a new highlight region. */ if (button != src->active_button || area.sx != src->area.sx || area.sy != src->area.sy || @@ -2149,12 +2148,14 @@ rsn_dvdsrc_activate_nav_block (resinDvdSrc * src, GstBuffer * nav_buf) src->have_pci = TRUE; forced_button = src->cur_pci.hli.hl_gi.fosl_btnn & 0x3f; - - if (forced_button != 0) + if (forced_button != 0) { + GST_DEBUG_OBJECT (src, "Selecting button %d based on nav packet command", + forced_button); dvdnav_button_select (src->dvdnav, &src->cur_pci, forced_button); - + } /* highlight might change, let's check */ rsn_dvdsrc_update_highlight (src); + if (src->highlight_event && src->in_still_state) { GST_LOG_OBJECT (src, "Signalling still condition due to highlight change"); g_cond_broadcast (src->still_cond); -- cgit v1.2.1 From 13694cd654cef130bd97d2498f5e65e8da525722 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 14 May 2009 09:53:25 +0100 Subject: resindvd: Make segment updates less aggressive. When updating a pad, send the update to half a second behind the SCR, which avoids ever updating the start time for a pad to beyond the end of the cell. Also, remember the last actual new-segment start time for each pad, and use it when closing the segment. --- ext/resindvd/gstmpegdemux.c | 38 +++++++++++++++++++++++++------------- ext/resindvd/gstmpegdemux.h | 1 + 2 files changed, 26 insertions(+), 13 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/gstmpegdemux.c b/ext/resindvd/gstmpegdemux.c index ed4b3d93..b360bdcc 100644 --- a/ext/resindvd/gstmpegdemux.c +++ b/ext/resindvd/gstmpegdemux.c @@ -469,7 +469,7 @@ gst_flups_demux_clear_times (GstFluPSDemux * demux) GstFluPSStream *stream = demux->streams[id]; if (stream) { - stream->last_ts = GST_CLOCK_TIME_NONE; + stream->last_seg_start = stream->last_ts = GST_CLOCK_TIME_NONE; } } } @@ -494,8 +494,9 @@ gst_flups_demux_send_segment_updates (GstFluPSDemux * demux, stream->last_ts = demux->src_segment.start; if (stream->last_ts + stream->segment_thresh < new_time) { #if 0 - g_print ("Segment update to pad %s time %" GST_TIME_FORMAT "\n", - GST_PAD_NAME (stream->pad), GST_TIME_ARGS (new_time)); + g_print ("Segment update to pad %s time %" GST_TIME_FORMAT " stop now %" + GST_TIME_FORMAT "\n", GST_PAD_NAME (stream->pad), + GST_TIME_ARGS (new_time), GST_TIME_ARGS (demux->src_segment.stop)); #endif GST_DEBUG_OBJECT (demux, "Segment update to pad %s time %" GST_TIME_FORMAT, @@ -509,7 +510,7 @@ gst_flups_demux_send_segment_updates (GstFluPSDemux * demux, } gst_event_ref (event); gst_pad_push_event (stream->pad, event); - stream->last_ts = new_time; + stream->last_seg_start = stream->last_ts = new_time; } } } @@ -528,23 +529,30 @@ gst_flups_demux_send_segment_close (GstFluPSDemux * demux) GstFluPSStream *stream = demux->streams[id]; if (stream) { - if (stream->last_ts == GST_CLOCK_TIME_NONE || - stream->last_ts < demux->src_segment.start) - stream->last_ts = demux->src_segment.start; + GstClockTime start = demux->src_segment.start; + if (stream->last_seg_start != GST_CLOCK_TIME_NONE && + stream->last_seg_start > start) + start = stream->last_seg_start; #if 0 - g_print ("Segment update to pad %s start %" GST_TIME_FORMAT + g_print ("Segment close to pad %s start %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT "\n", - GST_PAD_NAME (stream->pad), GST_TIME_ARGS (stream->last_ts), + GST_PAD_NAME (stream->pad), GST_TIME_ARGS (start), GST_TIME_ARGS (demux->src_segment.stop)); #endif + if (start > demux->src_segment.stop) { + g_print ("Problem on pad %s with start %" GST_TIME_FORMAT " > stop %" + GST_TIME_FORMAT "\n", + gst_object_get_name (GST_OBJECT (stream->pad)), + GST_TIME_ARGS (start), GST_TIME_ARGS (demux->src_segment.stop)); + } event = gst_event_new_new_segment_full (TRUE, demux->src_segment.rate, demux->src_segment.applied_rate, - GST_FORMAT_TIME, stream->last_ts, + GST_FORMAT_TIME, start, demux->src_segment.stop, - demux->src_segment.time + - (stream->last_ts - demux->src_segment.start)); - gst_pad_push_event (stream->pad, event); + demux->src_segment.time + (start - demux->src_segment.start)); + if (event) + gst_pad_push_event (stream->pad, event); } } } @@ -1354,6 +1362,10 @@ gst_flups_demux_parse_pack_start (GstFluPSDemux * demux) new_time = MPEGTIME_TO_GSTTIME (scr_adjusted); if (new_time != GST_CLOCK_TIME_NONE) { // g_print ("SCR now %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (new_time)); + if (new_time > GST_SECOND / 2) + new_time -= GST_SECOND / 2; + else + new_time = 0; gst_flups_demux_send_segment_updates (demux, new_time); demux->src_segment.last_stop = new_time; } diff --git a/ext/resindvd/gstmpegdemux.h b/ext/resindvd/gstmpegdemux.h index b7b2d9fc..683b7cde 100644 --- a/ext/resindvd/gstmpegdemux.h +++ b/ext/resindvd/gstmpegdemux.h @@ -63,6 +63,7 @@ struct _GstFluPSStream { gboolean notlinked; gboolean need_segment; + GstClockTime last_seg_start; GstClockTime last_ts; GstClockTime segment_thresh; }; -- cgit v1.2.1 From e62b64f1d34ec402f8fce4f91f174d40315576c9 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 14 May 2009 10:34:08 +0100 Subject: resindvd: Fix the argument order in a debug statement Make the debug statement correctly show the 'old' and 'new' button coordinates, instead of the wrong way around. --- ext/resindvd/resindvdsrc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index bdf74ced..f24e45aa 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -2065,10 +2065,12 @@ rsn_dvdsrc_update_highlight (resinDvdSrc * src) btni_t *btn_info = pci->hli.btnit + button - 1; guint32 btn_mask; - GST_DEBUG_OBJECT (src, "Setting highlight. Button %d @ %d,%d " - "active %d palette 0x%x (from button %d @ %d,%d palette 0x%x)", - button, src->area.sx, src->area.sy, mode, src->area.palette, - src->active_button, area.sx, area.sy, area.palette); + GST_DEBUG_OBJECT (src, "Setting highlight. Button %d @ %d,%d,%d,%d " + "active %d palette 0x%x (from button %d @ %d,%d,%d,%d palette 0x%x)", + button, area.sx, area.sy, area.ex, area.ey, + mode, area.palette, + src->active_button, src->area.sx, src->area.sy, src->area.ex, + src->area.ey, src->area.palette); memcpy (&(src->area), &area, sizeof (dvdnav_highlight_area_t)); -- cgit v1.2.1 From 462419f279a8ff865a570795462028fd9435f6a8 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 21 May 2009 11:10:13 +0100 Subject: resindvd: Minor change to inline a function in the demuxer --- ext/resindvd/gstmpegdemux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/gstmpegdemux.c b/ext/resindvd/gstmpegdemux.c index b360bdcc..8e513469 100644 --- a/ext/resindvd/gstmpegdemux.c +++ b/ext/resindvd/gstmpegdemux.c @@ -1861,7 +1861,7 @@ need_data: } } -static gboolean +static inline gboolean gst_flups_demux_is_pes_sync (guint32 sync) { return ((sync & 0xfc) == 0xbc) || -- cgit v1.2.1 From 59a3abfdf346d2b428057d23fc69f5ef7c3b659f Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 22 May 2009 14:02:38 +0100 Subject: resindvd: Try a different approach to segment filling. Restore the old segment update behaviour, and instead extend the close segment stop time if the SCR (last_stop) overruns the calculated stop position. --- ext/resindvd/gstmpegdemux.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/gstmpegdemux.c b/ext/resindvd/gstmpegdemux.c index 8e513469..8ea82b44 100644 --- a/ext/resindvd/gstmpegdemux.c +++ b/ext/resindvd/gstmpegdemux.c @@ -495,8 +495,10 @@ gst_flups_demux_send_segment_updates (GstFluPSDemux * demux, if (stream->last_ts + stream->segment_thresh < new_time) { #if 0 g_print ("Segment update to pad %s time %" GST_TIME_FORMAT " stop now %" - GST_TIME_FORMAT "\n", GST_PAD_NAME (stream->pad), - GST_TIME_ARGS (new_time), GST_TIME_ARGS (demux->src_segment.stop)); + GST_TIME_FORMAT " last_stop %" GST_TIME_FORMAT "\n", + GST_PAD_NAME (stream->pad), GST_TIME_ARGS (new_time), + GST_TIME_ARGS (demux->src_segment.stop), + GST_TIME_ARGS (demux->src_segment.last_stop)); #endif GST_DEBUG_OBJECT (demux, "Segment update to pad %s time %" GST_TIME_FORMAT, @@ -524,6 +526,10 @@ gst_flups_demux_send_segment_close (GstFluPSDemux * demux) { gint id; GstEvent *event = NULL; + GstClockTime stop = demux->src_segment.stop; + + if (demux->src_segment.last_stop != -1 && demux->src_segment.last_stop > stop) + stop = demux->src_segment.last_stop; for (id = 0; id < GST_FLUPS_DEMUX_MAX_STREAMS; id++) { GstFluPSStream *stream = demux->streams[id]; @@ -534,23 +540,23 @@ gst_flups_demux_send_segment_close (GstFluPSDemux * demux) if (stream->last_seg_start != GST_CLOCK_TIME_NONE && stream->last_seg_start > start) start = stream->last_seg_start; + #if 0 g_print ("Segment close to pad %s start %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT "\n", GST_PAD_NAME (stream->pad), GST_TIME_ARGS (start), - GST_TIME_ARGS (demux->src_segment.stop)); + GST_TIME_ARGS (stop)); #endif - if (start > demux->src_segment.stop) { + if (start > stop) { g_print ("Problem on pad %s with start %" GST_TIME_FORMAT " > stop %" GST_TIME_FORMAT "\n", gst_object_get_name (GST_OBJECT (stream->pad)), - GST_TIME_ARGS (start), GST_TIME_ARGS (demux->src_segment.stop)); + GST_TIME_ARGS (start), GST_TIME_ARGS (stop)); } event = gst_event_new_new_segment_full (TRUE, demux->src_segment.rate, demux->src_segment.applied_rate, GST_FORMAT_TIME, start, - demux->src_segment.stop, - demux->src_segment.time + (start - demux->src_segment.start)); + stop, demux->src_segment.time + (start - demux->src_segment.start)); if (event) gst_pad_push_event (stream->pad, event); } @@ -872,8 +878,12 @@ gst_flups_demux_sink_event (GstPad * pad, GstEvent * event) else demux->scr_adjust = -GSTTIME_TO_MPEGTIME (-adjust); - if (stop != -1) + if (stop != -1) { stop = start + dur; + if (demux->src_segment.last_stop != -1 + && demux->src_segment.last_stop > stop) + stop = demux->src_segment.last_stop; + } GST_DEBUG_OBJECT (demux, "sending new segment: update %d rate %g format %d, start: %" @@ -1362,12 +1372,8 @@ gst_flups_demux_parse_pack_start (GstFluPSDemux * demux) new_time = MPEGTIME_TO_GSTTIME (scr_adjusted); if (new_time != GST_CLOCK_TIME_NONE) { // g_print ("SCR now %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (new_time)); - if (new_time > GST_SECOND / 2) - new_time -= GST_SECOND / 2; - else - new_time = 0; + gst_segment_set_last_stop (&demux->src_segment, GST_FORMAT_TIME, new_time); gst_flups_demux_send_segment_updates (demux, new_time); - demux->src_segment.last_stop = new_time; } /* Reset the bytes_since_scr value to count the data remaining in the -- cgit v1.2.1 From 19d450a16425ea7844c9970a9ca325236897780b Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 25 May 2009 00:25:07 +0100 Subject: resindvd: Fix subpicture timing in some cases Make sure we send events to all pads. Unmark the notlinked flag on freshly selected pads to ensure they get data. --- ext/resindvd/gstmpegdemux.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/gstmpegdemux.c b/ext/resindvd/gstmpegdemux.c index 8ea82b44..281b13f3 100644 --- a/ext/resindvd/gstmpegdemux.c +++ b/ext/resindvd/gstmpegdemux.c @@ -572,7 +572,7 @@ gst_flups_demux_send_event (GstFluPSDemux * demux, GstEvent * event) for (id = 0; id < GST_FLUPS_DEMUX_MAX_STREAMS; id++) { GstFluPSStream *stream = demux->streams[id]; - if (stream && !stream->notlinked) { + if (stream) { (void) gst_event_ref (event); if (!gst_pad_push_event (stream->pad, event)) { @@ -739,6 +739,8 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event) "event", G_TYPE_STRING, "select-pad", NULL); GstEvent *sel_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s); + + temp->notlinked = FALSE; gst_pad_push_event (temp->pad, sel_event); gst_event_ref (event); -- cgit v1.2.1 From 8f70498c898a65d0938e3e104e91662ff5b693c3 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Tue, 26 May 2009 19:38:54 +0100 Subject: resindvd: LPCM streams are only from 0xa0 to 0xaf. Fix the same bug as the previous commit, but in resindvd's copy of mpegdemux. --- ext/resindvd/gstmpegdemux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/resindvd') diff --git a/ext/resindvd/gstmpegdemux.c b/ext/resindvd/gstmpegdemux.c index 281b13f3..5ab26107 100644 --- a/ext/resindvd/gstmpegdemux.c +++ b/ext/resindvd/gstmpegdemux.c @@ -1162,7 +1162,7 @@ gst_flups_demux_reset_psm (GstFluPSDemux * demux) FILL_TYPE (0x40, 0x7f, -1); FILL_TYPE (0x80, 0x87, ST_PS_AUDIO_AC3); FILL_TYPE (0x88, 0x9f, ST_PS_AUDIO_DTS); - FILL_TYPE (0xa0, 0xbf, ST_PS_AUDIO_LPCM); + FILL_TYPE (0xa0, 0xaf, ST_PS_AUDIO_LPCM); FILL_TYPE (0xbd, 0xbd, -1); FILL_TYPE (0xc0, 0xdf, ST_AUDIO_MPEG1); FILL_TYPE (0xe0, 0xef, ST_GST_VIDEO_MPEG1_OR_2); -- cgit v1.2.1