mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
ext/resindvd/: Add in Title/Chapter seeking, and simple but buggy audio and subtitle stream selection.
Original commit message from CVS: * ext/resindvd/gstmpegdemux.c: * ext/resindvd/gstmpegdemux.h: * ext/resindvd/resindvdbin.c: * ext/resindvd/resindvdsrc.c: * ext/resindvd/rsnstreamselector.c: Add in Title/Chapter seeking, and simple but buggy audio and subtitle stream selection.
This commit is contained in:
parent
a51c4c16b2
commit
a8736df9b5
5 changed files with 291 additions and 54 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2008-09-27 Jan Schmidt <jan.schmidt@sun.com>
|
||||
|
||||
* ext/resindvd/gstmpegdemux.c:
|
||||
* ext/resindvd/gstmpegdemux.h:
|
||||
* ext/resindvd/resindvdbin.c:
|
||||
* ext/resindvd/resindvdsrc.c:
|
||||
* ext/resindvd/rsnstreamselector.c:
|
||||
Add in Title/Chapter seeking, and simple but buggy audio
|
||||
and subtitle stream selection.
|
||||
|
||||
2008-09-24 Michael Smith <msmith@songbirdnest.com>
|
||||
|
||||
* sys/dshowdecwrapper/gstdshowaudiodec.cpp:
|
||||
|
|
|
@ -28,9 +28,6 @@
|
|||
#include "gstmpegdefs.h"
|
||||
#include "gstmpegdemux.h"
|
||||
|
||||
#define MAX_DVD_AUDIO_STREAMS 8
|
||||
#define MAX_DVD_SUBPICTURE_STREAMS 32
|
||||
|
||||
#define SEGMENT_THRESHOLD (GST_SECOND/2)
|
||||
|
||||
/* The SCR_MUNGE value is used to offset the scr_adjust value, to avoid
|
||||
|
@ -581,6 +578,7 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
|
|||
gint i;
|
||||
gchar cur_stream_name[32];
|
||||
GstFluPSStream *temp;
|
||||
gboolean ret = TRUE;
|
||||
|
||||
if (strcmp (type, "dvd-lang-codes") == 0) {
|
||||
GstEvent **p_ev;
|
||||
|
@ -624,6 +622,8 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
|
|||
if (!gst_structure_get_int (structure, cur_stream_name, &stream_format))
|
||||
continue;
|
||||
|
||||
demux->audio_stream_types[i] = stream_format;
|
||||
|
||||
switch (stream_format) {
|
||||
case 0x0:
|
||||
/* AC3 */
|
||||
|
@ -678,10 +678,89 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
|
|||
gst_element_no_more_pads (GST_ELEMENT (demux));
|
||||
demux->need_no_more_pads = FALSE;
|
||||
gst_event_unref (event);
|
||||
} else if (strcmp (type, "dvd-set-subpicture-track") == 0) {
|
||||
gint stream_id;
|
||||
gboolean forced_only;
|
||||
|
||||
gst_structure_get_boolean (structure, "forced-only", &forced_only);
|
||||
|
||||
if (gst_structure_get_int (structure, "physical-id", &stream_id)) {
|
||||
temp = demux->streams[0x20 + stream_id];
|
||||
if (temp != NULL && temp->pad != NULL) {
|
||||
/* Send event to the selector to activate the desired pad */
|
||||
GstStructure *s = gst_structure_new ("application/x-gst-dvd",
|
||||
"event", G_TYPE_STRING, "select-pad", NULL);
|
||||
GstEvent *sel_event =
|
||||
gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
|
||||
gst_pad_push_event (temp->pad, sel_event);
|
||||
|
||||
gst_event_ref (event);
|
||||
ret = gst_pad_push_event (temp->pad, event);
|
||||
g_print ("Subpicture physical ID change to %d, forced %d\n", stream_id,
|
||||
forced_only);
|
||||
}
|
||||
}
|
||||
gst_event_unref (event);
|
||||
} else if (strcmp (type, "dvd-set-audio-track") == 0) {
|
||||
gint stream_id;
|
||||
|
||||
if (gst_structure_get_int (structure, "physical-id", &stream_id)) {
|
||||
gint aud_type;
|
||||
|
||||
stream_id %= MAX_DVD_AUDIO_STREAMS;
|
||||
|
||||
aud_type = demux->audio_stream_types[stream_id % MAX_DVD_AUDIO_STREAMS];
|
||||
|
||||
switch (aud_type) {
|
||||
case 0x0:
|
||||
/* AC3 */
|
||||
stream_id += 0x80;
|
||||
temp = demux->streams[stream_id];
|
||||
break;
|
||||
#if 0 /* FIXME: Ignore non AC-3 requests until the decoder bin can handle them */
|
||||
case 0x2:
|
||||
case 0x3:
|
||||
/* MPEG audio without and with extension stream are
|
||||
* treated the same */
|
||||
stream_id = 0xC0 + i;
|
||||
temp = demux->streams[stream_id];
|
||||
break;
|
||||
case 0x4:
|
||||
/* LPCM */
|
||||
stream_id = 0xA0 + i;
|
||||
temp = demux->streams[stream_id];
|
||||
break;
|
||||
case 0x6:
|
||||
/* DTS */
|
||||
stream_id = 0x88 + i;
|
||||
temp = demux->streams[stream_id];
|
||||
break;
|
||||
case 0x7:
|
||||
/* FIXME: What range is SDDS? */
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
temp = NULL;
|
||||
break;
|
||||
}
|
||||
if (temp != NULL && temp->pad != NULL) {
|
||||
/* Send event to the selector to activate the desired pad */
|
||||
GstStructure *s = gst_structure_new ("application/x-gst-dvd",
|
||||
"event", G_TYPE_STRING, "select-pad", NULL);
|
||||
GstEvent *sel_event =
|
||||
gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
|
||||
gst_pad_push_event (temp->pad, sel_event);
|
||||
g_print ("Audio physical ID change to %d\n", stream_id);
|
||||
|
||||
gst_event_ref (event);
|
||||
ret = gst_pad_push_event (temp->pad, event);
|
||||
}
|
||||
}
|
||||
ret = gst_flups_demux_send_event (demux, event);
|
||||
} else {
|
||||
gst_flups_demux_send_event (demux, event);
|
||||
ret = gst_flups_demux_send_event (demux, event);
|
||||
}
|
||||
return TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -42,6 +42,8 @@ typedef struct _GstFluPSDemuxClass GstFluPSDemuxClass;
|
|||
|
||||
#define GST_FLUPS_DEMUX_MAX_STREAMS 256
|
||||
#define GST_FLUPS_DEMUX_MAX_PSM 256
|
||||
#define MAX_DVD_AUDIO_STREAMS 8
|
||||
#define MAX_DVD_SUBPICTURE_STREAMS 32
|
||||
|
||||
typedef enum {
|
||||
STATE_FLUPS_DEMUX_NEED_SYNC,
|
||||
|
@ -106,6 +108,7 @@ struct _GstFluPSDemux {
|
|||
/* Language codes event is stored when a dvd-lang-codes
|
||||
* custom event arrives from upstream */
|
||||
GstEvent * lang_codes;
|
||||
gint audio_stream_types[MAX_DVD_AUDIO_STREAMS];
|
||||
};
|
||||
|
||||
struct _GstFluPSDemuxClass {
|
||||
|
|
|
@ -84,6 +84,9 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
|||
|
||||
/* Private seek format for private flushing */
|
||||
static GstFormat rsndvd_format;
|
||||
/* Title/chapter formats */
|
||||
static GstFormat title_format;
|
||||
static GstFormat chapter_format;
|
||||
|
||||
static void rsn_dvdsrc_register_extra (GType rsn_dvdsrc_type);
|
||||
|
||||
|
@ -104,6 +107,7 @@ static gboolean rsn_dvdsrc_stop (RsnBaseSrc * bsrc);
|
|||
static gboolean rsn_dvdsrc_unlock (RsnBaseSrc * bsrc);
|
||||
static gboolean rsn_dvdsrc_unlock_stop (RsnBaseSrc * bsrc);
|
||||
|
||||
static gboolean rsn_dvdsrc_is_seekable (RsnBaseSrc * bsrc);
|
||||
static gboolean rsn_dvdsrc_prepare_seek (RsnBaseSrc * bsrc, GstEvent * event,
|
||||
GstSegment * segment);
|
||||
static gboolean rsn_dvdsrc_do_seek (RsnBaseSrc * bsrc, GstSegment * segment);
|
||||
|
@ -163,6 +167,9 @@ rsn_dvdsrc_register_extra (GType rsn_dvdsrc_type)
|
|||
|
||||
rsndvd_format = gst_format_register ("rsndvdsrc-internal",
|
||||
"private Resin DVD src format");
|
||||
|
||||
title_format = gst_format_register ("title", "DVD title format");
|
||||
chapter_format = gst_format_register ("chapter", "DVD chapter format");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -206,6 +213,7 @@ rsn_dvdsrc_class_init (resinDvdSrcClass * klass)
|
|||
gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (rsn_dvdsrc_unlock_stop);
|
||||
gstbasesrc_class->event = GST_DEBUG_FUNCPTR (rsn_dvdsrc_src_event);
|
||||
gstbasesrc_class->query = GST_DEBUG_FUNCPTR (rsn_dvdsrc_src_query);
|
||||
gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (rsn_dvdsrc_is_seekable);
|
||||
gstbasesrc_class->prepare_seek_segment =
|
||||
GST_DEBUG_FUNCPTR (rsn_dvdsrc_prepare_seek);
|
||||
gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (rsn_dvdsrc_do_seek);
|
||||
|
@ -284,7 +292,6 @@ rsn_dvdsrc_set_property (GObject * object, guint prop_id,
|
|||
else
|
||||
src->device = g_value_dup_string (value);
|
||||
GST_OBJECT_UNLOCK (src);
|
||||
g_print ("Device is now %s\n", src->device);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -756,7 +763,6 @@ 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;
|
||||
|
||||
g_print ("VTS change\n");
|
||||
if (dvdnav_is_domain_vmgm (src->dvdnav))
|
||||
src->vts_n = 0;
|
||||
else
|
||||
|
@ -772,7 +778,7 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock)
|
|||
case DVDNAV_AUDIO_STREAM_CHANGE:{
|
||||
dvdnav_audio_stream_change_event_t *event =
|
||||
(dvdnav_audio_stream_change_event_t *) data;
|
||||
g_print ("cur audio stream change\n");
|
||||
|
||||
GST_DEBUG_OBJECT (src, " physical: %d", event->physical);
|
||||
GST_DEBUG_OBJECT (src, " logical: %d", event->logical);
|
||||
|
||||
|
@ -782,9 +788,10 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock)
|
|||
case DVDNAV_SPU_STREAM_CHANGE:{
|
||||
dvdnav_spu_stream_change_event_t *event =
|
||||
(dvdnav_spu_stream_change_event_t *) data;
|
||||
gint phys_track = event->physical_wide & 0x1f;
|
||||
gboolean forced_only = (event->physical_wide & 0x80) ? TRUE : FALSE;
|
||||
|
||||
rsn_dvdsrc_prepare_spu_stream_event (src, event->physical_wide & 0x1f,
|
||||
(event->physical_wide & 0x80) ? TRUE : FALSE);
|
||||
rsn_dvdsrc_prepare_spu_stream_event (src, phys_track, forced_only);
|
||||
|
||||
GST_DEBUG_OBJECT (src, " physical_wide: %d", event->physical_wide);
|
||||
GST_DEBUG_OBJECT (src, " physical_letterbox: %d",
|
||||
|
@ -1200,6 +1207,8 @@ rsn_dvdsrc_prepare_audio_stream_event (resinDvdSrc * src, guint8 phys_stream)
|
|||
return;
|
||||
src->cur_audio_phys_stream = phys_stream;
|
||||
|
||||
g_print ("Preparing audio change, phys %d\n", phys_stream);
|
||||
|
||||
s = gst_structure_new ("application/x-gst-dvd",
|
||||
"event", G_TYPE_STRING, "dvd-set-audio-track",
|
||||
"physical-id", G_TYPE_INT, (gint) phys_stream, NULL);
|
||||
|
@ -1220,12 +1229,14 @@ rsn_dvdsrc_prepare_spu_stream_event (resinDvdSrc * src, guint8 phys_stream,
|
|||
|
||||
if (phys_stream == src->cur_spu_phys_stream &&
|
||||
forced_only == src->cur_spu_forced_only) {
|
||||
g_print ("Not preparing SPU change\n");
|
||||
return;
|
||||
}
|
||||
src->cur_spu_phys_stream = phys_stream;
|
||||
src->cur_spu_forced_only = forced_only;
|
||||
|
||||
g_print ("Preparing SPU change, phys %d forced %d\n",
|
||||
phys_stream, forced_only);
|
||||
|
||||
s = gst_structure_new ("application/x-gst-dvd",
|
||||
"event", G_TYPE_STRING, "dvd-set-subpicture-track",
|
||||
"physical-id", G_TYPE_INT, (gint) phys_stream,
|
||||
|
@ -1252,6 +1263,7 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
|
|||
gchar lang_code[3] = { '\0', '\0', '\0' };
|
||||
gchar *t;
|
||||
gboolean is_widescreen;
|
||||
gboolean have_audio;
|
||||
|
||||
if (src->vts_attrs == NULL || src->vts_n >= src->vts_attrs->len) {
|
||||
if (src->vts_attrs)
|
||||
|
@ -1301,13 +1313,21 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
|
|||
NULL);
|
||||
|
||||
/* audio */
|
||||
if (n_audio == 0) {
|
||||
/* Always create at least one audio stream */
|
||||
gst_structure_set (s, "audio-0-format", G_TYPE_INT, (int) 0, NULL);
|
||||
}
|
||||
have_audio = FALSE;
|
||||
for (i = 0; i < n_audio; i++) {
|
||||
const audio_attr_t *a = a_attrs + i;
|
||||
|
||||
#if 1
|
||||
/* FIXME: Only output A52 streams for now, until the decoder switching
|
||||
* is ready */
|
||||
if (a->audio_format != 0) {
|
||||
GST_DEBUG_OBJECT (src, "Ignoring non-A52 stream %d, format %d", i,
|
||||
(int) a->audio_format);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
have_audio = TRUE;
|
||||
|
||||
t = g_strdup_printf ("audio-%d-format", i);
|
||||
gst_structure_set (s, t, G_TYPE_INT, (int) a->audio_format, NULL);
|
||||
g_free (t);
|
||||
|
@ -1327,6 +1347,11 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
|
|||
GST_DEBUG_OBJECT (src, "Audio stream %d - no language", i, lang_code);
|
||||
}
|
||||
|
||||
if (have_audio == FALSE) {
|
||||
/* Always create at least one audio stream */
|
||||
gst_structure_set (s, "audio-0-format", G_TYPE_INT, (int) 0, NULL);
|
||||
}
|
||||
|
||||
/* subpictures */
|
||||
if (n_subp == 0) {
|
||||
/* Always create at least one subpicture stream */
|
||||
|
@ -1447,7 +1472,15 @@ rsn_dvdsrc_update_highlight (resinDvdSrc * src)
|
|||
|
||||
/* Check if we have a new button number, or a new highlight region. */
|
||||
if (button != src->active_button ||
|
||||
memcmp (&area, &(src->area), sizeof (dvdnav_highlight_area_t)) != 0) {
|
||||
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) {
|
||||
|
||||
g_print ("Setting highlight. Button %d @ %d,%d active %d palette 0x%x "
|
||||
"(from button %d @ %d,%d palette 0x%x)\n",
|
||||
button, src->area.sx, src->area.sy, mode, src->area.palette,
|
||||
src->active_button, area.sx, area.sy, area.palette);
|
||||
|
||||
memcpy (&(src->area), &area, sizeof (dvdnav_highlight_area_t));
|
||||
|
||||
s = gst_structure_new ("application/x-gst-dvd", "event",
|
||||
|
@ -1469,9 +1502,6 @@ rsn_dvdsrc_update_highlight (resinDvdSrc * src)
|
|||
|
||||
src->active_button = button;
|
||||
|
||||
g_print ("Setting highlight. Button %d @ %d,%d active %d"
|
||||
" palette 0x%x\n", button, area.sx, area.sy, mode, area.palette);
|
||||
|
||||
if (src->highlight_event)
|
||||
gst_event_unref (src->highlight_event);
|
||||
src->highlight_event = event;
|
||||
|
@ -1708,11 +1738,70 @@ rsn_dvdsrc_src_query (RsnBaseSrc * basesrc, GstQuery * query)
|
|||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_DURATION:
|
||||
gst_query_parse_duration (query, &format, NULL);
|
||||
if (format == GST_FORMAT_TIME && src->pgc_duration != GST_CLOCK_TIME_NONE) {
|
||||
val = src->pgc_duration;
|
||||
gst_query_set_duration (query, format, val);
|
||||
res = TRUE;
|
||||
g_mutex_lock (src->dvd_lock);
|
||||
if (!src->running) {
|
||||
g_mutex_unlock (src->dvd_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
if (format == GST_FORMAT_TIME) {
|
||||
if (src->pgc_duration != GST_CLOCK_TIME_NONE) {
|
||||
val = src->pgc_duration;
|
||||
gst_query_set_duration (query, format, val);
|
||||
res = TRUE;
|
||||
}
|
||||
} else if (format == title_format) {
|
||||
gint32 titles;
|
||||
|
||||
if (dvdnav_get_number_of_titles (src->dvdnav,
|
||||
&titles) == DVDNAV_STATUS_OK) {
|
||||
val = titles;
|
||||
gst_query_set_duration (query, format, val);
|
||||
res = TRUE;
|
||||
}
|
||||
} else if (format == chapter_format) {
|
||||
gint32 title, chapters, x;
|
||||
|
||||
if (dvdnav_current_title_info (src->dvdnav, &title,
|
||||
&x) == DVDNAV_STATUS_OK) {
|
||||
if (dvdnav_get_number_of_parts (src->dvdnav, title,
|
||||
&chapters) == DVDNAV_STATUS_OK) {
|
||||
val = chapters;
|
||||
gst_query_set_duration (query, format, val);
|
||||
res = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (src->dvd_lock);
|
||||
break;
|
||||
case GST_QUERY_POSITION:
|
||||
gst_query_parse_position (query, &format, NULL);
|
||||
|
||||
g_mutex_lock (src->dvd_lock);
|
||||
if (!src->running) {
|
||||
g_mutex_unlock (src->dvd_lock);
|
||||
break;
|
||||
}
|
||||
if (format == title_format) {
|
||||
gint32 title, chapter;
|
||||
|
||||
if (dvdnav_current_title_info (src->dvdnav, &title,
|
||||
&chapter) == DVDNAV_STATUS_OK) {
|
||||
val = title;
|
||||
gst_query_set_position (query, format, val);
|
||||
res = TRUE;
|
||||
}
|
||||
} else if (format == chapter_format) {
|
||||
gint32 title, chapter = -1;
|
||||
|
||||
if (dvdnav_current_title_info (src->dvdnav, &title,
|
||||
&chapter) == DVDNAV_STATUS_OK) {
|
||||
val = chapter;
|
||||
gst_query_set_position (query, format, val);
|
||||
res = TRUE;
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (src->dvd_lock);
|
||||
break;
|
||||
default:
|
||||
res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
|
||||
|
@ -1722,6 +1811,12 @@ rsn_dvdsrc_src_query (RsnBaseSrc * basesrc, GstQuery * query)
|
|||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
rsn_dvdsrc_is_seekable (RsnBaseSrc * bsrc)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
rsn_dvdsrc_prepare_seek (RsnBaseSrc * bsrc, GstEvent * event,
|
||||
GstSegment * segment)
|
||||
|
@ -1737,8 +1832,9 @@ rsn_dvdsrc_prepare_seek (RsnBaseSrc * bsrc, GstEvent * event,
|
|||
gst_event_parse_seek (event, &rate, &seek_format, &flags,
|
||||
&cur_type, &cur, &stop_type, &stop);
|
||||
|
||||
if (seek_format == rsndvd_format) {
|
||||
/* Seeks in our internal format are passed directly through to the do_seek
|
||||
if (seek_format == rsndvd_format || seek_format == title_format ||
|
||||
seek_format == chapter_format) {
|
||||
/* Seeks in our internal formats are passed directly through to the do_seek
|
||||
* method. */
|
||||
gst_segment_init (segment, seek_format);
|
||||
gst_segment_set_seek (segment, rate, seek_format, flags, cur_type, cur,
|
||||
|
@ -1753,8 +1849,7 @@ rsn_dvdsrc_prepare_seek (RsnBaseSrc * bsrc, GstEvent * event,
|
|||
if (seek_format == GST_FORMAT_BYTES)
|
||||
return FALSE;
|
||||
|
||||
/* Let basesrc handle other formats for now. FIXME: Implement angle,
|
||||
* chapter etc */
|
||||
/* Let basesrc handle other formats for now. FIXME: Implement angle */
|
||||
return GST_BASE_SRC_CLASS (parent_class)->prepare_seek_segment (bsrc,
|
||||
event, segment);
|
||||
}
|
||||
|
@ -1766,6 +1861,9 @@ rsn_dvdsrc_do_seek (RsnBaseSrc * bsrc, GstSegment * segment)
|
|||
gboolean ret = FALSE;
|
||||
|
||||
if (segment->format == rsndvd_format) {
|
||||
/* 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;
|
||||
} else {
|
||||
/* FIXME: Handle other formats: Time, title, chapter, angle */
|
||||
|
@ -1773,13 +1871,41 @@ rsn_dvdsrc_do_seek (RsnBaseSrc * bsrc, GstSegment * segment)
|
|||
if (segment->format == GST_FORMAT_TIME) {
|
||||
ret = TRUE;
|
||||
src->discont = TRUE;
|
||||
} else if (segment->format == title_format) {
|
||||
gint titles;
|
||||
|
||||
g_mutex_lock (src->dvd_lock);
|
||||
if (src->running &&
|
||||
dvdnav_get_number_of_titles (src->dvdnav,
|
||||
&titles) == DVDNAV_STATUS_OK) {
|
||||
if (segment->start > 0 && segment->start <= titles) {
|
||||
dvdnav_title_play (src->dvdnav, segment->start);
|
||||
ret = TRUE;
|
||||
src->discont = TRUE;
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (src->dvd_lock);
|
||||
} else if (segment->format == chapter_format) {
|
||||
g_mutex_lock (src->dvd_lock);
|
||||
if (src->running) {
|
||||
gint32 title, chapters, x;
|
||||
if (dvdnav_current_title_info (src->dvdnav, &title, &x) ==
|
||||
DVDNAV_STATUS_OK) {
|
||||
if (dvdnav_get_number_of_parts (src->dvdnav, title, &chapters) ==
|
||||
DVDNAV_STATUS_OK) {
|
||||
if (segment->start > 0 && segment->start <= chapters) {
|
||||
dvdnav_part_play (src->dvdnav, title, segment->start);
|
||||
ret = TRUE;
|
||||
src->discont = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (src->dvd_lock);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
/* The internal format has served its purpose of waking everything
|
||||
* up and flushing, now step to the next data block so we know our
|
||||
* position */
|
||||
/* Force a highlight update */
|
||||
src->active_button = -1;
|
||||
|
||||
|
|
|
@ -63,7 +63,9 @@ enum
|
|||
|
||||
static gboolean rsn_stream_selector_is_active_sinkpad (RsnStreamSelector * sel,
|
||||
GstPad * pad);
|
||||
static GstPad *rsn_stream_selector_activate_sinkpad (RsnStreamSelector * sel,
|
||||
static GstPad *rsn_stream_selector_get_active (RsnStreamSelector * sel,
|
||||
GstPad * pad);
|
||||
static void rsn_stream_selector_set_active (RsnStreamSelector * sel,
|
||||
GstPad * pad);
|
||||
static GstPad *rsn_stream_selector_get_linked_pad (GstPad * pad,
|
||||
gboolean strict);
|
||||
|
@ -261,7 +263,7 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event)
|
|||
selpad = GST_SELECTOR_PAD_CAST (pad);
|
||||
|
||||
/* only forward if we are dealing with the active sinkpad */
|
||||
active_sinkpad = rsn_stream_selector_activate_sinkpad (sel, pad);
|
||||
active_sinkpad = rsn_stream_selector_get_active (sel, pad);
|
||||
forward = (active_sinkpad == pad);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
|
@ -307,6 +309,18 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event)
|
|||
GST_OBJECT_UNLOCK (selpad);
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_CUSTOM_DOWNSTREAM:
|
||||
{
|
||||
const GstStructure *structure = gst_event_get_structure (event);
|
||||
if (structure != NULL &&
|
||||
gst_structure_has_name (structure, "application/x-gst-dvd")) {
|
||||
const char *type = gst_structure_get_string (structure, "event");
|
||||
if (strcmp (type, "select-pad") == 0) {
|
||||
rsn_stream_selector_set_active (sel, pad);
|
||||
forward = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
case GST_EVENT_EOS:
|
||||
selpad->eos = TRUE;
|
||||
break;
|
||||
|
@ -351,7 +365,7 @@ gst_selector_pad_bufferalloc (GstPad * pad, guint64 offset,
|
|||
|
||||
sel = RSN_STREAM_SELECTOR (gst_pad_get_parent (pad));
|
||||
|
||||
active_sinkpad = rsn_stream_selector_activate_sinkpad (sel, pad);
|
||||
active_sinkpad = rsn_stream_selector_get_active (sel, pad);
|
||||
|
||||
/* Fallback allocation for buffers from pads except the selected one */
|
||||
if (pad != active_sinkpad) {
|
||||
|
@ -397,7 +411,7 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
|
|||
selpad = GST_SELECTOR_PAD_CAST (pad);
|
||||
seg = &selpad->segment;
|
||||
|
||||
active_sinkpad = rsn_stream_selector_activate_sinkpad (sel, pad);
|
||||
active_sinkpad = rsn_stream_selector_get_active (sel, pad);
|
||||
|
||||
timestamp = GST_BUFFER_TIMESTAMP (buf);
|
||||
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||
|
@ -574,28 +588,10 @@ rsn_stream_selector_set_property (GObject * object, guint prop_id,
|
|||
case PROP_ACTIVE_PAD:
|
||||
{
|
||||
GstPad *pad = NULL;
|
||||
GstPad **active_pad_p;
|
||||
|
||||
pad = g_value_get_object (value);
|
||||
rsn_stream_selector_set_active (sel, pad);
|
||||
|
||||
GST_OBJECT_LOCK (object);
|
||||
if (pad != sel->active_sinkpad) {
|
||||
RsnSelectorPad *selpad;
|
||||
|
||||
selpad = GST_SELECTOR_PAD_CAST (pad);
|
||||
/* we can only activate pads that have data received */
|
||||
if (selpad && !selpad->active) {
|
||||
GST_DEBUG_OBJECT (sel, "No data received on pad %" GST_PTR_FORMAT,
|
||||
pad);
|
||||
} else {
|
||||
active_pad_p = &sel->active_sinkpad;
|
||||
gst_object_replace ((GstObject **) active_pad_p,
|
||||
GST_OBJECT_CAST (pad));
|
||||
GST_DEBUG_OBJECT (sel, "New active pad is %" GST_PTR_FORMAT,
|
||||
sel->active_sinkpad);
|
||||
}
|
||||
}
|
||||
GST_OBJECT_UNLOCK (object);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -694,7 +690,7 @@ rsn_stream_selector_is_active_sinkpad (RsnStreamSelector * sel, GstPad * pad)
|
|||
|
||||
/* Get or create the active sinkpad */
|
||||
static GstPad *
|
||||
rsn_stream_selector_activate_sinkpad (RsnStreamSelector * sel, GstPad * pad)
|
||||
rsn_stream_selector_get_active (RsnStreamSelector * sel, GstPad * pad)
|
||||
{
|
||||
GstPad *active_sinkpad;
|
||||
RsnSelectorPad *selpad;
|
||||
|
@ -714,6 +710,29 @@ rsn_stream_selector_activate_sinkpad (RsnStreamSelector * sel, GstPad * pad)
|
|||
return active_sinkpad;
|
||||
}
|
||||
|
||||
static void
|
||||
rsn_stream_selector_set_active (RsnStreamSelector * sel, GstPad * pad)
|
||||
{
|
||||
GstPad **active_pad_p;
|
||||
|
||||
GST_OBJECT_LOCK (GST_OBJECT_CAST (sel));
|
||||
if (pad != sel->active_sinkpad) {
|
||||
RsnSelectorPad *selpad;
|
||||
|
||||
selpad = GST_SELECTOR_PAD_CAST (pad);
|
||||
/* we can only activate pads that have data received */
|
||||
if (selpad && !selpad->active) {
|
||||
GST_DEBUG_OBJECT (sel, "No data received on pad %" GST_PTR_FORMAT, pad);
|
||||
} else {
|
||||
active_pad_p = &sel->active_sinkpad;
|
||||
gst_object_replace ((GstObject **) active_pad_p, GST_OBJECT_CAST (pad));
|
||||
GST_DEBUG_OBJECT (sel, "New active pad is %" GST_PTR_FORMAT,
|
||||
sel->active_sinkpad);
|
||||
}
|
||||
}
|
||||
GST_OBJECT_UNLOCK (GST_OBJECT_CAST (sel));
|
||||
}
|
||||
|
||||
static GList *
|
||||
rsn_stream_selector_get_linked_pads (GstPad * pad)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue