docs/plugins/.cvsignore: Ignore *-undeclared.txt

Original commit message from CVS:
* docs/plugins/.cvsignore:
Ignore *-undeclared.txt
* ext/resindvd/rsnaudiomunge.c:
Turn g_print's into debug statements.
* ext/resindvd/resin-play:
* ext/resindvd/Makefile.am:
* ext/resindvd/resindvdbin.c:
* ext/resindvd/resindvdbin.h:
* ext/resindvd/rsnparsetter.c:
* ext/resindvd/rsnparsetter.h:
* ext/resindvd/rsnwrappedbuffer.c:
* ext/resindvd/rsnwrappedbuffer.h:
Add a bloated implementation of a really simple idea: Replace the
pixel-aspect-ratio in the output video with a prescribed one when
necessary. There must be an easier way.
Split the dvdspu out of the resindvdbin and put out the subpicture
stream on the subpicture pad.
* ext/resindvd/gstmpegdemux.c:
Send video-aspect events down the pipe from the demuxer.
* ext/resindvd/resindvdsrc.c:
* ext/resindvd/resindvdsrc.h:
Handle timed-stills somewhat using g_cond_timed_wait, with a FIXME
to make it use clock-waiting later.
* ext/resindvd/rsnbasesrc.c:
Don't overwrite the last_stop in the basesrc segment after a seamless
seek.
This commit is contained in:
Jan Schmidt 2008-07-11 14:06:08 +00:00
parent f79bf9a0fb
commit 9a392ef442
14 changed files with 980 additions and 153 deletions

View file

@ -1,3 +1,38 @@
2008-07-11 Jan Schmidt <thaytan@noraisin.net>
* docs/plugins/.cvsignore:
Ignore *-undeclared.txt
* ext/resindvd/rsnaudiomunge.c:
Turn g_print's into debug statements.
* ext/resindvd/resin-play:
* ext/resindvd/Makefile.am:
* ext/resindvd/resindvdbin.c:
* ext/resindvd/resindvdbin.h:
* ext/resindvd/rsnparsetter.c:
* ext/resindvd/rsnparsetter.h:
* ext/resindvd/rsnwrappedbuffer.c:
* ext/resindvd/rsnwrappedbuffer.h:
Add a bloated implementation of a really simple idea: Replace the
pixel-aspect-ratio in the output video with a prescribed one when
necessary. There must be an easier way.
Split the dvdspu out of the resindvdbin and put out the subpicture
stream on the subpicture pad.
* ext/resindvd/gstmpegdemux.c:
Send video-aspect events down the pipe from the demuxer.
* ext/resindvd/resindvdsrc.c:
* ext/resindvd/resindvdsrc.h:
Handle timed-stills somewhat using g_cond_timed_wait, with a FIXME
to make it use clock-waiting later.
* ext/resindvd/rsnbasesrc.c:
Don't overwrite the last_stop in the basesrc segment after a seamless
seek.
2008-07-10 Zaheer Abbas Merali <zaheerabbas at merali dot org> 2008-07-10 Zaheer Abbas Merali <zaheerabbas at merali dot org>
* gst/mpegtsparse/mpegtspacketizer.c: * gst/mpegtsparse/mpegtspacketizer.c:

View file

@ -12,10 +12,12 @@ libresindvd_la_SOURCES = \
resindvdsrc.c \ resindvdsrc.c \
gstmpegdesc.c \ gstmpegdesc.c \
gstmpegdemux.c \ gstmpegdemux.c \
gstpesfilter.c gstpesfilter.c \
rsnparsetter.c \
rsnwrappedbuffer.c
libresindvd_la_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(DVDNAV_CFLAGS) libresindvd_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(DVDNAV_CFLAGS)
libresindvd_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(DVDNAV_LIBS) libresindvd_la_LIBADD = $(GST_PLUGINS_BASE_CFLAGS) -lgstvideo-$(GST_MAJORMINOR) $(GST_BASE_LIBS) $(GST_LIBS) $(DVDNAV_LIBS)
libresindvd_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libresindvd_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = resindvdbin.h \ noinst_HEADERS = resindvdbin.h \
@ -27,4 +29,5 @@ noinst_HEADERS = resindvdbin.h \
gstmpegdefs.h \ gstmpegdefs.h \
gstmpegdesc.h \ gstmpegdesc.h \
gstmpegdemux.h \ gstmpegdemux.h \
gstpesfilter.h gstpesfilter.h \
rsnparsetter.h

View file

