mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
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:
parent
f79bf9a0fb
commit
9a392ef442
14 changed files with 980 additions and 153 deletions
35
ChangeLog
35
ChangeLog
|
@ -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>
|
||||
|
||||
* gst/mpegtsparse/mpegtspacketizer.c:
|
||||
|
|
|
@ -12,10 +12,12 @@ libresindvd_la_SOURCES = \
|
|||
resindvdsrc.c \
|
||||
gstmpegdesc.c \
|
||||
gstmpegdemux.c \
|
||||
gstpesfilter.c
|
||||
gstpesfilter.c \
|
||||
rsnparsetter.c \
|
||||
rsnwrappedbuffer.c
|
||||
|
||||
libresindvd_la_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(DVDNAV_CFLAGS)
|
||||
libresindvd_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(DVDNAV_LIBS)
|
||||
libresindvd_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(DVDNAV_CFLAGS)
|
||||
libresindvd_la_LIBADD = $(GST_PLUGINS_BASE_CFLAGS) -lgstvideo-$(GST_MAJORMINOR) $(GST_BASE_LIBS) $(GST_LIBS) $(DVDNAV_LIBS)
|
||||
libresindvd_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
|
||||
noinst_HEADERS = resindvdbin.h \
|
||||
|
@ -27,4 +29,5 @@ noinst_HEADERS = resindvdbin.h \
|
|||
gstmpegdefs.h \
|
||||
gstmpegdesc.h \
|
||||
gstmpegdemux.h \
|
||||
gstpesfilter.h
|
||||
gstpesfilter.h \
|
||||
rsnparsetter.h
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
/* The SCR_MUNGE value is used to offset the scr_adjust value, to avoid
|
||||
* 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 */
|
||||
#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:
|
||||
{
|
||||
gint mpeg_version = 1;
|
||||
|
||||
if (stream_type == ST_VIDEO_MPEG2 ||
|
||||
(stream_type == ST_GST_VIDEO_MPEG1_OR_2 && demux->is_mpeg2_pack)) {
|
||||
mpeg_version = 2;
|
||||
|
@ -584,19 +585,35 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
|
|||
|
||||
if (strcmp (type, "dvd-lang-codes") == 0) {
|
||||
GstEvent **p_ev;
|
||||
|
||||
/* Store the language codes event on the element, then iterate over the
|
||||
* streams it specifies and retrieve them. The stream creation code then
|
||||
* creates the pad appropriately and sends tag events as needed */
|
||||
p_ev = &demux->lang_codes;
|
||||
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");
|
||||
|
||||
/* 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);
|
||||
/* 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
|
||||
* is present */
|
||||
|
@ -646,6 +663,7 @@ gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
|
|||
/* And subtitle streams */
|
||||
for (i = 0; i < MAX_DVD_SUBPICTURE_STREAMS; i++) {
|
||||
gint stream_format;
|
||||
|
||||
g_snprintf (cur_stream_name, 32, "subpicture-%d-format", i);
|
||||
|
||||
if (!gst_structure_get_int (structure, cur_stream_name, &stream_format))
|
||||
|
|
|
@ -7,5 +7,6 @@ else
|
|||
fi
|
||||
|
||||
gst-launch rsndvdbin name=dvd "$DEVICE_OPT" \
|
||||
dvd. ! ffmpegcolorspace ! videoscale ! autovideosink \
|
||||
dvd. ! audioconvert ! autoaudiosink
|
||||
dvd. ! dvdspu name=spu ! ffmpegcolorspace ! videoscale ! ximagesink force-aspect-ratio=true \
|
||||
dvd. ! spu. \
|
||||
dvd. ! audioconvert ! autoaudiosink $@
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "resindvdsrc.h"
|
||||
#include "rsnstreamselector.h"
|
||||
#include "rsnaudiomunge.h"
|
||||
#include "rsnparsetter.h"
|
||||
|
||||
#include "gstmpegdemux.h"
|
||||
|
||||
|
@ -58,13 +59,23 @@ static GstStaticPadTemplate video_src_template =
|
|||
GST_STATIC_PAD_TEMPLATE ("video",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_SOMETIMES,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
GST_STATIC_CAPS
|
||||
("video/mpeg, mpegversion=(int) { 1, 2 }, systemstream=false")
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate audio_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("audio",
|
||||
GST_STATIC_PAD_TEMPLATE ("audio",
|
||||
GST_PAD_SRC,
|
||||
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_finalize (GObject * object);
|
||||
|
@ -103,6 +114,8 @@ rsn_dvdbin_base_init (gpointer gclass)
|
|||
gst_static_pad_template_get (&video_src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
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);
|
||||
|
||||
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]),
|
||||
"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",
|
||||
"video decoder buffer"))
|
||||
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],
|
||||
"max-size-time", G_GUINT64_CONSTANT (0), "max-size-bytes", 0,
|
||||
"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,
|
||||
RSN_TYPE_STREAM_SELECTOR, "subpselect", "Subpicture stream selector"))
|
||||
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");
|
||||
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)
|
||||
goto failed_spu_ghost;
|
||||
ghost = gst_ghost_pad_new ("video", src);
|
||||
ghost = gst_ghost_pad_new ("subpicture", src);
|
||||
if (ghost == NULL)
|
||||
goto failed_spu_ghost;
|
||||
if (!gst_element_add_pad (GST_ELEMENT (dvdbin), ghost))
|
||||
goto failed_spu_ghost;
|
||||
gst_object_unref (src);
|
||||
src = sink = NULL;
|
||||
ghost = src = sink = NULL;
|
||||
|
||||
if (!try_create_piece (dvdbin, DVD_ELEM_AUD_SELECT, NULL,
|
||||
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))
|
||||
goto failed_aud_ghost;
|
||||
gst_object_unref (src);
|
||||
src = sink = NULL;
|
||||
ghost = src = sink = NULL;
|
||||
|
||||
return TRUE;
|
||||
|
||||
failed_connect:
|
||||
GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
|
||||
("Could not connect DVD source and demuxer elements"));
|
||||
return FALSE;
|
||||
failed_spu_connect:
|
||||
goto error_out;
|
||||
failed_vidq_connect:
|
||||
GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
|
||||
("Could not connect DVD video buffer and spu elements"));
|
||||
if (src != NULL)
|
||||
gst_object_unref (src);
|
||||
if (sink != NULL)
|
||||
gst_object_unref (sink);
|
||||
return FALSE;
|
||||
("Could not connect DVD aspect ratio adjuster and video buffer elements"));
|
||||
goto error_out;
|
||||
failed_vidq_ghost:
|
||||
GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
|
||||
("Could not ghost SPU output pad"));
|
||||
goto error_out;
|
||||
failed_spu_ghost:
|
||||
GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
|
||||
("Could not ghost SPU output pad"));
|
||||
if (src != NULL)
|
||||
gst_object_unref (src);
|
||||
if (ghost != NULL)
|
||||
gst_object_unref (ghost);
|
||||
return FALSE;
|
||||
goto error_out;
|
||||
failed_aud_connect:
|
||||
GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
|
||||
("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)
|
||||
gst_object_unref (src);
|
||||
if (sink != NULL)
|
||||
gst_object_unref (sink);
|
||||
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
|
||||
|
@ -578,7 +592,7 @@ demux_pad_added (GstElement * element, GstPad * pad, RsnDvdBin * dvdbin)
|
|||
GstCaps *caps;
|
||||
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);
|
||||
if (caps == NULL) {
|
||||
|
@ -622,7 +636,7 @@ demux_pad_added (GstElement * element, GstPad * pad, RsnDvdBin * dvdbin)
|
|||
mq_pad = connect_thru_mq (dvdbin, pad);
|
||||
if (mq_pad == NULL)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -648,9 +662,9 @@ viddec_pad_added (GstElement * element, GstPad * pad, gboolean last,
|
|||
{
|
||||
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_object_unref (q_pad);
|
||||
|
@ -663,7 +677,7 @@ auddec_pad_added (GstElement * element, GstPad * pad, gboolean last,
|
|||
{
|
||||
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 =
|
||||
gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "sink");
|
||||
|
|
|
@ -44,12 +44,13 @@ typedef struct _RsnDvdBinClass RsnDvdBinClass;
|
|||
#define DVD_ELEM_MQUEUE 2
|
||||
#define DVD_ELEM_SPU 3
|
||||
#define DVD_ELEM_VIDDEC 4
|
||||
#define DVD_ELEM_AUDDEC 5
|
||||
#define DVD_ELEM_VIDQ 6
|
||||
#define DVD_ELEM_SPU_SELECT 7
|
||||
#define DVD_ELEM_AUD_SELECT 8
|
||||
#define DVD_ELEM_AUD_MUNGE 9
|
||||
#define DVD_ELEM_LAST 10
|
||||
#define DVD_ELEM_PARSET 5
|
||||
#define DVD_ELEM_AUDDEC 6
|
||||
#define DVD_ELEM_VIDQ 7
|
||||
#define DVD_ELEM_SPU_SELECT 8
|
||||
#define DVD_ELEM_AUD_SELECT 9
|
||||
#define DVD_ELEM_AUD_MUNGE 10
|
||||
#define DVD_ELEM_LAST 11
|
||||
|
||||
struct _RsnDvdBin
|
||||
{
|
||||
|
|
|
@ -344,6 +344,12 @@ rsn_dvdsrc_start (RsnBaseSrc * bsrc)
|
|||
src->in_menu = FALSE;
|
||||
|
||||
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);
|
||||
|
||||
return TRUE;
|
||||
|
@ -494,8 +500,8 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration)
|
|||
GstEvent *seg_event;
|
||||
GstSegment *segment = &(GST_BASE_SRC (src)->segment);
|
||||
|
||||
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",
|
||||
|
@ -518,12 +524,22 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration)
|
|||
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)
|
||||
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);
|
||||
|
||||
g_mutex_lock (src->branch_lock);
|
||||
|
||||
src->in_still_state = TRUE;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (src, "Re-entering still wait");
|
||||
g_mutex_lock (src->branch_lock);
|
||||
}
|
||||
|
||||
if (src->branching) {
|
||||
GST_INFO_OBJECT (src, "Branching - aborting still");
|
||||
g_mutex_unlock (src->branch_lock);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -535,28 +551,62 @@ rsn_dvdsrc_do_still (resinDvdSrc * src, int duration)
|
|||
* don't skip it
|
||||
*/
|
||||
src->need_segment = TRUE;
|
||||
|
||||
g_mutex_unlock (src->dvd_lock);
|
||||
GST_LOG_OBJECT (src, "Entering cond_wait still");
|
||||
g_cond_wait (src->still_cond, src->branch_lock);
|
||||
GST_LOG_OBJECT (src, "cond_wait still over, branching = %d",
|
||||
src->branching);
|
||||
|
||||
if (src->branching) {
|
||||
g_mutex_unlock (src->branch_lock);
|
||||
g_mutex_lock (src->dvd_lock);
|
||||
return TRUE;
|
||||
}
|
||||
src->in_still_state = FALSE;
|
||||
|
||||
g_mutex_unlock (src->branch_lock);
|
||||
g_mutex_lock (src->dvd_lock);
|
||||
} 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
|
||||
* in multiple steps if we get paused/unpaused */
|
||||
if (dvdnav_still_skip (src->dvdnav) != DVDNAV_STATUS_OK)
|
||||
return FALSE;
|
||||
|
||||
/* 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, TRUE, NULL);
|
||||
still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
|
||||
g_mutex_unlock (src->dvd_lock);
|
||||
GST_LOG_OBJECT (src, "cond_timed_wait still");
|
||||
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);
|
||||
|
||||
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);
|
||||
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_nav_ts = GST_CLOCK_TIME_NONE;
|
||||
src->alloc_buf = NULL;
|
||||
src->in_still_state = FALSE;
|
||||
break;
|
||||
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);
|
||||
gboolean discont = FALSE;
|
||||
|
||||
src->in_still_state = FALSE;
|
||||
|
||||
if (new_start_ptm != src->cur_end_ts)
|
||||
discont = TRUE;
|
||||
|
||||
|
@ -655,15 +708,13 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock)
|
|||
}
|
||||
case DVDNAV_STOP:
|
||||
/* End of the disc. EOS */
|
||||
g_print ("STOP found. End of disc\n");
|
||||
dvdnav_reset (src->dvdnav);
|
||||
ret = GST_FLOW_UNEXPECTED;
|
||||
break;
|
||||
case DVDNAV_STILL_FRAME:
|
||||
{
|
||||
dvdnav_still_event_t *info = (dvdnav_still_event_t *) data;
|
||||
|
||||
g_print ("STILL frame duration %d\n", info->length);
|
||||
|
||||
if (!have_dvd_lock) {
|
||||
/* At a still frame but can't block, handle it later */
|
||||
return GST_FLOW_WOULD_BLOCK;
|
||||
|
@ -764,7 +815,7 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock)
|
|||
|
||||
src->highlight_event = NULL;
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
g_mutex_lock (src->dvd_lock);
|
||||
|
||||
if (src->need_segment) {
|
||||
/* Seamless segment update */
|
||||
GstEvent *seek;
|
||||
|
@ -871,6 +920,9 @@ rsn_dvdsrc_create (RsnPushSrc * psrc, GstBuffer ** outbuf)
|
|||
gst_element_send_event (GST_ELEMENT (src), seek);
|
||||
src->need_segment = FALSE;
|
||||
}
|
||||
|
||||
g_mutex_lock (src->dvd_lock);
|
||||
|
||||
if (src->cur_end_ts != GST_CLOCK_TIME_NONE)
|
||||
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;
|
||||
}
|
||||
} else if (g_str_equal (key, "period")) {
|
||||
gint title = 0;
|
||||
gint part = 0;
|
||||
|
||||
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 {
|
||||
g_print ("Unknown keypress: %s\n", key);
|
||||
}
|
||||
|
@ -1152,6 +1197,10 @@ rsn_dvdsrc_prepare_audio_stream_event (resinDvdSrc * src, guint8 phys_stream)
|
|||
GstStructure *s;
|
||||
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",
|
||||
"event", G_TYPE_STRING, "dvd-set-audio-track",
|
||||
"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;
|
||||
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",
|
||||
"event", G_TYPE_STRING, "dvd-set-subpicture-track",
|
||||
"physical-id", G_TYPE_INT, (gint) phys_stream,
|
||||
|
@ -1186,6 +1243,7 @@ static gboolean
|
|||
rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
|
||||
{
|
||||
vtsi_mat_t *vts_attr;
|
||||
video_attr_t *v_attr;
|
||||
audio_attr_t *a_attrs;
|
||||
subp_attr_t *s_attrs;
|
||||
gint n_audio, n_subp;
|
||||
|
@ -1194,6 +1252,7 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
|
|||
gint i;
|
||||
gchar lang_code[3] = { '\0', '\0', '\0' };
|
||||
gchar *t;
|
||||
gboolean is_widescreen;
|
||||
|
||||
if (src->vts_attrs == NULL || src->vts_n >= src->vts_attrs->len) {
|
||||
if (src->vts_attrs)
|
||||
|
@ -1207,6 +1266,7 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
|
|||
if (src->vts_n == 0) {
|
||||
/* VMGM info */
|
||||
vts_attr = NULL;
|
||||
v_attr = &src->vmgm_attr.vmgm_video_attr;
|
||||
a_attrs = &src->vmgm_attr.vmgm_audio_attr;
|
||||
n_audio = MIN (1, src->vmgm_attr.nr_of_vmgm_audio_streams);
|
||||
s_attrs = &src->vmgm_attr.vmgm_subp_attr;
|
||||
|
@ -1214,6 +1274,7 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
|
|||
} else if (src->in_menu) {
|
||||
/* VTSM attrs */
|
||||
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;
|
||||
n_audio = vts_attr->nr_of_vtsm_audio_streams;
|
||||
s_attrs = &vts_attr->vtsm_subp_attr;
|
||||
|
@ -1221,6 +1282,7 @@ rsn_dvdsrc_prepare_streamsinfo_event (resinDvdSrc * src)
|
|||
} else {
|
||||
/* VTS domain */
|
||||
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;
|
||||
n_audio = vts_attr->nr_of_vts_audio_streams;
|
||||
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);
|
||||
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 */
|
||||
if (n_audio == 0) {
|
||||
/* 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];
|
||||
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",
|
||||
"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)
|
||||
break; /* Next NAV is in the future */
|
||||
|
||||
g_print ("Activating nav pack for with TS %" GST_TIME_FORMAT
|
||||
" at running TS %" GST_TIME_FORMAT "\n",
|
||||
GST_TIME_ARGS (cur->ts), GST_TIME_ARGS (cur->running_ts));
|
||||
GST_DEBUG_OBJECT (src, "Activating nav pack for with TS %" GST_TIME_FORMAT
|
||||
" at running TS %" GST_TIME_FORMAT, GST_TIME_ARGS (cur->ts),
|
||||
GST_TIME_ARGS (cur->running_ts));
|
||||
rsn_dvdsrc_activate_nav_block (src, cur->buffer);
|
||||
|
||||
gst_buffer_unref (cur->buffer);
|
||||
|
@ -1523,29 +1596,31 @@ rsn_dvdsrc_schedule_nav_cb (resinDvdSrc * src, RsnDvdPendingNav * next_nav)
|
|||
{
|
||||
GstClock *clock;
|
||||
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);
|
||||
clock = GST_ELEMENT_CLOCK (src);
|
||||
if (clock)
|
||||
gst_object_ref (clock);
|
||||
base_ts = GST_ELEMENT (src)->base_time;
|
||||
if (GST_STATE (src) != GST_STATE_PLAYING) {
|
||||
GST_OBJECT_UNLOCK (src);
|
||||
return; /* Not in playing state yet */
|
||||
}
|
||||
|
||||
if (clock == NULL)
|
||||
clock = GST_ELEMENT_CLOCK (src);
|
||||
base_ts = GST_ELEMENT (src)->base_time;
|
||||
|
||||
if (clock == NULL) {
|
||||
GST_OBJECT_UNLOCK (src);
|
||||
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_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_object_unref (clock);
|
||||
}
|
||||
|
||||
|
@ -1725,10 +1800,10 @@ rsn_dvdsrc_do_seek (RsnBaseSrc * bsrc, GstSegment * segment)
|
|||
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)
|
||||
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;
|
||||
/* The first TS output: */
|
||||
|
|
|
@ -88,6 +88,7 @@ struct _resinDvdSrc
|
|||
gboolean flushing_seek;
|
||||
gboolean need_segment;
|
||||
gboolean active_highlight;
|
||||
gboolean in_still_state;
|
||||
|
||||
GstBuffer *alloc_buf;
|
||||
GstBuffer *next_buf;
|
||||
|
@ -128,6 +129,12 @@ struct _resinDvdSrc
|
|||
|
||||
gboolean have_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
|
||||
|
|
|
@ -273,8 +273,6 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event)
|
|||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
rsn_audiomunge_reset (munge);
|
||||
|
||||
g_print ("*********** AUDIO MUNGE: FLUSH\n");
|
||||
ret = gst_pad_push_event (munge->srcpad, event);
|
||||
break;
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
|
@ -299,11 +297,6 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event)
|
|||
rate, arate, format, start, stop, time);
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@ -319,21 +312,23 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event)
|
|||
* in the closing segment.
|
||||
*/
|
||||
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),
|
||||
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 {
|
||||
g_print ("*********** below thresh: accum = %" GST_TIME_FORMAT
|
||||
"\n", GST_TIME_ARGS (segment->accum));
|
||||
GST_LOG_OBJECT (munge, "Not sending audio fill buffer: "
|
||||
"segment accum below thresh: accum = %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (segment->accum));
|
||||
}
|
||||
|
||||
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_DEBUG_OBJECT (munge, "Sending newsegment: start %" GST_TIME_FORMAT
|
||||
" stop %" GST_TIME_FORMAT " accum now %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
|
||||
GST_TIME_ARGS (segment->accum));
|
||||
|
||||
ret = gst_pad_push_event (munge->srcpad, event);
|
||||
|
@ -342,6 +337,7 @@ rsn_audiomunge_sink_event (GstPad * pad, GstEvent * event)
|
|||
case GST_EVENT_CUSTOM_DOWNSTREAM:
|
||||
{
|
||||
const GstStructure *s = gst_event_get_structure (event);
|
||||
|
||||
if (s && gst_structure_has_name (s, "application/x-gst-dvd"))
|
||||
rsn_audiomunge_handle_dvd_event (munge, event);
|
||||
|
||||
|
|
|
@ -1046,9 +1046,6 @@ rsn_base_src_perform_seek (RsnBaseSrc * src, GstEvent * event, gboolean unlock)
|
|||
FALSE, seeksegment.rate, seeksegment.applied_rate,
|
||||
seeksegment.format, seeksegment.last_stop,
|
||||
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) {
|
||||
|
|
405
ext/resindvd/rsnparsetter.c
Normal file
405
ext/resindvd/rsnparsetter.c
Normal 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;
|
||||
}
|
54
ext/resindvd/rsnparsetter.h
Normal file
54
ext/resindvd/rsnparsetter.h
Normal 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__ */
|
152
ext/resindvd/rsnwrappedbuffer.c
Normal file
152
ext/resindvd/rsnwrappedbuffer.c
Normal 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;
|
||||
}
|
69
ext/resindvd/rsnwrappedbuffer.h
Normal file
69
ext/resindvd/rsnwrappedbuffer.h
Normal 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
|
Loading…
Reference in a new issue