@ -35,7 +35,7 @@
/* The SCR_MUNGE value is used to offset the scr_adjust value, to avoid /* The SCR_MUNGE value is used to offset the scr_adjust value, to avoid
* ever generating a negative timestamp */ * ever generating a negative timestamp */
#define SCR_MUNGE (2 * GST_SECOND) #define SCR_MUNGE (10 * GST_SECOND)
/* We clamp scr delta with 0 so negative bytes won't be possible */ /* We clamp scr delta with 0 so negative bytes won't be possible */
#define GSTTIME_TO_BYTES(time) \ #define GSTTIME_TO_BYTES(time) \
@ -266,6 +266,7 @@ gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type)
case ST_GST_VIDEO_MPEG1_OR_2: case ST_GST_VIDEO_MPEG1_OR_2:
{ {
gint mpeg_version = 1; gint mpeg_version = 1;
if (stream_type == ST_VIDEO_MPEG2 || if (stream_type == ST_VIDEO_MPEG2 ||
(stream_type == ST_GST_VIDEO_MPEG1_OR_2 && demux->is_mpeg2_pack)) { (stream_type == ST_GST_VIDEO_MPEG1_OR_2 && demux->is_mpeg2_pack)) {
mpeg_version = 2; mpeg_version = 2;
@ -584,19 +585,35 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
if (strcmp (type, "dvd-lang-codes") == 0) { if (strcmp (type, "dvd-lang-codes") == 0) {
GstEvent **p_ev; GstEvent **p_ev;
/* Store the language codes event on the element, then iterate over the /* Store the language codes event on the element, then iterate over the
* streams it specifies and retrieve them. The stream creation code then * streams it specifies and retrieve them. The stream creation code then
* creates the pad appropriately and sends tag events as needed */ * creates the pad appropriately and sends tag events as needed */
p_ev = &demux->lang_codes; p_ev = &demux->lang_codes;
gst_event_replace (p_ev, event); gst_event_replace (p_ev, event);
GST_ERROR_OBJECT (demux, "*********************\nLang codes event %s",
gst_structure_to_string (structure));
GST_DEBUG_OBJECT (demux, "Handling language codes event"); GST_DEBUG_OBJECT (demux, "Handling language codes event");
/* Create a video pad to ensure have it before emit no more pads */ /* Create a video pad to ensure it exists before emit no more pads */
temp = gst_flups_demux_get_stream (demux, 0xe0, ST_VIDEO_MPEG2); temp = gst_flups_demux_get_stream (demux, 0xe0, ST_VIDEO_MPEG2);
/* Send a video format event downstream */
{
gboolean is_widescreen, is_pal;
if (gst_structure_get_boolean (structure,
"video-widescreen", &is_widescreen) &&
gst_structure_get_boolean (structure, "video-pal-format", &is_pal)) {
GstEvent *v_format;
GstStructure *v_struct;
v_struct = gst_structure_new ("application/x-gst-dvd",
"event", G_TYPE_STRING, "dvd-video-format",
"video-widescreen", G_TYPE_BOOLEAN, is_widescreen,
"video-pal-format", G_TYPE_BOOLEAN, is_pal, NULL);
v_format = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, v_struct);
gst_pad_push_event (temp->pad, v_format);
}
}
/* Read out the languages for audio streams and request each one that /* Read out the languages for audio streams and request each one that
* is present */ * is present */
@ -646,6 +663,7 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
/* And subtitle streams */ /* And subtitle streams */
for (i = 0; i < MAX_DVD_SUBPICTURE_STREAMS; i++) { for (i = 0; i < MAX_DVD_SUBPICTURE_STREAMS; i++) {
gint stream_format; gint stream_format;
g_snprintf (cur_stream_name, 32, "subpicture-%d-format", i); g_snprintf (cur_stream_name, 32, "subpicture-%d-format", i);
if (!gst_structure_get_int (structure, cur_stream_name, &stream_format)) if (!gst_structure_get_int (structure, cur_stream_name, &stream_format))

View file

@ -7,5 +7,6 @@ else
fi fi
gst-launch rsndvdbin name=dvd "$DEVICE_OPT" \ gst-launch rsndvdbin name=dvd "$DEVICE_OPT" \
dvd. ! ffmpegcolorspace ! videoscale ! autovideosink \ dvd. ! dvdspu name=spu ! ffmpegcolorspace ! videoscale ! ximagesink force-aspect-ratio=true \
dvd. ! audioconvert ! autoaudiosink dvd. ! spu. \
dvd. ! audioconvert ! autoaudiosink $@

View file

@ -29,6 +29,7 @@
#include "resindvdsrc.h" #include "resindvdsrc.h"
#include "rsnstreamselector.h" #include "rsnstreamselector.h"
#include "rsnaudiomunge.h" #include "rsnaudiomunge.h"
#include "rsnparsetter.h"
#include "gstmpegdemux.h" #include "gstmpegdemux.h"
@ -58,13 +59,23 @@ static GstStaticPadTemplate video_src_template =
GST_STATIC_PAD_TEMPLATE ("video", GST_STATIC_PAD_TEMPLATE ("video",
GST_PAD_SRC, GST_PAD_SRC,
GST_PAD_SOMETIMES, GST_PAD_SOMETIMES,
GST_STATIC_CAPS_ANY); GST_STATIC_CAPS
("video/mpeg, mpegversion=(int) { 1, 2 }, systemstream=false")
);
static GstStaticPadTemplate audio_src_template = static GstStaticPadTemplate audio_src_template =
GST_STATIC_PAD_TEMPLATE ("audio", GST_STATIC_PAD_TEMPLATE ("audio",
GST_PAD_SRC, GST_PAD_SRC,
GST_PAD_SOMETIMES, GST_PAD_SOMETIMES,
GST_STATIC_CAPS_ANY); GST_STATIC_CAPS ("audio/x-raw-int;audio/x-raw-float")
);
static GstStaticPadTemplate subpicture_src_template =
GST_STATIC_PAD_TEMPLATE ("subpicture",
GST_PAD_SRC,
GST_PAD_SOMETIMES,
GST_STATIC_CAPS ("video/x-dvd-subpicture")
);
static void rsn_dvdbin_do_init (GType rsn_dvdbin_type); static void rsn_dvdbin_do_init (GType rsn_dvdbin_type);
static void rsn_dvdbin_finalize (GObject * object); static void rsn_dvdbin_finalize (GObject * object);
@ -103,6 +114,8 @@ rsn_dvdbin_base_init (gpointer gclass)
gst_static_pad_template_get (&video_src_template)); gst_static_pad_template_get (&video_src_template));
gst_element_class_add_pad_template (element_class, gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&audio_src_template)); gst_static_pad_template_get (&audio_src_template));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&subpicture_src_template));
gst_element_class_set_details (element_class, &element_details); gst_element_class_set_details (element_class, &element_details);
element_class->change_state = GST_DEBUG_FUNCPTR (rsn_dvdbin_change_state); element_class->change_state = GST_DEBUG_FUNCPTR (rsn_dvdbin_change_state);
@ -365,53 +378,56 @@ create_elements (RsnDvdBin * dvdbin)
g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_VIDDEC]), g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_VIDDEC]),
"new-decoded-pad", G_CALLBACK (viddec_pad_added), dvdbin); "new-decoded-pad", G_CALLBACK (viddec_pad_added), dvdbin);
#if 1
if (!try_create_piece (dvdbin, DVD_ELEM_PARSET, NULL, RSN_TYPE_RSNPARSETTER,
"rsnparsetter", "Aspect ratio adjustment"))
return FALSE;
#else
if (!try_create_piece (dvdbin, DVD_ELEM_PARSET, "identity", 0,
"rsnparsetter", "Aspect ratio adjustment"))
return FALSE;
#endif
if (!try_create_piece (dvdbin, DVD_ELEM_VIDQ, "queue", 0, "vid_q", if (!try_create_piece (dvdbin, DVD_ELEM_VIDQ, "queue", 0, "vid_q",
"video decoder buffer")) "video decoder buffer"))
return FALSE; return FALSE;
src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_PARSET], "src");
sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_VIDQ], "sink");
if (src == NULL || sink == NULL)
goto failed_vidq_connect;
if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink)))
goto failed_vidq_connect;
g_object_set (dvdbin->pieces[DVD_ELEM_VIDQ], g_object_set (dvdbin->pieces[DVD_ELEM_VIDQ],
"max-size-time", G_GUINT64_CONSTANT (0), "max-size-bytes", 0, "max-size-time", G_GUINT64_CONSTANT (0), "max-size-bytes", 0,
"max-size-buffers", 3, NULL); "max-size-buffers", 3, NULL);
src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_VIDQ], "src");
if (src == NULL)
goto failed_vidq_ghost;
ghost = gst_ghost_pad_new ("video", src);
if (ghost == NULL)
goto failed_vidq_ghost;
if (!gst_element_add_pad (GST_ELEMENT (dvdbin), ghost))
goto failed_vidq_ghost;
gst_object_unref (src);
ghost = src = sink = NULL;
if (!try_create_piece (dvdbin, DVD_ELEM_SPU_SELECT, NULL, if (!try_create_piece (dvdbin, DVD_ELEM_SPU_SELECT, NULL,
RSN_TYPE_STREAM_SELECTOR, "subpselect", "Subpicture stream selector")) RSN_TYPE_STREAM_SELECTOR, "subpselect", "Subpicture stream selector"))
return FALSE; return FALSE;
if (!try_create_piece (dvdbin, DVD_ELEM_SPU, "dvdspu", 0, "spu",
"Subpicture overlay"))
return FALSE;
sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU], "video");
src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_VIDQ], "src");
if (src == NULL || sink == NULL)
goto failed_spu_connect;
if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink)))
goto failed_spu_connect;
gst_object_unref (sink);
gst_object_unref (src);
src = sink = NULL;
sink =
gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU], "subpicture");
src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU_SELECT], "src"); src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU_SELECT], "src");
if (src == NULL || sink == NULL)
goto failed_spu_connect;
if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink)))
goto failed_spu_connect;
gst_object_unref (sink);
gst_object_unref (src);
src = sink = NULL;
src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU], "src");
if (src == NULL) if (src == NULL)
goto failed_spu_ghost; goto failed_spu_ghost;
ghost = gst_ghost_pad_new ("video", src); ghost = gst_ghost_pad_new ("subpicture", src);
if (ghost == NULL) if (ghost == NULL)
goto failed_spu_ghost; goto failed_spu_ghost;
if (!gst_element_add_pad (GST_ELEMENT (dvdbin), ghost)) if (!gst_element_add_pad (GST_ELEMENT (dvdbin), ghost))
goto failed_spu_ghost; goto failed_spu_ghost;
gst_object_unref (src); gst_object_unref (src);
src = sink = NULL; ghost = src = sink = NULL;
if (!try_create_piece (dvdbin, DVD_ELEM_AUD_SELECT, NULL, if (!try_create_piece (dvdbin, DVD_ELEM_AUD_SELECT, NULL,
RSN_TYPE_STREAM_SELECTOR, "audioselect", "Audio stream selector")) RSN_TYPE_STREAM_SELECTOR, "audioselect", "Audio stream selector"))
@ -468,44 +484,42 @@ create_elements (RsnDvdBin * dvdbin)
if (!gst_element_add_pad (GST_ELEMENT (dvdbin), ghost)) if (!gst_element_add_pad (GST_ELEMENT (dvdbin), ghost))
goto failed_aud_ghost; goto failed_aud_ghost;
gst_object_unref (src); gst_object_unref (src);
src = sink = NULL; ghost = src = sink = NULL;
return TRUE; return TRUE;
failed_connect: failed_connect:
GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
("Could not connect DVD source and demuxer elements")); ("Could not connect DVD source and demuxer elements"));
return FALSE; goto error_out;
failed_spu_connect: failed_vidq_connect:
GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
("Could not connect DVD video buffer and spu elements")); ("Could not connect DVD aspect ratio adjuster and video buffer elements"));
if (src != NULL) goto error_out;
gst_object_unref (src); failed_vidq_ghost:
if (sink != NULL) GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
gst_object_unref (sink); ("Could not ghost SPU output pad"));
return FALSE; goto error_out;
failed_spu_ghost: failed_spu_ghost:
GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
("Could not ghost SPU output pad")); ("Could not ghost SPU output pad"));
if (src != NULL) goto error_out;
gst_object_unref (src);
if (ghost != NULL)
gst_object_unref (ghost);
return FALSE;
failed_aud_connect: failed_aud_connect:
GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
("Could not connect DVD audio decoder")); ("Could not connect DVD audio decoder"));
goto error_out;
failed_aud_ghost:
GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
("Could not ghost audio output pad"));
goto error_out;
error_out:
if (ghost != NULL)
gst_object_unref (ghost);
if (src != NULL) if (src != NULL)
gst_object_unref (src); gst_object_unref (src);
if (sink != NULL) if (sink != NULL)
gst_object_unref (sink); gst_object_unref (sink);
return FALSE; return FALSE;
failed_aud_ghost:
GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
("Could not ghost audio output pad"));
if (ghost != NULL)
gst_object_unref (ghost);
return FALSE;
} }
static void static void
@ -578,7 +592,7 @@ demux_pad_added (GstElement * element, GstPad * pad, RsnDvdBin * dvdbin)
GstCaps *caps; GstCaps *caps;
GstStructure *s; GstStructure *s;
GST_ERROR_OBJECT (dvdbin, "New pad: %" GST_PTR_FORMAT, pad); GST_DEBUG_OBJECT (dvdbin, "New pad: %" GST_PTR_FORMAT, pad);
caps = gst_pad_get_caps (pad); caps = gst_pad_get_caps (pad);
if (caps == NULL) { if (caps == NULL) {
@ -622,7 +636,7 @@ demux_pad_added (GstElement * element, GstPad * pad, RsnDvdBin * dvdbin)
mq_pad = connect_thru_mq (dvdbin, pad); mq_pad = connect_thru_mq (dvdbin, pad);
if (mq_pad == NULL) if (mq_pad == NULL)
goto failed; goto failed;
GST_ERROR_OBJECT (dvdbin, "Linking new pad %" GST_PTR_FORMAT GST_DEBUG_OBJECT (dvdbin, "Linking new pad %" GST_PTR_FORMAT
" through multiqueue to %" GST_PTR_FORMAT, pad, dest_pad); " through multiqueue to %" GST_PTR_FORMAT, pad, dest_pad);
} }
@ -648,9 +662,9 @@ viddec_pad_added (GstElement * element, GstPad * pad, gboolean last,
{ {
GstPad *q_pad; GstPad *q_pad;
GST_ERROR_OBJECT (dvdbin, "New video pad: %" GST_PTR_FORMAT, pad); GST_DEBUG_OBJECT (dvdbin, "New video pad: %" GST_PTR_FORMAT, pad);
q_pad = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_VIDQ], "sink"); q_pad = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_PARSET], "sink");
gst_pad_link (pad, q_pad); gst_pad_link (pad, q_pad);
gst_object_unref (q_pad); gst_object_unref (q_pad);
@ -663,7 +677,7 @@ auddec_pad_added (GstElement * element, GstPad * pad, gboolean last,
{ {
GstPad *out_pad; GstPad *out_pad;
GST_ERROR_OBJECT (dvdbin, "New audio pad: %" GST_PTR_FORMAT, pad); GST_DEBUG_OBJECT (dvdbin, "New audio pad: %" GST_PTR_FORMAT, pad);
out_pad = out_pad =
gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "sink"); gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "sink");

View file

@ -44,12 +44,13 @@ typedef struct _RsnDvdBinClass RsnDvdBinClass;
#define DVD_ELEM_MQUEUE 2 #define DVD_ELEM_MQUEUE 2
#define DVD_ELEM_SPU 3 #define DVD_ELEM_SPU 3
#define DVD_ELEM_VIDDEC 4 #define DVD_ELEM_VIDDEC 4
#define DVD_ELEM_AUDDEC 5 #define DVD_ELEM_PARSET 5
#define DVD_ELEM_VIDQ 6 #define DVD_ELEM_AUDDEC 6
#define DVD_ELEM_SPU_SELECT 7 #define DVD_ELEM_VIDQ 7
#define DVD_ELEM_AUD_SELECT 8 #define DVD_ELEM_SPU_SELECT 8
#define DVD_ELEM_AUD_MUNGE 9 #define DVD_ELEM_AUD_SELECT 9
#define DVD_ELEM_LAST 10 #define DVD_ELEM_AUD_MUNGE 10
#define DVD_ELEM_LAST 11
struct _RsnDvdBin struct _RsnDvdBin
{ {

View file

@ -344,6 +344,12 @@ rsn_dvdsrc_start (RsnBaseSrc * bsrc)
src->in_menu = FALSE; src->in_menu = FALSE;
src->active_button = -1; src->active_button = -1;
src->cur_spu_phys_stream = -1;
src->cur_spu_forced_only = FALSE;
memset (src->cur_clut, 0, sizeof (guint32) * 16);
src->cur_audio_phys_stream = -1;
g_mutex_unlock (src->dvd_lock); g_mutex_unlock (src->dvd_lock);
return TRUE; return TRUE;
@ -494,36 +500,46 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration)
GstEvent *seg_event; GstEvent *seg_event;
GstSegment *segment = &(GST_BASE_SRC (src)->segment); GstSegment *segment = &(GST_BASE_SRC (src)->segment);
g_print ("**** STILL FRAME. Duration %d ****\n", duration); if (src->in_still_state == FALSE) {
g_print ("**** STILL FRAME. Duration %d ****\n", duration);
/* Send a close-segment event, and a dvd-still start
* event, then sleep */
s = gst_structure_new ("application/x-gst-dvd",
"event", G_TYPE_STRING, "dvd-still",
"still-state", G_TYPE_BOOLEAN, TRUE, NULL);
still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
/* Send a close-segment event, and a dvd-still start gst_segment_set_last_stop (segment, GST_FORMAT_TIME, src->cur_end_ts);
* event, then sleep */
s = gst_structure_new ("application/x-gst-dvd",
"event", G_TYPE_STRING, "dvd-still",
"still-state", G_TYPE_BOOLEAN, TRUE, NULL);
still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
gst_segment_set_last_stop (segment, GST_FORMAT_TIME, src->cur_end_ts); seg_event = gst_event_new_new_segment_full (TRUE,
segment->rate, segment->applied_rate, segment->format,
segment->start, segment->last_stop, segment->time);
seg_event = gst_event_new_new_segment_full (TRUE, /* Grab any pending highlight event to send too */
segment->rate, segment->applied_rate, segment->format, hl_event = src->highlight_event;
segment->start, segment->last_stop, segment->time); src->highlight_event = NULL;
/* Grab any pending highlight event to send too */ /* Now, send the events. We need to drop the dvd lock while doing so,
hl_event = src->highlight_event; * and then check after if we got flushed */
src->highlight_event = NULL; g_mutex_unlock (src->dvd_lock);
gst_pad_push_event (GST_BASE_SRC_PAD (src), still_event);
gst_pad_push_event (GST_BASE_SRC_PAD (src), seg_event);
if (hl_event) {
g_print ("Sending highlight event before still\n");
gst_pad_push_event (GST_BASE_SRC_PAD (src), hl_event);
}
g_mutex_lock (src->dvd_lock);
/* Now, send the events. We need to drop the dvd lock while doing so, g_mutex_lock (src->branch_lock);
* and then check after if we got flushed */
g_mutex_unlock (src->dvd_lock); src->in_still_state = TRUE;
gst_pad_push_event (GST_BASE_SRC_PAD (src), still_event); } else {
gst_pad_push_event (GST_BASE_SRC_PAD (src), seg_event); GST_DEBUG_OBJECT (src, "Re-entering still wait");
if (hl_event) g_mutex_lock (src->branch_lock);
gst_pad_push_event (GST_BASE_SRC_PAD (src), hl_event); }
g_mutex_lock (src->dvd_lock);
g_mutex_lock (src->branch_lock);
if (src->branching) { if (src->branching) {
GST_INFO_OBJECT (src, "Branching - aborting still");
g_mutex_unlock (src->branch_lock); g_mutex_unlock (src->branch_lock);
return TRUE; return TRUE;
} }
@ -535,28 +551,62 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration)
* don't skip it * don't skip it
*/ */
src->need_segment = TRUE; src->need_segment = TRUE;
g_mutex_unlock (src->dvd_lock); g_mutex_unlock (src->dvd_lock);
GST_LOG_OBJECT (src, "Entering cond_wait still");
g_cond_wait (src->still_cond, src->branch_lock); g_cond_wait (src->still_cond, src->branch_lock);
GST_LOG_OBJECT (src, "cond_wait still over, branching = %d",
src->branching);
if (src->branching) { if (src->branching) {
g_mutex_unlock (src->branch_lock); g_mutex_unlock (src->branch_lock);
g_mutex_lock (src->dvd_lock); g_mutex_lock (src->dvd_lock);
return TRUE; return TRUE;
} }
src->in_still_state = FALSE;
g_mutex_unlock (src->branch_lock); g_mutex_unlock (src->branch_lock);
g_mutex_lock (src->dvd_lock); g_mutex_lock (src->dvd_lock);
} else { } else {
GTimeVal end_time;
gboolean was_signalled;
g_get_current_time (&end_time);
g_time_val_add (&end_time, duration * G_USEC_PER_SEC);
/* FIXME: Implement timed stills by sleeping on the clock, possibly /* FIXME: Implement timed stills by sleeping on the clock, possibly
* in multiple steps if we get paused/unpaused */ * in multiple steps if we get paused/unpaused */
if (dvdnav_still_skip (src->dvdnav) != DVDNAV_STATUS_OK) g_mutex_unlock (src->dvd_lock);
return FALSE; GST_LOG_OBJECT (src, "cond_timed_wait still");
was_signalled =
/* Later: We'll only do this if the still isn't interrupted: */ g_cond_timed_wait (src->still_cond, src->branch_lock, &end_time);
s = gst_structure_new ("application/x-gst-dvd", was_signalled |= src->branching;
"event", G_TYPE_STRING, "dvd-still",
"still-state", G_TYPE_BOOLEAN, TRUE, NULL);
still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
g_mutex_unlock (src->branch_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;
}
/* Else timed out, end the still */
GST_DEBUG_OBJECT (src,
"Timed still of %d secs over, calling dvdnav_still_skip", duration);
if (dvdnav_still_skip (src->dvdnav) != DVDNAV_STATUS_OK) {
return FALSE;
}
/* Tell downstream the still is over.
* Later: We'll 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);
g_mutex_unlock (src->dvd_lock); g_mutex_unlock (src->dvd_lock);
gst_pad_push_event (GST_BASE_SRC_PAD (src), still_event); gst_pad_push_event (GST_BASE_SRC_PAD (src), still_event);
@ -596,6 +646,7 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock)
src->next_is_nav_block = FALSE; src->next_is_nav_block = FALSE;
src->next_nav_ts = GST_CLOCK_TIME_NONE; src->next_nav_ts = GST_CLOCK_TIME_NONE;
src->alloc_buf = NULL; src->alloc_buf = NULL;
src->in_still_state = FALSE;
break; break;
case DVDNAV_NAV_PACKET: case DVDNAV_NAV_PACKET:
{ {
@ -605,6 +656,8 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock)
GstClockTimeDiff new_base_time = ifotime_to_gsttime (&pci->pci_gi.e_eltm); GstClockTimeDiff new_base_time = ifotime_to_gsttime (&pci->pci_gi.e_eltm);
gboolean discont = FALSE; gboolean discont = FALSE;
src->in_still_state = FALSE;
if (new_start_ptm != src->cur_end_ts) if (new_start_ptm != src->cur_end_ts)
discont = TRUE; discont = TRUE;
@ -655,15 +708,13 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock)
} }
case DVDNAV_STOP: case DVDNAV_STOP:
/* End of the disc. EOS */ /* End of the disc. EOS */
g_print ("STOP found. End of disc\n"); dvdnav_reset (src->dvdnav);
ret = GST_FLOW_UNEXPECTED; ret = GST_FLOW_UNEXPECTED;
break; break;
case DVDNAV_STILL_FRAME: case DVDNAV_STILL_FRAME:
{ {
dvdnav_still_event_t *info = (dvdnav_still_event_t *) data; dvdnav_still_event_t *info = (dvdnav_still_event_t *) data;
g_print ("STILL frame duration %d\n", info->length);
if (!have_dvd_lock) { if (!have_dvd_lock) {
/* At a still frame but can't block, handle it later */ /* At a still frame but can't block, handle it later */
return GST_FLOW_WOULD_BLOCK; return GST_FLOW_WOULD_BLOCK;
@ -764,7 +815,7 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock)
src->highlight_event = NULL; src->highlight_event = NULL;
g_mutex_unlock (src->dvd_lock); g_mutex_unlock (src->dvd_lock);
g_print ("Highlight change - button: %d\n", src->active_button); g_print ("Sending highlight event - button %d\n", src->active_button);
gst_pad_push_event (GST_BASE_SRC_PAD (src), hl_event); gst_pad_push_event (GST_BASE_SRC_PAD (src), hl_event);
g_mutex_lock (src->dvd_lock); g_mutex_lock (src->dvd_lock);
} }
@ -860,8 +911,6 @@ rsn_dvdsrc_create (RsnPushSrc * psrc, GstBuffer ** outbuf)
gst_pad_push_event (GST_BASE_SRC_PAD (src), audio_select_event); gst_pad_push_event (GST_BASE_SRC_PAD (src), audio_select_event);
} }
g_mutex_lock (src->dvd_lock);
if (src->need_segment) { if (src->need_segment) {
/* Seamless segment update */ /* Seamless segment update */
GstEvent *seek; GstEvent *seek;
@ -871,6 +920,9 @@ rsn_dvdsrc_create (RsnPushSrc * psrc, GstBuffer ** outbuf)
gst_element_send_event (GST_ELEMENT (src), seek); gst_element_send_event (GST_ELEMENT (src), seek);
src->need_segment = FALSE; src->need_segment = FALSE;
} }
g_mutex_lock (src->dvd_lock);
if (src->cur_end_ts != GST_CLOCK_TIME_NONE) if (src->cur_end_ts != GST_CLOCK_TIME_NONE)
gst_segment_set_last_stop (segment, GST_FORMAT_TIME, src->cur_end_ts); gst_segment_set_last_stop (segment, GST_FORMAT_TIME, src->cur_end_ts);
@ -1037,15 +1089,8 @@ rsn_dvdsrc_handle_navigation_event (resinDvdSrc * src, GstEvent * event)
channel_hop = TRUE; channel_hop = TRUE;
} }
} else if (g_str_equal (key, "period")) { } else if (g_str_equal (key, "period")) {
gint title = 0; dvdnav_next_pg_search (src->dvdnav);
gint part = 0; channel_hop = TRUE;
if (dvdnav_current_title_info (src->dvdnav, &title, &part) && title > 0) {
if (dvdnav_part_play (src->dvdnav, title, part + 1) ==
DVDNAV_STATUS_ERR)
dvdnav_next_pg_search (src->dvdnav);
channel_hop = TRUE;
}
} else { } else {
g_print ("Unknown keypress: %s\n", key); g_print ("Unknown keypress: %s\n", key);
} }
@ -1152,6 +1197,10 @@ rsn_dvdsrc_prepare_audio_stream_event (resinDvdSrc * src, guint8 phys_stream)
GstStructure *s; GstStructure *s;
GstEvent *e; GstEvent *e;
if (phys_stream == src->cur_audio_phys_stream)
return;
src->cur_audio_phys_stream = phys_stream;
s = gst_structure_new ("application/x-gst-dvd", s = gst_structure_new ("application/x-gst-dvd",
"event", G_TYPE_STRING, "dvd-set-audio-track", "event", G_TYPE_STRING, "dvd-set-audio-track",
"physical-id", G_TYPE_INT, (gint) phys_stream, NULL); "physical-id", G_TYPE_INT, (gint) phys_stream, NULL);
@ -1170,6 +1219,14 @@ rsn_dvdsrc_prepare_spu_stream_event (resinDvdSrc * src, guint8 phys_stream,
GstStructure *s; GstStructure *s;
GstEvent *e; GstEvent *e;
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;
s = gst_structure_new ("application/x-gst-dvd", s = gst_structure_new ("application/x-gst-dvd",
"event", G_TYPE_STRING, "dvd-set-subpicture-track", "event", G_TYPE_STRING, "dvd-set-subpicture-track",
"physical-id", G_TYPE_INT, (gint) phys_stream, "physical-id", G_TYPE_INT, (gint) phys_stream,
@ -1186,6 +1243,7 @@ static gboolean
rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src) rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
{ {
vtsi_mat_t *vts_attr; vtsi_mat_t *vts_attr;
video_attr_t *v_attr;
audio_attr_t *a_attrs; audio_attr_t *a_attrs;
subp_attr_t *s_attrs; subp_attr_t *s_attrs;
gint n_audio, n_subp; gint n_audio, n_subp;
@ -1194,6 +1252,7 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
gint i; gint i;
gchar lang_code[3] = { '\0', '\0', '\0' }; gchar lang_code[3] = { '\0', '\0', '\0' };
gchar *t; gchar *t;
gboolean is_widescreen;
if (src->vts_attrs == NULL || src->vts_n >= src->vts_attrs->len) { if (src->vts_attrs == NULL || src->vts_n >= src->vts_attrs->len) {
if (src->vts_attrs) if (src->vts_attrs)
@ -1207,6 +1266,7 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
if (src->vts_n == 0) { if (src->vts_n == 0) {
/* VMGM info */ /* VMGM info */
vts_attr = NULL; vts_attr = NULL;
v_attr = &src->vmgm_attr.vmgm_video_attr;
a_attrs = &src->vmgm_attr.vmgm_audio_attr; a_attrs = &src->vmgm_attr.vmgm_audio_attr;
n_audio = MIN (1, src->vmgm_attr.nr_of_vmgm_audio_streams); n_audio = MIN (1, src->vmgm_attr.nr_of_vmgm_audio_streams);
s_attrs = &src->vmgm_attr.vmgm_subp_attr; s_attrs = &src->vmgm_attr.vmgm_subp_attr;
@ -1214,6 +1274,7 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
} else if (src->in_menu) { } else if (src->in_menu) {
/* VTSM attrs */ /* VTSM attrs */
vts_attr = &g_array_index (src->vts_attrs, vtsi_mat_t, src->vts_n); vts_attr = &g_array_index (src->vts_attrs, vtsi_mat_t, src->vts_n);
v_attr = &vts_attr->vtsm_video_attr;
a_attrs = &vts_attr->vtsm_audio_attr; a_attrs = &vts_attr->vtsm_audio_attr;
n_audio = vts_attr->nr_of_vtsm_audio_streams; n_audio = vts_attr->nr_of_vtsm_audio_streams;
s_attrs = &vts_attr->vtsm_subp_attr; s_attrs = &vts_attr->vtsm_subp_attr;
@ -1221,6 +1282,7 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
} else { } else {
/* VTS domain */ /* VTS domain */
vts_attr = &g_array_index (src->vts_attrs, vtsi_mat_t, src->vts_n); vts_attr = &g_array_index (src->vts_attrs, vtsi_mat_t, src->vts_n);
v_attr = &vts_attr->vts_video_attr;
a_attrs = vts_attr->vts_audio_attr; a_attrs = vts_attr->vts_audio_attr;
n_audio = vts_attr->nr_of_vts_audio_streams; n_audio = vts_attr->nr_of_vts_audio_streams;
s_attrs = vts_attr->vts_subp_attr; s_attrs = vts_attr->vts_subp_attr;
@ -1232,6 +1294,13 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
"event", G_TYPE_STRING, "dvd-lang-codes", NULL); "event", G_TYPE_STRING, "dvd-lang-codes", NULL);
e = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s); e = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
/* video */
is_widescreen = (v_attr->display_aspect_ratio != 0);
gst_structure_set (s, "video-pal-format", G_TYPE_BOOLEAN,
(v_attr->video_format != 0), NULL);
gst_structure_set (s, "video-widescreen", G_TYPE_BOOLEAN, is_widescreen,
NULL);
/* audio */ /* audio */
if (n_audio == 0) { if (n_audio == 0) {
/* Always create at least one audio stream */ /* Always create at least one audio stream */
@ -1301,6 +1370,10 @@ rsn_dvdsrc_prepare_clut_change_event (resinDvdSrc * src, const guint32 * clut)
gchar name[16]; gchar name[16];
int i; int i;
if (memcmp (src->cur_clut, clut, sizeof (guint32) * 16) == 0)
return;
memcpy (src->cur_clut, clut, sizeof (guint32) * 16);
structure = gst_structure_new ("application/x-gst-dvd", structure = gst_structure_new ("application/x-gst-dvd",
"event", G_TYPE_STRING, "dvd-spu-clut-change", NULL); "event", G_TYPE_STRING, "dvd-spu-clut-change", NULL);
@ -1492,9 +1565,9 @@ rsn_dvdsrc_nav_clock_cb (GstClock * clock, GstClockTime time, GstClockID id,
if (time < base_time + cur->running_ts) if (time < base_time + cur->running_ts)
break; /* Next NAV is in the future */ break; /* Next NAV is in the future */
g_print ("Activating nav pack for with TS %" GST_TIME_FORMAT GST_DEBUG_OBJECT (src, "Activating nav pack for with TS %" GST_TIME_FORMAT
" at running TS %" GST_TIME_FORMAT "\n", " at running TS %" GST_TIME_FORMAT, GST_TIME_ARGS (cur->ts),
GST_TIME_ARGS (cur->ts), GST_TIME_ARGS (cur->running_ts)); GST_TIME_ARGS (cur->running_ts));
rsn_dvdsrc_activate_nav_block (src, cur->buffer); rsn_dvdsrc_activate_nav_block (src, cur->buffer);
gst_buffer_unref (cur->buffer); gst_buffer_unref (cur->buffer);
@ -1523,29 +1596,31 @@ rsn_dvdsrc_schedule_nav_cb (resinDvdSrc * src, RsnDvdPendingNav * next_nav)
{ {
GstClock *clock; GstClock *clock;
GstClockTime base_ts; GstClockTime base_ts;
GstState cur_state;
gst_element_get_state (GST_ELEMENT (src), &cur_state, NULL, 0);
if (cur_state != GST_STATE_PLAYING)
return; /* Not in playing state yet */
GST_OBJECT_LOCK (src); GST_OBJECT_LOCK (src);
clock = GST_ELEMENT_CLOCK (src); if (GST_STATE (src) != GST_STATE_PLAYING) {
if (clock) GST_OBJECT_UNLOCK (src);
gst_object_ref (clock); return; /* Not in playing state yet */
base_ts = GST_ELEMENT (src)->base_time; }
GST_OBJECT_UNLOCK (src);
if (clock == NULL) clock = GST_ELEMENT_CLOCK (src);
base_ts = GST_ELEMENT (src)->base_time;
if (clock == NULL) {
GST_OBJECT_UNLOCK (src);
return; return;
}
gst_object_ref (clock);
src->nav_clock_id = gst_clock_new_single_shot_id (clock,
base_ts + next_nav->running_ts);
GST_OBJECT_UNLOCK (src);
GST_LOG_OBJECT (src, "Schedule nav pack for running TS %" GST_TIME_FORMAT, GST_LOG_OBJECT (src, "Schedule nav pack for running TS %" GST_TIME_FORMAT,
GST_TIME_ARGS (next_nav->running_ts)); GST_TIME_ARGS (next_nav->running_ts));
src->nav_clock_id = gst_clock_new_single_shot_id (clock,
base_ts + next_nav->running_ts);
gst_clock_id_wait_async (src->nav_clock_id, rsn_dvdsrc_nav_clock_cb, src); gst_clock_id_wait_async (src->nav_clock_id, rsn_dvdsrc_nav_clock_cb, src);
gst_object_unref (clock); gst_object_unref (clock);
} }
@ -1725,10 +1800,10 @@ rsn_dvdsrc_do_seek (RsnBaseSrc * bsrc, GstSegment * segment)
g_mutex_unlock (src->dvd_lock); g_mutex_unlock (src->dvd_lock);
} }
g_print ("Entering prepare_next_block after seek\n"); GST_LOG_OBJECT (src, "Entering prepare_next_block after seek");
if (rsn_dvdsrc_prepare_next_block (src, FALSE) != GST_FLOW_OK) if (rsn_dvdsrc_prepare_next_block (src, FALSE) != GST_FLOW_OK)
goto fail; goto fail;
g_print ("prepare_next_block after seek done\n"); GST_LOG_OBJECT (src, "prepare_next_block after seek done");
segment->format = GST_FORMAT_TIME; segment->format = GST_FORMAT_TIME;
/* The first TS output: */ /* The first TS output: */

View file

@ -88,6 +88,7 @@ struct _resinDvdSrc
gboolean flushing_seek; gboolean flushing_seek;
gboolean need_segment; gboolean need_segment;
gboolean active_highlight; gboolean active_highlight;
gboolean in_still_state;
GstBuffer *alloc_buf; GstBuffer *alloc_buf;
GstBuffer *next_buf; GstBuffer *next_buf;
@ -128,6 +129,12 @@ struct _resinDvdSrc
gboolean have_pci; gboolean have_pci;
pci_t cur_pci; pci_t cur_pci;
/* Current state tracking */
gint8 cur_audio_phys_stream;
gint8 cur_spu_phys_stream;
gboolean cur_spu_forced_only;
guint32 cur_clut[16];
}; };
struct _resinDvdSrcClass struct _resinDvdSrcClass

View file

@ -273,8 +273,6 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event)
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_STOP: case GST_EVENT_FLUSH_STOP:
rsn_audiomunge_reset (munge); rsn_audiomunge_reset (munge);
g_print ("*********** AUDIO MUNGE: FLUSH\n");
ret = gst_pad_push_event (munge->srcpad, event); ret = gst_pad_push_event (munge->srcpad, event);
break; break;
case GST_EVENT_NEWSEGMENT: case GST_EVENT_NEWSEGMENT:
@ -299,11 +297,6 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event)
rate, arate, format, start, stop, time); rate, arate, format, start, stop, time);
if (munge->have_audio) { if (munge->have_audio) {
g_print ("*********** AUDIO MUNGE NEWSEG: start %" GST_TIME_FORMAT
" stop %" GST_TIME_FORMAT " accum now %" GST_TIME_FORMAT
"\n", GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
GST_TIME_ARGS (segment->accum));
ret = gst_pad_push_event (munge->srcpad, event); ret = gst_pad_push_event (munge->srcpad, event);
break; break;
} }
@ -319,21 +312,23 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event)
* in the closing segment. * in the closing segment.
*/ */
if (segment->accum >= AUDIO_FILL_THRESHOLD || munge->in_still) { if (segment->accum >= AUDIO_FILL_THRESHOLD || munge->in_still) {
g_print ("*********** Send audio mebbe: accum = %" GST_TIME_FORMAT g_print ("*********** Sending audio fill: accum = %" GST_TIME_FORMAT
" still-state=%d\n", GST_TIME_ARGS (segment->accum), " still-state=%d\n", GST_TIME_ARGS (segment->accum),
munge->in_still); munge->in_still);
/* Just generate a 100ms silence buffer for now. FIXME: Fill the gap */ /* Just generate a 100ms silence buffer for now. FIXME: Fill the gap */
if (rsn_audiomunge_make_audio (munge, segment->start, if (rsn_audiomunge_make_audio (munge, segment->start,
GST_SECOND / 10) == GST_FLOW_OK) GST_SECOND / 10) == GST_FLOW_OK)
munge->have_audio = TRUE; munge->have_audio = TRUE;
} else { } else {
g_print ("*********** below thresh: accum = %" GST_TIME_FORMAT GST_LOG_OBJECT (munge, "Not sending audio fill buffer: "
"\n", GST_TIME_ARGS (segment->accum)); "segment accum below thresh: accum = %" GST_TIME_FORMAT,
GST_TIME_ARGS (segment->accum));
} }
g_print ("*********** AUDIO MUNGE NEWSEG: start %" GST_TIME_FORMAT GST_DEBUG_OBJECT (munge, "Sending newsegment: start %" GST_TIME_FORMAT
" stop %" GST_TIME_FORMAT " accum now %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT " accum now %" GST_TIME_FORMAT,
"\n", GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
GST_TIME_ARGS (segment->accum)); GST_TIME_ARGS (segment->accum));
ret = gst_pad_push_event (munge->srcpad, event); ret = gst_pad_push_event (munge->srcpad, event);
@ -342,6 +337,7 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event)
case GST_EVENT_CUSTOM_DOWNSTREAM: case GST_EVENT_CUSTOM_DOWNSTREAM:
{ {
const GstStructure *s = gst_event_get_structure (event); const GstStructure *s = gst_event_get_structure (event);
if (s && gst_structure_has_name (s, "application/x-gst-dvd")) if (s && gst_structure_has_name (s, "application/x-gst-dvd"))
rsn_audiomunge_handle_dvd_event (munge, event); rsn_audiomunge_handle_dvd_event (munge, event);

View file

@ -1046,9 +1046,6 @@ rsn_base_src_perform_seek (RsnBaseSrc * src, GstEvent * event, gboolean unlock)
FALSE, seeksegment.rate, seeksegment.applied_rate, FALSE, seeksegment.rate, seeksegment.applied_rate,
seeksegment.format, seeksegment.last_stop, seeksegment.format, seeksegment.last_stop,
seeksegment.stop, seeksegment.time); seeksegment.stop, seeksegment.time);
gst_segment_set_last_stop (&src->segment, GST_FORMAT_TIME,
seeksegment.last_stop);
} }
if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) { if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {

405
ext/resindvd/rsnparsetter.c Normal file
View file

@ -0,0 +1,405 @@
/*
* Copyright (C) 2008 Jan Schmidt <thaytan@noraisin.net>
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gst/gst.h>
#include <gst/video/video.h>
#include <string.h>
#include "rsnparsetter.h"
#include "rsnwrappedbuffer.h"
GST_DEBUG_CATEGORY_STATIC (rsn_parsetter_debug);
#define GST_CAT_DEFAULT rsn_parsetter_debug
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-rgb; video/x-raw-yuv")
);
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-rgb; video/x-raw-yuv")
);
static void rsn_parsetter_register_extra (GType rsn_parsetter_type);
GST_BOILERPLATE_FULL (RsnParSetter, rsn_parsetter, GstElement,
GST_TYPE_ELEMENT, rsn_parsetter_register_extra);
static void rsn_parsetter_finalize (GObject * object);
static GstFlowReturn rsn_parsetter_chain (GstPad * pad, GstBuffer * buf);
static gboolean rsn_parsetter_sink_event (GstPad * pad, GstEvent * event);
static gboolean rsn_parsetter_sink_setcaps (GstPad * pad, GstCaps * caps);
static GstFlowReturn rsn_parsetter_sink_bufferalloc (GstPad * pad,
guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
static GstCaps *rsn_parsetter_src_getcaps (GstPad * pad);
static GstCaps *rsn_parsetter_convert_caps (RsnParSetter * parset,
GstCaps * caps, gboolean widescreen);
static gboolean rsn_parsetter_check_caps (RsnParSetter * parset,
GstCaps * caps);
static void
rsn_parsetter_register_extra (GType rsn_parsetter_type)
{
GST_DEBUG_CATEGORY_INIT (rsn_parsetter_debug, "rsnparsetter", 0,
"Resin DVD aspect ratio adjuster");
}
static void
rsn_parsetter_base_init (gpointer gclass)
{
static GstElementDetails element_details = {
"Resin Aspect Ratio Setter",
"Filter/Video",
"Overrides caps on video buffers to force a particular display ratio",
"Jan Schmidt <thaytan@noraisin.net>"
};
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_factory));
gst_element_class_set_details (element_class, &element_details);
}
static void
rsn_parsetter_class_init (RsnParSetterClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gobject_class->finalize = rsn_parsetter_finalize;
}
static void
rsn_parsetter_init (RsnParSetter * parset, RsnParSetterClass * gclass)
{
parset->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
gst_pad_set_getcaps_function (parset->sinkpad,
GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
gst_pad_set_chain_function (parset->sinkpad,
GST_DEBUG_FUNCPTR (rsn_parsetter_chain));
gst_pad_set_event_function (parset->sinkpad,
GST_DEBUG_FUNCPTR (rsn_parsetter_sink_event));
gst_pad_set_setcaps_function (parset->sinkpad,
GST_DEBUG_FUNCPTR (rsn_parsetter_sink_setcaps));
gst_pad_set_bufferalloc_function (parset->sinkpad,
GST_DEBUG_FUNCPTR (rsn_parsetter_sink_bufferalloc));
gst_element_add_pad (GST_ELEMENT (parset), parset->sinkpad);
parset->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
gst_pad_set_getcaps_function (parset->srcpad,
GST_DEBUG_FUNCPTR (rsn_parsetter_src_getcaps));
gst_element_add_pad (GST_ELEMENT (parset), parset->srcpad);
parset->caps_lock = g_mutex_new ();
}
static void
rsn_parsetter_finalize (GObject * object)
{
RsnParSetter *parset = RSN_PARSETTER (object);
gst_caps_replace (&parset->outcaps, NULL);
gst_caps_replace (&parset->in_caps_last, NULL);
gst_caps_replace (&parset->in_caps_converted, NULL);
g_mutex_free (parset->caps_lock);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static GstFlowReturn
rsn_parsetter_chain (GstPad * pad, GstBuffer * buf)
{
RsnParSetter *parset = RSN_PARSETTER (GST_OBJECT_PARENT (pad));
/* If this is a buffer we wrapped up earlier, unwrap it now */
if (RSN_IS_WRAPPEDBUFFER (buf)) {
RsnWrappedBuffer *wrap_buf = RSN_WRAPPEDBUFFER (buf);
if (wrap_buf->owner == GST_ELEMENT (parset)) {
buf = rsn_wrappedbuffer_unwrap_and_unref (wrap_buf);
GST_DEBUG_OBJECT (parset, "Unwrapping %p yields buffer %p with caps %"
GST_PTR_FORMAT, wrap_buf, buf, GST_BUFFER_CAPS (buf));
}
}
if (parset->outcaps != GST_BUFFER_CAPS (buf)) {
if (parset->override_outcaps == FALSE &&
gst_caps_is_equal (parset->outcaps, GST_BUFFER_CAPS (buf))) {
/* Just update our output caps var */
gst_caps_replace (&parset->outcaps, GST_BUFFER_CAPS (buf));
goto out;
}
/* Replace the caps on the output buffer */
buf = gst_buffer_make_metadata_writable (buf);
gst_buffer_set_caps (buf, parset->outcaps);
GST_DEBUG_OBJECT (parset,
"Replacing caps on buffer %p with caps %" GST_PTR_FORMAT,
buf, parset->outcaps);
}
out:
return gst_pad_push (parset->srcpad, buf);
}
static gboolean
rsn_parsetter_sink_event (GstPad * pad, GstEvent * event)
{
RsnParSetter *parset = RSN_PARSETTER (gst_pad_get_parent (pad));
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 (type == NULL)
goto out;
if (strcmp (type, "dvd-video-format") == 0) {
gboolean is_widescreen;
gst_structure_get_boolean (structure, "video-widescreen", &is_widescreen);
GST_DEBUG_OBJECT (parset, "Video is %s",
parset->is_widescreen ? "16:9" : "4:3");
g_mutex_lock (parset->caps_lock);
if (parset->is_widescreen != is_widescreen) {
/* Force caps check */
gst_caps_replace (&parset->in_caps_last, NULL);
gst_caps_replace (&parset->in_caps_converted, NULL);
}
parset->is_widescreen = is_widescreen;
/* FIXME: Added for testing: */
// parset->is_widescreen = FALSE;
g_mutex_unlock (parset->caps_lock);
}
}
out:
gst_object_unref (GST_OBJECT (parset));
return gst_pad_event_default (pad, event);
}
static GstCaps *
rsn_parsetter_src_getcaps (GstPad * pad)
{
RsnParSetter *parset = RSN_PARSETTER (gst_pad_get_parent (pad));
GstCaps *ret;
const GstCaps *templ_caps = gst_pad_get_pad_template_caps (pad);
ret = gst_pad_peer_get_caps (parset->sinkpad);
if (ret == NULL)
ret = gst_caps_copy (templ_caps);
else {
GstCaps *temp;
temp = gst_caps_intersect (templ_caps, ret);
gst_caps_unref (ret);
ret = rsn_parsetter_convert_caps (parset, temp, parset->is_widescreen);
gst_caps_unref (temp);
}
gst_object_unref (parset);
return ret;
}
static gboolean
rsn_parsetter_check_caps (RsnParSetter * parset, GstCaps * caps)
{
GstStructure *s;
gint width, height;
gint par_n, par_d;
guint dar_n, dar_d;
gboolean ret = FALSE;
g_mutex_lock (parset->caps_lock);
if (caps == parset->in_caps_last ||
gst_caps_is_equal (caps, parset->in_caps_last)) {
ret = parset->in_caps_was_ok;
goto out;
}
/* Calculate the DAR from the incoming caps, and return TRUE if it matches
* the required DAR, FALSE if not */
s = gst_caps_get_structure (caps, 0);
if (s == NULL)
goto out;
if (!gst_structure_get_int (s, "width", &width) ||
!gst_structure_get_int (s, "height", &height))
goto out;
if (!gst_structure_get_fraction (s, "pixel-aspect-ratio", &par_n, &par_d))
par_n = par_d = 1;
if (!gst_video_calculate_display_ratio (&dar_n, &dar_d, width, height,
par_n, par_d, 1, 1))
goto out;
GST_DEBUG_OBJECT (parset,
"Incoming video caps now: w %d h %d PAR %d/%d = DAR %d/%d",
width, height, par_n, par_d, dar_n, dar_d);
if (parset->is_widescreen) {
if (dar_n == 16 && dar_d == 9)
ret = TRUE;
} else {
if (dar_n == 4 && dar_d == 3)
ret = TRUE;
}
gst_caps_replace (&parset->in_caps_last, caps);
gst_caps_replace (&parset->in_caps_converted, NULL);
parset->in_caps_was_ok = ret;
out:
g_mutex_unlock (parset->caps_lock);
return ret;
}
static GstCaps *
rsn_parsetter_convert_caps (RsnParSetter * parset, GstCaps * caps,
gboolean widescreen)
{
/* Duplicate the given caps, with a PAR that provides the desired DAR */
GstCaps *outcaps;
GstStructure *s;
gint width, height;
gint par_n, par_d;
guint dar_n, dar_d;
GValue par = { 0, };
g_mutex_lock (parset->caps_lock);
if (caps == parset->in_caps_last && parset->in_caps_converted) {
outcaps = gst_caps_ref (parset->in_caps_converted);
goto out;
}
outcaps = gst_caps_copy (caps);
/* Calculate the DAR from the incoming caps, and return TRUE if it matches
* the required DAR, FALSE if not */
s = gst_caps_get_structure (outcaps, 0);
if (s == NULL)
goto out;
if (!gst_structure_get_int (s, "width", &width) ||
!gst_structure_get_int (s, "height", &height))
goto out;
if (widescreen) {
dar_n = 16;
dar_d = 9;
} else {
dar_n = 4;
dar_d = 3;
}
par_n = dar_n * height;
par_d = dar_d * width;
g_value_init (&par, GST_TYPE_FRACTION);
gst_value_set_fraction (&par, par_n, par_d);
gst_structure_set_value (s, "pixel-aspect-ratio", &par);
g_value_unset (&par);
gst_caps_replace (&parset->in_caps_converted, outcaps);
out:
g_mutex_unlock (parset->caps_lock);
return outcaps;
}
static gboolean
rsn_parsetter_sink_setcaps (GstPad * pad, GstCaps * caps)
{
/* Check the new incoming caps against our current DAR, and mark
* whether the buffers will need adjusting */
RsnParSetter *parset = RSN_PARSETTER (gst_pad_get_parent (pad));
if (rsn_parsetter_check_caps (parset, caps)) {
parset->override_outcaps = FALSE;
gst_caps_replace (&parset->outcaps, caps);
} else {
GstCaps *override_caps = rsn_parsetter_convert_caps (parset, caps,
parset->is_widescreen);
if (parset->outcaps)
gst_caps_unref (parset->outcaps);
parset->outcaps = override_caps;
parset->override_outcaps = TRUE;
}
GST_DEBUG_OBJECT (parset, "caps changed: need_override now = %d",
parset->override_outcaps);
gst_object_unref (parset);
return TRUE;
}
static GstFlowReturn
rsn_parsetter_sink_bufferalloc (GstPad * pad, guint64 offset, guint size,
GstCaps * caps, GstBuffer ** buf)
{
RsnParSetter *parset = RSN_PARSETTER (gst_pad_get_parent (pad));
GstFlowReturn ret;
GST_LOG_OBJECT (parset, "Entering bufferalloc");
if (rsn_parsetter_check_caps (parset, caps)) {
ret = gst_pad_alloc_buffer (parset->srcpad, offset, size, caps, buf);
GST_LOG_OBJECT (parset, "Not wrapping buf %p", *buf);
} else {
/* Allocate and wrap a downstream buffer */
GstBuffer *orig_buf;
GstBuffer *outbuf;
GstCaps *override_caps = rsn_parsetter_convert_caps (parset, caps,
parset->is_widescreen);
ret = gst_pad_alloc_buffer (parset->srcpad, offset, size,
override_caps, &orig_buf);
gst_caps_unref (override_caps);
if (ret != GST_FLOW_OK)
return ret;
outbuf = (GstBuffer *) rsn_wrapped_buffer_new (orig_buf);
if (!outbuf) {
/* FIXME: Throw error */
return GST_FLOW_ERROR;
}
rsn_wrapped_buffer_set_owner (RSN_WRAPPEDBUFFER (outbuf),
GST_ELEMENT (parset));
gst_buffer_set_caps (outbuf, caps);
GST_LOG_OBJECT (parset,
"Wrapped ds buf %p with caps %" GST_PTR_FORMAT
" into new buf %p with caps %" GST_PTR_FORMAT,
orig_buf, GST_BUFFER_CAPS (orig_buf), outbuf, GST_BUFFER_CAPS (outbuf));
*buf = outbuf;
}
gst_object_unref (GST_OBJECT (parset));
return ret;
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2008 Jan Schmidt <thaytan@noraisin.net>
*/
#ifndef __RSN_PARSETTER_H__
#define __RSN_PARSETTER_H__
#include <gst/gst.h>
#include "rsnwrappedbuffer.h"
G_BEGIN_DECLS
#define RSN_TYPE_RSNPARSETTER \
(rsn_parsetter_get_type())
#define RSN_PARSETTER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),RSN_TYPE_RSNPARSETTER,RsnParSetter))
#define RSN_PARSETTER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),RSN_TYPE_RSNPARSETTER,RsnParSetterClass))
#define RSN_IS_PARSETTER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),RSN_TYPE_RSNPARSETTER))
#define RSN_IS_PARSETTER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),RSN_TYPE_RSNPARSETTER))
typedef struct _RsnParSetter RsnParSetter;
typedef struct _RsnParSetterClass RsnParSetterClass;
struct _RsnParSetter
{
GstElement element;
GstPad *sinkpad, *srcpad;
gboolean override_outcaps;
GstCaps *outcaps;
gboolean is_widescreen;
GMutex *caps_lock;
GstCaps *in_caps_last;
gboolean in_caps_was_ok;
GstCaps *in_caps_converted;
};
struct _RsnParSetterClass
{
GstElementClass parent_class;
};
GType rsn_parsetter_get_type (void);
G_END_DECLS
#endif /* __RSN_PARSETTER_H__ */

View file

@ -0,0 +1,152 @@
/* GStreamer
* Copyright (C) 2008 Jan Schmidt <thaytan@noraisin.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <gst/gst.h>
#include "rsnwrappedbuffer.h"
GST_BOILERPLATE (RsnWrappedBuffer, rsn_wrappedbuffer,
GstBuffer, GST_TYPE_BUFFER);
static gboolean
rsn_wrapped_buffer_default_release (GstElement * owner, RsnWrappedBuffer * buf);
static void rsn_wrapped_buffer_finalize (RsnWrappedBuffer * wrap_buf);
static void
rsn_wrappedbuffer_base_init (gpointer gclass)
{
}
static void
rsn_wrappedbuffer_class_init (RsnWrappedBufferClass * klass)
{
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (klass);
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
rsn_wrapped_buffer_finalize;
}
static void
rsn_wrappedbuffer_init (RsnWrappedBuffer * buf, RsnWrappedBufferClass * gclass)
{
buf->release = rsn_wrapped_buffer_default_release;
}
static void
rsn_wrapped_buffer_finalize (RsnWrappedBuffer * wrap_buf)
{
if (wrap_buf->release) {
/* Release might increment the refcount to recycle and return TRUE,
* in which case, exit without chaining up */
if (wrap_buf->release (wrap_buf->owner, wrap_buf))
return;
}
GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (wrap_buf));
}
RsnWrappedBuffer *
rsn_wrapped_buffer_new (GstBuffer * buf_to_wrap)
{
RsnWrappedBuffer *buf;
g_return_val_if_fail (buf_to_wrap, NULL);
buf = (RsnWrappedBuffer *) gst_mini_object_new (RSN_TYPE_WRAPPEDBUFFER);
if (buf == NULL)
return NULL;
buf->wrapped_buffer = buf_to_wrap;
GST_BUFFER_DATA (buf) = GST_BUFFER_DATA (buf_to_wrap);
GST_BUFFER_SIZE (buf) = GST_BUFFER_SIZE (buf_to_wrap);
gst_buffer_copy_metadata (GST_BUFFER (buf), buf_to_wrap, GST_BUFFER_COPY_ALL);
/* If the wrapped buffer isn't writable, make sure this one isn't either */
if (!gst_buffer_is_writable (buf_to_wrap))
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY);
return buf;
}
void
rsn_wrapped_buffer_set_owner (RsnWrappedBuffer * wrapped_buf,
GstElement * owner)
{
g_return_if_fail (wrapped_buf != NULL);
if (wrapped_buf->owner)
gst_object_unref (wrapped_buf->owner);
if (owner)
wrapped_buf->owner = gst_object_ref (owner);
else
wrapped_buf->owner = NULL;
}
void
rsn_wrapped_buffer_set_releasefunc (RsnWrappedBuffer * wrapped_buf,
RsnWrappedBufferReleaseFunc release_func)
{
g_return_if_fail (wrapped_buf != NULL);
wrapped_buf->release = release_func;
}
static gboolean
rsn_wrapped_buffer_default_release (GstElement * owner, RsnWrappedBuffer * buf)
{
g_return_val_if_fail (buf != NULL, FALSE);
g_return_val_if_fail (buf->wrapped_buffer != NULL, FALSE);
gst_buffer_unref (buf->wrapped_buffer);
if (buf->owner)
gst_object_unref (buf->owner);
return FALSE;
}
GstBuffer *
rsn_wrappedbuffer_unwrap_and_unref (RsnWrappedBuffer * wrap_buf)
{
GstBuffer *buf;
gboolean is_readonly;
g_return_val_if_fail (wrap_buf != NULL, NULL);
g_return_val_if_fail (wrap_buf->wrapped_buffer != NULL, NULL);
buf = gst_buffer_ref (wrap_buf->wrapped_buffer);
/* Copy changed metadata back to the wrapped buffer from the wrapper,
* except the the read-only flag and the caps. */
is_readonly = GST_BUFFER_FLAG_IS_SET (wrap_buf, GST_BUFFER_FLAG_READONLY);
gst_buffer_copy_metadata (buf, GST_BUFFER (wrap_buf),
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
if (!is_readonly)
GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_READONLY);
gst_buffer_unref (GST_BUFFER (wrap_buf));
return buf;
}

View file

@ -0,0 +1,69 @@
/* GStreamer
* Copyright (C) 2008 Jan Schmidt <thaytan@noraisin.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __RSN_WRAPPERBUFFER_H__
#define __RSN_WRAPPERBUFFER_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define RSN_TYPE_WRAPPEDBUFFER (rsn_wrappedbuffer_get_type())
#define RSN_WRAPPEDBUFFER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), RSN_TYPE_WRAPPEDBUFFER, \
RsnWrappedBuffer))
#define RSN_WRAPPEDBUFFER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), RSN_TYPE_WRAPPEDBUFFER, \
RsnWrappedBufferClass))
#define RSN_IS_WRAPPEDBUFFER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), RSN_TYPE_WRAPPEDBUFFER))
#define RSN_IS_WRAPPEDBUFFER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), RSN_TYPE_WRAPPEDBUFFER))
typedef struct _RsnWrappedBuffer RsnWrappedBuffer;
typedef struct _RsnWrappedBufferClass RsnWrappedBufferClass;
typedef gboolean (*RsnWrappedBufferReleaseFunc)(GstElement *owner,
RsnWrappedBuffer *buf);
struct _RsnWrappedBuffer {
GstBuffer buffer;
GstBuffer *wrapped_buffer;
GstElement *owner;
RsnWrappedBufferReleaseFunc release;
};
struct _RsnWrappedBufferClass
{
GstBufferClass parent_class;
};
RsnWrappedBuffer *rsn_wrapped_buffer_new (GstBuffer *buf_to_wrap);
GstBuffer *rsn_wrappedbuffer_unwrap_and_unref (RsnWrappedBuffer *wrap_buf);
void rsn_wrapped_buffer_set_owner (RsnWrappedBuffer *wrapped_buf,
GstElement *owner);
void rsn_wrapped_buffer_set_releasefunc (RsnWrappedBuffer *wrapped_buf,
RsnWrappedBufferReleaseFunc release_func);
GType rsn_wrappedbuffer_get_type (void);
G_END_DECLS
#endif