#include <string.h>
#include <math.h>
#include <gst/video/video.h>
+#include <gst/video/gstvideopool.h>
#include "gstdvdec.h"
static GstStaticPadTemplate src_temp = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-raw-yuv, "
- "format = (fourcc) YUY2, "
- "width = (int) 720, "
- "framerate = (fraction) [ 1/1, 60/1 ];"
- "video/x-raw-rgb, "
- "bpp = (int) 32, "
- "depth = (int) 24, "
- "endianness = (int) " G_STRINGIFY (G_BIG_ENDIAN) ", "
- "red_mask = (int) 0x0000ff00, "
- "green_mask = (int) 0x00ff0000, "
- "blue_mask = (int) 0xff000000, "
- "width = (int) 720, "
- "framerate = (fraction) [ 1/1, 60/1 ];"
- "video/x-raw-rgb, "
- "bpp = (int) 24, "
- "depth = (int) 24, "
- "endianness = (int) " G_STRINGIFY (G_BIG_ENDIAN) ", "
- "red_mask = (int) 0x00ff0000, "
- "green_mask = (int) 0x0000ff00, "
- "blue_mask = (int) 0x000000ff, "
- "width = (int) 720, " "framerate = (fraction) [ 1/1, 60/1 ]")
+ GST_STATIC_CAPS ("video/x-raw, "
+ "format = (string) { YUY2, BGRx, RGB }, "
+ "framerate = (fraction) [ 1/1, 60/1 ], "
+ "width = (int) 720, " "height = (int) { 576, 480 }")
);
#define GST_TYPE_DVDEC_QUALITY (gst_dvdec_quality_get_type())
return qtype;
}
-GST_BOILERPLATE (GstDVDec, gst_dvdec, GstElement, GST_TYPE_ELEMENT);
+#define gst_dvdec_parent_class parent_class
+G_DEFINE_TYPE (GstDVDec, gst_dvdec, GST_TYPE_ELEMENT);
-static void gst_dvdec_finalize (GObject * object);
-static gboolean gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps);
-static GstFlowReturn gst_dvdec_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_dvdec_sink_event (GstPad * pad, GstEvent * event);
+static GstFlowReturn gst_dvdec_chain (GstPad * pad, GstObject * parent,
+ GstBuffer * buffer);
+static gboolean gst_dvdec_sink_event (GstPad * pad, GstObject * parent,
+ GstEvent * event);
static GstStateChangeReturn gst_dvdec_change_state (GstElement * element,
GstStateChange transition);
GValue * value, GParamSpec * pspec);
static void
-gst_dvdec_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_temp));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_temp));
-
- gst_element_class_set_details_simple (element_class, "DV video decoder",
- "Codec/Decoder/Video",
- "Uses libdv to decode DV video (smpte314) (libdv.sourceforge.net)",
- "Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
-
- GST_DEBUG_CATEGORY_INIT (dvdec_debug, "dvdec", 0, "DV decoding element");
-}
-
-static void
gst_dvdec_class_init (GstDVDecClass * klass)
{
GObjectClass *gobject_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
- gobject_class->finalize = gst_dvdec_finalize;
gobject_class->set_property = gst_dvdec_set_property;
gobject_class->get_property = gst_dvdec_get_property;
1, G_MAXINT, DV_DEFAULT_DECODE_NTH,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- gstelement_class->change_state = gst_dvdec_change_state;
+ gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dvdec_change_state);
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&sink_temp));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&src_temp));
+
+ gst_element_class_set_details_simple (gstelement_class, "DV video decoder",
+ "Codec/Decoder/Video",
+ "Uses libdv to decode DV video (smpte314) (libdv.sourceforge.net)",
+ "Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
+
+ GST_DEBUG_CATEGORY_INIT (dvdec_debug, "dvdec", 0, "DV decoding element");
}
static void
-gst_dvdec_init (GstDVDec * dvdec, GstDVDecClass * g_class)
+gst_dvdec_init (GstDVDec * dvdec)
{
dvdec->sinkpad = gst_pad_new_from_static_template (&sink_temp, "sink");
- gst_pad_set_setcaps_function (dvdec->sinkpad,
- GST_DEBUG_FUNCPTR (gst_dvdec_sink_setcaps));
gst_pad_set_chain_function (dvdec->sinkpad, gst_dvdec_chain);
gst_pad_set_event_function (dvdec->sinkpad, gst_dvdec_sink_event);
gst_element_add_pad (GST_ELEMENT (dvdec), dvdec->sinkpad);
dvdec->clamp_luma = FALSE;
dvdec->clamp_chroma = FALSE;
dvdec->quality = DV_DEFAULT_QUALITY;
- dvdec->segment = gst_segment_new ();
-}
-
-static void
-gst_dvdec_finalize (GObject * object)
-{
- GstDVDec *dvdec = GST_DVDEC (object);
-
- gst_segment_free (dvdec->segment);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gboolean
-gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
+gst_dvdec_sink_setcaps (GstDVDec * dvdec, GstCaps * caps)
{
- GstDVDec *dvdec;
GstStructure *s;
const GValue *par = NULL, *rate = NULL;
- dvdec = GST_DVDEC (gst_pad_get_parent (pad));
-
/* first parse the caps */
s = gst_caps_get_structure (caps, 0);
dvdec->sink_negotiated = TRUE;
dvdec->src_negotiated = FALSE;
- gst_object_unref (dvdec);
-
return TRUE;
/* ERRORS */
no_framerate:
{
GST_DEBUG_OBJECT (dvdec, "no framerate specified in caps");
- gst_object_unref (dvdec);
return FALSE;
}
}
+static void
+gst_dvdec_negotiate_pool (GstDVDec * dec, GstCaps * caps, GstVideoInfo * info)
+{
+ GstQuery *query;
+ GstBufferPool *pool = NULL;
+ guint size, min, max, prefix, alignment;
+ GstStructure *config;
+
+ /* find a pool for the negotiated caps now */
+ query = gst_query_new_allocation (caps, TRUE);
+
+ if (gst_pad_peer_query (dec->srcpad, query)) {
+ GST_DEBUG_OBJECT (dec, "got downstream ALLOCATION hints");
+ /* we got configuration from our peer, parse them */
+ gst_query_parse_allocation_params (query, &size, &min, &max, &prefix,
+ &alignment, &pool);
+ size = MAX (size, info->size);
+ } else {
+ GST_DEBUG_OBJECT (dec, "didn't get downstream ALLOCATION hints");
+ size = info->size;
+ min = max = 0;
+ prefix = 0;
+ alignment = 0;
+ }
+
+ if (pool == NULL) {
+ /* we did not get a pool, make one ourselves then */
+ pool = gst_buffer_pool_new ();
+ }
+
+ if (dec->pool)
+ gst_object_unref (dec->pool);
+ dec->pool = pool;
+
+ config = gst_buffer_pool_get_config (pool);
+ gst_buffer_pool_config_set (config, caps, size, min, max, prefix, alignment);
+ /* just set the option, if the pool can support it we will transparently use
+ * it through the video info API. We could also see if the pool support this
+ * option and only activate it then. */
+ gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
+
+ gst_buffer_pool_set_config (pool, config);
+ /* and activate */
+ gst_buffer_pool_set_active (pool, TRUE);
+
+ gst_query_unref (query);
+}
+
static gboolean
gst_dvdec_src_negotiate (GstDVDec * dvdec)
{
/* ignoring rgb, bgr0 for now */
dvdec->bpp = 2;
- othercaps = gst_caps_new_simple ("video/x-raw-yuv",
- "format", GST_TYPE_FOURCC, GST_STR_FOURCC ("YUY2"),
- "width", G_TYPE_INT, 720,
- "height", G_TYPE_INT, dvdec->height,
- "framerate", GST_TYPE_FRACTION, dvdec->framerate_numerator,
- dvdec->framerate_denominator,
- "pixel-aspect-ratio", GST_TYPE_FRACTION, dvdec->par_x,
- dvdec->par_y, "interlaced", G_TYPE_BOOLEAN, dvdec->interlaced, NULL);
+ gst_video_info_set_format (&dvdec->vinfo, GST_VIDEO_FORMAT_YUY2,
+ 720, dvdec->height);
+ dvdec->vinfo.fps_n = dvdec->framerate_numerator;
+ dvdec->vinfo.fps_d = dvdec->framerate_denominator;
+ dvdec->vinfo.par_n = dvdec->par_x;
+ dvdec->vinfo.par_d = dvdec->par_y;
+ if (dvdec->interlaced) {
+ dvdec->vinfo.interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
+ dvdec->vinfo.flags |= GST_VIDEO_FLAG_INTERLACED;
+ } else {
+ dvdec->vinfo.interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
+ dvdec->vinfo.flags &= GST_VIDEO_FLAG_INTERLACED;
+ }
+ othercaps = gst_video_info_to_caps (&dvdec->vinfo);
gst_pad_set_caps (dvdec->srcpad, othercaps);
+
+ gst_dvdec_negotiate_pool (dvdec, othercaps, &dvdec->vinfo);
gst_caps_unref (othercaps);
dvdec->src_negotiated = TRUE;
}
static gboolean
-gst_dvdec_sink_event (GstPad * pad, GstEvent * event)
+gst_dvdec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
GstDVDec *dvdec;
gboolean res = TRUE;
- dvdec = GST_DVDEC (gst_pad_get_parent (pad));
+ dvdec = GST_DVDEC (parent);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_STOP:
- gst_segment_init (dvdec->segment, GST_FORMAT_UNDEFINED);
+ gst_segment_init (&dvdec->segment, GST_FORMAT_UNDEFINED);
break;
- case GST_EVENT_NEWSEGMENT:{
- gboolean update;
- gdouble rate, applied_rate;
- GstFormat format;
- gint64 start, stop, position;
-
- gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
- &format, &start, &stop, &position);
-
- GST_DEBUG_OBJECT (dvdec, "Got NEWSEGMENT [%" GST_TIME_FORMAT
- " - %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "]",
- GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
- GST_TIME_ARGS (position));
-
- gst_segment_set_newsegment_full (dvdec->segment, update, rate,
- applied_rate, format, start, stop, position);
+ case GST_EVENT_SEGMENT:{
+ const GstSegment *segment;
+
+ gst_event_parse_segment (event, &segment);
+
+ GST_DEBUG_OBJECT (dvdec, "Got NEWSEGMENT %" GST_SEGMENT_FORMAT, &segment);
+
+ gst_segment_copy_into (segment, &dvdec->segment);
+ break;
+ }
+ case GST_EVENT_CAPS:
+ {
+ GstCaps *caps;
+
+ gst_event_parse_caps (event, &caps);
+ gst_dvdec_sink_setcaps (dvdec, caps);
+ gst_event_unref (event);
+ event = NULL;
+ res = TRUE;
break;
}
+
default:
break;
}
- res = gst_pad_push_event (dvdec->srcpad, event);
+ if (event)
+ res = gst_pad_push_event (dvdec->srcpad, event);
return res;
}
static GstFlowReturn
-gst_dvdec_chain (GstPad * pad, GstBuffer * buf)
+gst_dvdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
GstDVDec *dvdec;
guint8 *inframe;
- guint8 *outframe;
guint8 *outframe_ptrs[3];
gint outframe_pitches[3];
+ GstMapInfo map;
+ GstVideoFrame frame;
GstBuffer *outbuf;
GstFlowReturn ret = GST_FLOW_OK;
guint length;
- gint64 cstart, cstop;
+ guint64 cstart, cstop;
gboolean PAL, wide;
- dvdec = GST_DVDEC (gst_pad_get_parent (pad));
- inframe = GST_BUFFER_DATA (buf);
+ dvdec = GST_DVDEC (parent);
+
+ gst_buffer_map (buf, &map, GST_MAP_READ);
+ inframe = map.data;
/* buffer should be at least the size of one NTSC frame, this should
* be enough to decode the header. */
- if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < NTSC_BUFFER))
+ if (G_UNLIKELY (map.size < NTSC_BUFFER))
goto wrong_size;
/* preliminary dropping. unref and return if outside of configured segment */
- if ((dvdec->segment->format == GST_FORMAT_TIME) &&
- (!(gst_segment_clip (dvdec->segment, GST_FORMAT_TIME,
+ if ((dvdec->segment.format == GST_FORMAT_TIME) &&
+ (!(gst_segment_clip (&dvdec->segment, GST_FORMAT_TIME,
GST_BUFFER_TIMESTAMP (buf),
GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf),
&cstart, &cstop))))
/* check the buffer is of right size after we know if we are
* dealing with PAL or NTSC */
length = (PAL ? PAL_BUFFER : NTSC_BUFFER);
- if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < length))
+ if (G_UNLIKELY (map.size < length))
goto wrong_size;
dv_parse_packs (dvdec->decoder, inframe);
goto not_negotiated;
}
- ret =
- gst_pad_alloc_buffer_and_set_caps (dvdec->srcpad, 0,
- (720 * dvdec->height) * dvdec->bpp,
- GST_PAD_CAPS (dvdec->srcpad), &outbuf);
+ if (gst_pad_check_reconfigure (dvdec->srcpad)) {
+ GstCaps *caps;
+
+ caps = gst_pad_get_current_caps (dvdec->srcpad);
+ gst_dvdec_negotiate_pool (dvdec, caps, &dvdec->vinfo);
+ gst_caps_unref (caps);
+ }
+
+ ret = gst_buffer_pool_acquire_buffer (dvdec->pool, &outbuf, NULL);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto no_buffer;
- outframe = GST_BUFFER_DATA (outbuf);
+ gst_video_frame_map (&frame, &dvdec->vinfo, outbuf, GST_MAP_WRITE);
- outframe_ptrs[0] = outframe;
- outframe_pitches[0] = 720 * dvdec->bpp;
+ outframe_ptrs[0] = GST_VIDEO_FRAME_COMP_DATA (&frame, 0);
+ outframe_pitches[0] = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 0);
/* the rest only matters for YUY2 */
if (dvdec->bpp < 3) {
- outframe_ptrs[1] = outframe_ptrs[0] + 720 * dvdec->height;
- outframe_ptrs[2] = outframe_ptrs[1] + 360 * dvdec->height;
+ outframe_ptrs[1] = GST_VIDEO_FRAME_COMP_DATA (&frame, 1);
+ outframe_ptrs[2] = GST_VIDEO_FRAME_COMP_DATA (&frame, 2);
- outframe_pitches[1] = dvdec->height / 2;
- outframe_pitches[2] = outframe_pitches[1];
+ outframe_pitches[1] = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 1);
+ outframe_pitches[2] = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 2);
}
GST_DEBUG_OBJECT (dvdec, "decoding and pushing buffer");
dv_decode_full_frame (dvdec->decoder, inframe,
e_dv_color_yuv, outframe_ptrs, outframe_pitches);
- GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_TFF);
+ gst_video_frame_unmap (&frame);
+
+ GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);
GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_END (buf);
dvdec->video_offset++;
done:
+ gst_buffer_unmap (buf, &map);
gst_buffer_unref (buf);
- gst_object_unref (dvdec);
return ret;
dv_decoder_new (0, dvdec->clamp_luma, dvdec->clamp_chroma);
dvdec->decoder->quality = qualities[dvdec->quality];
dv_set_error_log (dvdec->decoder, NULL);
- gst_segment_init (dvdec->segment, GST_FORMAT_UNDEFINED);
+ gst_video_info_init (&dvdec->vinfo);
+ gst_segment_init (&dvdec->segment, GST_FORMAT_UNDEFINED);
dvdec->src_negotiated = FALSE;
dvdec->sink_negotiated = FALSE;
/*
break;
}
- ret = parent_class->change_state (element, transition);
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
case GST_STATE_CHANGE_PAUSED_TO_READY:
dv_decoder_free (dvdec->decoder);
dvdec->decoder = NULL;
+ if (dvdec->pool) {
+ gst_buffer_pool_set_active (dvdec->pool, FALSE);
+ gst_object_unref (dvdec->pool);
+ dvdec->pool = NULL;
+ }
break;
case GST_STATE_CHANGE_READY_TO_NULL:
break;
static GstStaticPadTemplate audio_src_temp = GST_STATIC_PAD_TEMPLATE ("audio",
GST_PAD_SRC,
GST_PAD_SOMETIMES,
- GST_STATIC_CAPS ("audio/x-raw-int, "
- "depth = (int) 16, "
- "width = (int) 16, "
- "signed = (boolean) TRUE, "
- "channels = (int) {2, 4}, "
- "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
- "rate = (int) { 32000, 44100, 48000 }")
+ GST_STATIC_CAPS ("audio/x-raw, "
+ "format = (string) " GST_AUDIO_NE (S16) ", "
+ "layout = (string) interleaved, "
+ "rate = (int) { 32000, 44100, 48000 }, " "channels = (int) {2, 4}")
);
-GST_BOILERPLATE (GstDVDemux, gst_dvdemux, GstElement, GST_TYPE_ELEMENT);
+#define gst_dvdemux_parent_class parent_class
+G_DEFINE_TYPE (GstDVDemux, gst_dvdemux, GST_TYPE_ELEMENT);
static void gst_dvdemux_finalize (GObject * object);
/* query functions */
-static const GstQueryType *gst_dvdemux_get_src_query_types (GstPad * pad);
-static gboolean gst_dvdemux_src_query (GstPad * pad, GstQuery * query);
-static const GstQueryType *gst_dvdemux_get_sink_query_types (GstPad * pad);
-static gboolean gst_dvdemux_sink_query (GstPad * pad, GstQuery * query);
+static gboolean gst_dvdemux_src_query (GstPad * pad, GstObject * parent,
+ GstQuery * query);
+static gboolean gst_dvdemux_sink_query (GstPad * pad, GstObject * parent,
+ GstQuery * query);
/* convert functions */
static gboolean gst_dvdemux_sink_convert (GstDVDemux * demux,
/* event functions */
static gboolean gst_dvdemux_send_event (GstElement * element, GstEvent * event);
-static gboolean gst_dvdemux_handle_src_event (GstPad * pad, GstEvent * event);
-static gboolean gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_dvdemux_handle_src_event (GstPad * pad, GstObject * parent,
+ GstEvent * event);
+static gboolean gst_dvdemux_handle_sink_event (GstPad * pad, GstObject * parent,
+ GstEvent * event);
/* scheduling functions */
static void gst_dvdemux_loop (GstPad * pad);
static GstFlowReturn gst_dvdemux_flush (GstDVDemux * dvdemux);
-static GstFlowReturn gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer);
+static GstFlowReturn gst_dvdemux_chain (GstPad * pad, GstObject * parent,
+ GstBuffer * buffer);
/* state change functions */
-static gboolean gst_dvdemux_sink_activate (GstPad * sinkpad);
-static gboolean gst_dvdemux_sink_activate_push (GstPad * sinkpad,
- gboolean active);
-static gboolean gst_dvdemux_sink_activate_pull (GstPad * sinkpad,
- gboolean active);
+static gboolean gst_dvdemux_sink_activate (GstPad * sinkpad,
+ GstObject * parent);
+static gboolean gst_dvdemux_sink_activate_mode (GstPad * sinkpad,
+ GstObject * parent, GstPadMode mode, gboolean active);
static GstStateChangeReturn gst_dvdemux_change_state (GstElement * element,
GstStateChange transition);
static void
-gst_dvdemux_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_temp));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&video_src_temp));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&audio_src_temp));
-
- gst_element_class_set_details_simple (element_class,
- "DV system stream demuxer", "Codec/Demuxer",
- "Uses libdv to separate DV audio from DV video (libdv.sourceforge.net)",
- "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
-
- GST_DEBUG_CATEGORY_INIT (dvdemux_debug, "dvdemux", 0, "DV demuxer element");
-}
-
-static void
gst_dvdemux_class_init (GstDVDemuxClass * klass)
{
GObjectClass *gobject_class;
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dvdemux_change_state);
gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_dvdemux_send_event);
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&sink_temp));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&video_src_temp));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&audio_src_temp));
+
+ gst_element_class_set_details_simple (gstelement_class,
+ "DV system stream demuxer", "Codec/Demuxer",
+ "Uses libdv to separate DV audio from DV video (libdv.sourceforge.net)",
+ "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
+
+ GST_DEBUG_CATEGORY_INIT (dvdemux_debug, "dvdemux", 0, "DV demuxer element");
}
static void
-gst_dvdemux_init (GstDVDemux * dvdemux, GstDVDemuxClass * g_class)
+gst_dvdemux_init (GstDVDemux * dvdemux)
{
gint i;
gst_pad_set_activate_function (dvdemux->sinkpad,
GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate));
/* the function to activate in push mode */
- gst_pad_set_activatepush_function (dvdemux->sinkpad,
- GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate_push));
- /* the function to activate in pull mode */
- gst_pad_set_activatepull_function (dvdemux->sinkpad,
- GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate_pull));
+ gst_pad_set_activatemode_function (dvdemux->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate_mode));
/* for push mode, this is the chain function */
gst_pad_set_chain_function (dvdemux->sinkpad,
GST_DEBUG_FUNCPTR (gst_dvdemux_chain));
/* query functions */
gst_pad_set_query_function (dvdemux->sinkpad,
GST_DEBUG_FUNCPTR (gst_dvdemux_sink_query));
- gst_pad_set_query_type_function (dvdemux->sinkpad,
- GST_DEBUG_FUNCPTR (gst_dvdemux_get_sink_query_types));
/* now add the pad */
gst_element_add_pad (GST_ELEMENT (dvdemux), dvdemux->sinkpad);
gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_dvdemux_src_query));
- gst_pad_set_query_type_function (pad,
- GST_DEBUG_FUNCPTR (gst_dvdemux_get_src_query_types));
gst_pad_set_event_function (pad,
GST_DEBUG_FUNCPTR (gst_dvdemux_handle_src_event));
gst_pad_use_fixed_caps (pad);
if (no_more_pads)
gst_element_no_more_pads (GST_ELEMENT (dvdemux));
- gst_pad_push_event (pad, gst_event_new_new_segment (FALSE,
- dvdemux->byte_segment.rate, GST_FORMAT_TIME,
- dvdemux->time_segment.start, dvdemux->time_segment.stop,
- dvdemux->time_segment.start));
+ gst_pad_push_event (pad, gst_event_new_segment (&dvdemux->time_segment));
if (no_more_pads) {
- gst_element_found_tags (GST_ELEMENT (dvdemux),
- gst_tag_list_new_full (GST_TAG_CONTAINER_FORMAT, "DV", NULL));
+ gst_pad_push_event (pad,
+ gst_event_new_tag (gst_tag_list_new (GST_TAG_CONTAINER_FORMAT, "DV",
+ NULL)));
}
return pad;
}
}
-static const GstQueryType *
-gst_dvdemux_get_src_query_types (GstPad * pad)
-{
- static const GstQueryType src_query_types[] = {
- GST_QUERY_POSITION,
- GST_QUERY_DURATION,
- GST_QUERY_CONVERT,
- 0
- };
-
- return src_query_types;
-}
-
static gboolean
-gst_dvdemux_src_query (GstPad * pad, GstQuery * query)
+gst_dvdemux_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
gboolean res = TRUE;
GstDVDemux *dvdemux;
- dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
+ dvdemux = GST_DVDEMUX (parent);
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_POSITION:
/* bring the position to the requested format. */
if (!(res = gst_dvdemux_src_convert (dvdemux, pad,
- GST_FORMAT_TIME, dvdemux->time_segment.last_stop,
+ GST_FORMAT_TIME, dvdemux->time_segment.position,
&format, &cur)))
goto error;
gst_query_set_position (query, format, cur);
break;
}
default:
- res = gst_pad_query_default (pad, query);
+ res = gst_pad_query_default (pad, parent, query);
break;
}
- gst_object_unref (dvdemux);
return res;
/* ERRORS */
error:
{
- gst_object_unref (dvdemux);
GST_DEBUG ("error source query");
return FALSE;
}
}
-static const GstQueryType *
-gst_dvdemux_get_sink_query_types (GstPad * pad)
-{
- static const GstQueryType sink_query_types[] = {
- GST_QUERY_CONVERT,
- 0
- };
-
- return sink_query_types;
-}
-
static gboolean
-gst_dvdemux_sink_query (GstPad * pad, GstQuery * query)
+gst_dvdemux_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
gboolean res = TRUE;
GstDVDemux *dvdemux;
- dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
+ dvdemux = GST_DVDEMUX (parent);
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CONVERT:
break;
}
default:
- res = gst_pad_query_default (pad, query);
+ res = gst_pad_query_default (pad, parent, query);
break;
}
- gst_object_unref (dvdemux);
return res;
/* ERRORS */
error:
{
- gst_object_unref (dvdemux);
GST_DEBUG ("error handling sink query");
return FALSE;
}
}
static gboolean
-gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * event)
+gst_dvdemux_handle_sink_event (GstPad * pad, GstObject * parent,
+ GstEvent * event)
{
- GstDVDemux *dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
+ GstDVDemux *dvdemux = GST_DVDEMUX (parent);
gboolean res = TRUE;
switch (GST_EVENT_TYPE (event)) {
gst_segment_init (&dvdemux->time_segment, GST_FORMAT_TIME);
res = gst_dvdemux_push_event (dvdemux, event);
break;
- case GST_EVENT_NEWSEGMENT:
+ case GST_EVENT_SEGMENT:
{
- gboolean update;
- gdouble rate;
- GstFormat format;
- gint64 start, stop, time;
-
- /* parse byte start and stop positions */
- gst_event_parse_new_segment (event, &update, &rate, &format,
- &start, &stop, &time);
+ const GstSegment *segment;
- switch (format) {
+ gst_event_parse_segment (event, &segment);
+ switch (segment->format) {
case GST_FORMAT_BYTES:
- gst_segment_set_newsegment (&dvdemux->byte_segment, update,
- rate, format, start, stop, time);
+ gst_segment_copy_into (segment, &dvdemux->byte_segment);
+#if 0
+ /* FIXME ?? no longer such subtle distinction in 0.11 */
/* the update can always be sent */
if (update) {
GstEvent *update;
update = gst_event_new_new_segment (TRUE,
dvdemux->time_segment.rate, dvdemux->time_segment.format,
- dvdemux->time_segment.start, dvdemux->time_segment.last_stop,
+ dvdemux->time_segment.start, dvdemux->time_segment.position,
dvdemux->time_segment.time);
gst_dvdemux_push_event (dvdemux, update);
* frames, etc.. */
dvdemux->need_segment = TRUE;
}
+#endif
+ dvdemux->need_segment = TRUE;
gst_event_unref (event);
break;
case GST_FORMAT_TIME:
- gst_segment_set_newsegment (&dvdemux->time_segment, update,
- rate, format, start, stop, time);
+ gst_segment_copy_into (segment, &dvdemux->time_segment);
/* and we can just forward this time event */
res = gst_dvdemux_push_event (dvdemux, event);
/* and clear the adapter */
gst_adapter_clear (dvdemux->adapter);
break;
+ case GST_EVENT_CAPS:
+ gst_event_unref (event);
+ break;
default:
res = gst_dvdemux_push_event (dvdemux, event);
break;
}
- gst_object_unref (dvdemux);
-
return res;
}
* timestamp can be found. */
format = GST_FORMAT_BYTES;
res = gst_dvdemux_sink_convert (demux,
- segment->format, segment->last_stop,
- &format, &demux->byte_segment.last_stop);
+ segment->format, segment->position,
+ &format, (gint64 *) & demux->byte_segment.position);
if (!res)
goto done;
/* update byte segment start */
gst_dvdemux_sink_convert (demux,
- segment->format, segment->start, &format, &demux->byte_segment.start);
+ segment->format, segment->start, &format,
+ (gint64 *) & demux->byte_segment.start);
/* update byte segment stop */
gst_dvdemux_sink_convert (demux,
- segment->format, segment->stop, &format, &demux->byte_segment.stop);
+ segment->format, segment->stop, &format,
+ (gint64 *) & demux->byte_segment.stop);
/* update byte segment time */
gst_dvdemux_sink_convert (demux,
- segment->format, segment->time, &format, &demux->byte_segment.time);
+ segment->format, segment->time, &format,
+ (gint64 *) & demux->byte_segment.time);
/* calculate current frame number */
format = GST_FORMAT_DEFAULT;
/* now configure the seek segment */
if (event) {
- gst_segment_set_seek (&seeksegment, rate, format, flags,
+ gst_segment_do_seek (&seeksegment, rate, format, flags,
cur_type, cur, stop_type, stop, &update);
}
GST_DEBUG_OBJECT (demux, "segment configured from %" G_GINT64_FORMAT
" to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,
- seeksegment.start, seeksegment.stop, seeksegment.last_stop);
+ seeksegment.start, seeksegment.stop, seeksegment.position);
- /* do the seek, segment.last_stop contains new position. */
+ /* do the seek, segment.position contains new position. */
res = gst_dvdemux_do_seek (demux, &seeksegment);
/* and prepare to continue streaming */
if (flush) {
/* send flush stop, peer will accept data and events again. We
* are not yet providing data as we still have the STREAM_LOCK. */
- gst_dvdemux_push_event (demux, gst_event_new_flush_stop ());
- } else if (res && demux->running) {
- /* we are running the current segment and doing a non-flushing seek,
- * close the segment first based on the last_stop. */
- GST_DEBUG_OBJECT (demux, "closing running segment %" G_GINT64_FORMAT
- " to %" G_GINT64_FORMAT, demux->time_segment.start,
- demux->time_segment.last_stop);
-
- gst_dvdemux_push_event (demux,
- gst_event_new_new_segment (TRUE,
- demux->time_segment.rate, demux->time_segment.format,
- demux->time_segment.start, demux->time_segment.last_stop,
- demux->time_segment.time));
+ gst_dvdemux_push_event (demux, gst_event_new_flush_stop (TRUE));
}
/* if successfull seek, we update our real segment and push
if (demux->time_segment.flags & GST_SEEK_FLAG_SEGMENT) {
gst_element_post_message (GST_ELEMENT_CAST (demux),
gst_message_new_segment_start (GST_OBJECT_CAST (demux),
- demux->time_segment.format, demux->time_segment.last_stop));
+ demux->time_segment.format, demux->time_segment.position));
}
if ((stop = demux->time_segment.stop) == -1)
stop = demux->time_segment.duration;
if (demux->pending_segment)
gst_event_unref (demux->pending_segment);
- demux->pending_segment = gst_event_new_new_segment (FALSE,
- demux->time_segment.rate, demux->time_segment.format,
- demux->time_segment.last_stop, stop, demux->time_segment.time);
+ demux->pending_segment = gst_event_new_segment (&demux->time_segment);
demux->need_segment = FALSE;
}
- demux->running = TRUE;
/* and restart the task in case it got paused explicitely or by
* the FLUSH_START event we pushed out. */
gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_dvdemux_loop,
/* handle an event on the source pad, it's most likely a seek */
static gboolean
-gst_dvdemux_handle_src_event (GstPad * pad, GstEvent * event)
+gst_dvdemux_handle_src_event (GstPad * pad, GstObject * parent,
+ GstEvent * event)
{
gboolean res = TRUE;
GstDVDemux *dvdemux;
- dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
+ dvdemux = GST_DVDEMUX (parent);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK:
res = FALSE;
break;
case GST_EVENT_NAVIGATION:
- /* no navigation either... */
+ case GST_EVENT_CAPS:
+ /* no navigation or caps either... */
res = FALSE;
break;
default:
if (event)
gst_event_unref (event);
- gst_object_unref (dvdemux);
-
return res;
}
{
gint num_samples;
GstFlowReturn ret;
- const guint8 *data;
+ GstMapInfo map;
- data = GST_BUFFER_DATA (buffer);
-
- dv_decode_full_audio (dvdemux->decoder, data, dvdemux->audio_buffers);
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+ dv_decode_full_audio (dvdemux->decoder, map.data, dvdemux->audio_buffers);
+ gst_buffer_unmap (buffer, &map);
if (G_LIKELY ((num_samples = dv_get_num_samples (dvdemux->decoder)) > 0)) {
gint16 *a_ptr;
if (G_UNLIKELY ((frequency != dvdemux->frequency)
|| (channels != dvdemux->channels))) {
GstCaps *caps;
+ GstAudioInfo info;
dvdemux->frequency = frequency;
dvdemux->channels = channels;
- /* and set new caps */
- caps = gst_caps_new_simple ("audio/x-raw-int",
- "rate", G_TYPE_INT, frequency,
- "depth", G_TYPE_INT, 16,
- "width", G_TYPE_INT, 16,
- "signed", G_TYPE_BOOLEAN, TRUE,
- "channels", G_TYPE_INT, channels,
- "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
+ gst_audio_info_init (&info);
+ gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16LE,
+ frequency, channels, NULL);
+ caps = gst_audio_info_to_caps (&info);
gst_pad_set_caps (dvdemux->audiosrcpad, caps);
gst_caps_unref (caps);
}
outbuf = gst_buffer_new_and_alloc (num_samples *
sizeof (gint16) * dvdemux->channels);
- a_ptr = (gint16 *) GST_BUFFER_DATA (outbuf);
+ gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
+ a_ptr = (gint16 *) map.data;
for (i = 0; i < num_samples; i++) {
for (j = 0; j < dvdemux->channels; j++) {
*(a_ptr++) = dvdemux->audio_buffers[j][i];
}
}
+ gst_buffer_unmap (outbuf, &map);
GST_DEBUG ("pushing audio %" GST_TIME_FORMAT,
- GST_TIME_ARGS (dvdemux->time_segment.last_stop));
+ GST_TIME_ARGS (dvdemux->time_segment.position));
- GST_BUFFER_TIMESTAMP (outbuf) = dvdemux->time_segment.last_stop;
+ GST_BUFFER_TIMESTAMP (outbuf) = dvdemux->time_segment.position;
GST_BUFFER_DURATION (outbuf) = duration;
GST_BUFFER_OFFSET (outbuf) = dvdemux->audio_offset;
dvdemux->audio_offset += num_samples;
if (dvdemux->new_media)
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (dvdemux->audiosrcpad));
ret = gst_pad_push (dvdemux->audiosrcpad, outbuf);
} else {
/* takes ownership of buffer here, we just need to modify
* the metadata. */
- outbuf = gst_buffer_make_metadata_writable (buffer);
+ outbuf = gst_buffer_make_writable (buffer);
- GST_BUFFER_TIMESTAMP (outbuf) = dvdemux->time_segment.last_stop;
+ GST_BUFFER_TIMESTAMP (outbuf) = dvdemux->time_segment.position;
GST_BUFFER_OFFSET (outbuf) = dvdemux->video_offset;
GST_BUFFER_OFFSET_END (outbuf) = dvdemux->video_offset + 1;
GST_BUFFER_DURATION (outbuf) = duration;
if (dvdemux->new_media)
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (dvdemux->videosrcpad));
GST_DEBUG ("pushing video %" GST_TIME_FORMAT,
- GST_TIME_ARGS (dvdemux->time_segment.last_stop));
+ GST_TIME_ARGS (dvdemux->time_segment.position));
ret = gst_pad_push (dvdemux->videosrcpad, outbuf);
gst_dvdemux_get_timecode (GstDVDemux * dvdemux, GstBuffer * buffer,
GstSMPTETimeCode * timecode)
{
- guint8 *data = GST_BUFFER_DATA (buffer);
+ guint8 *data;
+ GstMapInfo map;
int offset;
int dif;
int n_difs = dvdemux->decoder->num_dif_seqs;
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+ data = map.data;
for (dif = 0; dif < n_difs; dif++) {
offset = get_ssyb_offset (dif, 3);
if (data[offset + 3] == 0x13) {
(data[offset + 7] & 0xf);
GST_DEBUG ("got timecode %" GST_SMPTE_TIME_CODE_FORMAT,
GST_SMPTE_TIME_CODE_ARGS (timecode));
+ gst_buffer_unmap (buffer, &map);
return TRUE;
}
}
+ gst_buffer_unmap (buffer, &map);
return FALSE;
}
static gboolean
gst_dvdemux_is_new_media (GstDVDemux * dvdemux, GstBuffer * buffer)
{
- guint8 *data = GST_BUFFER_DATA (buffer);
+ guint8 *data;
+ GstMapInfo map;
int aaux_offset;
int dif;
int n_difs;
n_difs = dvdemux->decoder->num_dif_seqs;
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+ data = map.data;
for (dif = 0; dif < n_difs; dif++) {
if (dif & 1) {
aaux_offset = (dif * 12000) + (6 + 16 * 1) * 80 + 3;
aaux_offset = (dif * 12000) + (6 + 16 * 4) * 80 + 3;
}
if (data[aaux_offset + 0] == 0x51) {
- if ((data[aaux_offset + 2] & 0x80) == 0)
+ if ((data[aaux_offset + 2] & 0x80) == 0) {
+ gst_buffer_unmap (buffer, &map);
return TRUE;
+ }
}
}
+ gst_buffer_unmap (buffer, &map);
return FALSE;
}
{
GstClockTime next_ts;
GstFlowReturn aret, vret, ret;
- guint8 *data;
+ GstMapInfo map;
guint64 duration;
GstSMPTETimeCode timecode;
int frame_number;
if (G_UNLIKELY (dvdemux->need_segment)) {
- GstEvent *event;
GstFormat format;
/* convert to time and store as start/end_timestamp */
if (!(gst_dvdemux_convert_sink_pair (dvdemux,
GST_FORMAT_BYTES, dvdemux->byte_segment.start,
dvdemux->byte_segment.stop, format,
- &dvdemux->time_segment.start, &dvdemux->time_segment.stop)))
+ (gint64 *) & dvdemux->time_segment.start,
+ (gint64 *) & dvdemux->time_segment.stop)))
goto segment_error;
dvdemux->time_segment.rate = dvdemux->byte_segment.rate;
- dvdemux->time_segment.abs_rate = dvdemux->byte_segment.abs_rate;
- dvdemux->time_segment.last_stop = dvdemux->time_segment.start;
+ dvdemux->time_segment.position = dvdemux->time_segment.start;
/* calculate current frame number */
format = GST_FORMAT_DEFAULT;
GST_TIME_ARGS (dvdemux->time_segment.stop),
GST_TIME_ARGS (dvdemux->time_segment.start));
- event = gst_event_new_new_segment (FALSE, dvdemux->byte_segment.rate,
- GST_FORMAT_TIME, dvdemux->time_segment.start,
- dvdemux->time_segment.stop, dvdemux->time_segment.start);
- gst_dvdemux_push_event (dvdemux, event);
+ gst_dvdemux_push_event (dvdemux,
+ gst_event_new_segment (&dvdemux->time_segment));
dvdemux->need_segment = FALSE;
}
next_ts = gst_util_uint64_scale_int (
(dvdemux->frame_offset + 1) * GST_SECOND,
dvdemux->framerate_denominator, dvdemux->framerate_numerator);
- duration = next_ts - dvdemux->time_segment.last_stop;
-
- data = GST_BUFFER_DATA (buffer);
+ duration = next_ts - dvdemux->time_segment.position;
- dv_parse_packs (dvdemux->decoder, data);
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+ dv_parse_packs (dvdemux->decoder, map.data);
+ gst_buffer_unmap (buffer, &map);
dvdemux->new_media = FALSE;
if (gst_dvdemux_is_new_media (dvdemux, buffer) &&
dvdemux->frames_since_new_media > 2) {
goto done;
}
- gst_segment_set_last_stop (&dvdemux->time_segment, GST_FORMAT_TIME, next_ts);
+ dvdemux->time_segment.position = next_ts;
dvdemux->frame_offset++;
/* check for the end of the segment */
gint length;
/* get the accumulated bytes */
- data = gst_adapter_peek (dvdemux->adapter, dvdemux->frame_len);
+ data = gst_adapter_map (dvdemux->adapter, dvdemux->frame_len);
/* parse header to know the length and other params */
- if (G_UNLIKELY (dv_parse_header (dvdemux->decoder, data) < 0))
+ if (G_UNLIKELY (dv_parse_header (dvdemux->decoder, data) < 0)) {
+ gst_adapter_unmap (dvdemux->adapter);
goto parse_header_error;
+ }
+ gst_adapter_unmap (dvdemux->adapter);
/* after parsing the header we know the length of the data */
length = dvdemux->frame_len = dvdemux->decoder->frame_size;
if (G_LIKELY (gst_adapter_available (dvdemux->adapter) >= length)) {
GstBuffer *buffer;
- data = gst_adapter_take (dvdemux->adapter, length);
-
- /* create buffer for the remainder of the code */
- buffer = gst_buffer_new ();
- GST_BUFFER_DATA (buffer) = (guint8 *) data;
- GST_BUFFER_SIZE (buffer) = length;
- GST_BUFFER_MALLOCDATA (buffer) = (guint8 *) data;
+ buffer = gst_adapter_take_buffer (dvdemux->adapter, length);
/* and decode the buffer, takes ownership */
ret = gst_dvdemux_demux_frame (dvdemux, buffer);
* accumulate data until we have a frame, then decode.
*/
static GstFlowReturn
-gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer)
+gst_dvdemux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
GstDVDemux *dvdemux;
GstFlowReturn ret;
GstClockTime timestamp;
- dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
+ dvdemux = GST_DVDEMUX (parent);
/* a discontinuity in the stream, we need to get rid of
* accumulated data in the adapter and assume a new frame
/* a timestamp always should be respected */
timestamp = GST_BUFFER_TIMESTAMP (buffer);
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
- gst_segment_set_last_stop (&dvdemux->time_segment, GST_FORMAT_TIME,
- timestamp);
+ dvdemux->time_segment.position = timestamp;
/* FIXME, adjust frame_offset and other counters */
}
/* and try to flush pending frames */
ret = gst_dvdemux_flush (dvdemux);
- gst_object_unref (dvdemux);
-
return ret;
}
GstFlowReturn ret;
GstDVDemux *dvdemux;
GstBuffer *buffer = NULL;
- const guint8 *data;
+ GstMapInfo map;
dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
/* pull in NTSC sized buffer to figure out the frame
* length */
ret = gst_pad_pull_range (dvdemux->sinkpad,
- dvdemux->byte_segment.last_stop, NTSC_BUFFER, &buffer);
+ dvdemux->byte_segment.position, NTSC_BUFFER, &buffer);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto pause;
/* check buffer size, don't want to read small buffers */
- if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < NTSC_BUFFER))
+ if (G_UNLIKELY (gst_buffer_get_size (buffer) < NTSC_BUFFER))
goto small_buffer;
- data = GST_BUFFER_DATA (buffer);
-
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
/* parse header to know the length and other params */
- if (G_UNLIKELY (dv_parse_header (dvdemux->decoder, data) < 0))
+ if (G_UNLIKELY (dv_parse_header (dvdemux->decoder, map.data) < 0)) {
+ gst_buffer_unmap (buffer, &map);
goto parse_header_error;
+ }
+ gst_buffer_unmap (buffer, &map);
/* after parsing the header we know the length of the data */
dvdemux->frame_len = dvdemux->decoder->frame_size;
if (G_LIKELY (buffer == NULL)) {
GST_DEBUG_OBJECT (dvdemux, "pulling buffer at offset %" G_GINT64_FORMAT,
- dvdemux->byte_segment.last_stop);
+ dvdemux->byte_segment.position);
ret = gst_pad_pull_range (dvdemux->sinkpad,
- dvdemux->byte_segment.last_stop, dvdemux->frame_len, &buffer);
+ dvdemux->byte_segment.position, dvdemux->frame_len, &buffer);
if (ret != GST_FLOW_OK)
goto pause;
/* check buffer size, don't want to read small buffers */
- if (GST_BUFFER_SIZE (buffer) < dvdemux->frame_len)
+ if (gst_buffer_get_size (buffer) < dvdemux->frame_len)
goto small_buffer;
}
/* and decode the buffer */
goto pause;
/* and position ourselves for the next buffer */
- dvdemux->byte_segment.last_stop += dvdemux->frame_len;
+ dvdemux->byte_segment.position += dvdemux->frame_len;
done:
gst_object_unref (dvdemux);
GST_ELEMENT_ERROR (dvdemux, STREAM, DECODE,
(NULL), ("Error parsing DV header"));
gst_buffer_unref (buffer);
- dvdemux->running = FALSE;
gst_pad_pause_task (dvdemux->sinkpad);
gst_dvdemux_push_event (dvdemux, gst_event_new_eos ());
goto done;
GST_ELEMENT_ERROR (dvdemux, STREAM, DECODE,
(NULL), ("Error reading buffer"));
gst_buffer_unref (buffer);
- dvdemux->running = FALSE;
gst_pad_pause_task (dvdemux->sinkpad);
gst_dvdemux_push_event (dvdemux, gst_event_new_eos ());
goto done;
pause:
{
GST_INFO_OBJECT (dvdemux, "pausing task, %s", gst_flow_get_name (ret));
- dvdemux->running = FALSE;
gst_pad_pause_task (dvdemux->sinkpad);
if (ret == GST_FLOW_EOS) {
GST_LOG_OBJECT (dvdemux, "got eos");
+ /* so align our position with the end of it, if there is one
+ * this ensures a subsequent will arrive at correct base/acc time */
+ if (dvdemux->time_segment.rate > 0.0 &&
+ GST_CLOCK_TIME_IS_VALID (dvdemux->time_segment.stop))
+ dvdemux->time_segment.position = dvdemux->time_segment.stop;
+ else if (dvdemux->time_segment.rate < 0.0)
+ dvdemux->time_segment.position = dvdemux->time_segment.start;
/* perform EOS logic */
if (dvdemux->time_segment.flags & GST_SEEK_FLAG_SEGMENT) {
gst_element_post_message (GST_ELEMENT (dvdemux),
gst_message_new_segment_done (GST_OBJECT_CAST (dvdemux),
- dvdemux->time_segment.format, dvdemux->time_segment.last_stop));
+ dvdemux->time_segment.format, dvdemux->time_segment.position));
} else {
gst_dvdemux_push_event (dvdemux, gst_event_new_eos ());
}
}
static gboolean
-gst_dvdemux_sink_activate_push (GstPad * sinkpad, gboolean active)
+gst_dvdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
+ GstPadMode mode, gboolean active)
{
- GstDVDemux *demux = GST_DVDEMUX (gst_pad_get_parent (sinkpad));
-
- if (active) {
- demux->seek_handler = gst_dvdemux_handle_push_seek;
- } else {
- demux->seek_handler = NULL;
+ gboolean res;
+ GstDVDemux *demux = GST_DVDEMUX (parent);
+
+ switch (mode) {
+ case GST_PAD_MODE_PULL:
+ if (active) {
+ demux->seek_handler = gst_dvdemux_handle_pull_seek;
+ res = gst_pad_start_task (sinkpad,
+ (GstTaskFunction) gst_dvdemux_loop, sinkpad);
+ } else {
+ demux->seek_handler = NULL;
+ res = gst_pad_stop_task (sinkpad);
+ }
+ break;
+ case GST_PAD_MODE_PUSH:
+ if (active) {
+ GST_DEBUG_OBJECT (demux, "activating push/chain function");
+ demux->seek_handler = gst_dvdemux_handle_push_seek;
+ } else {
+ GST_DEBUG_OBJECT (demux, "deactivating push/chain function");
+ demux->seek_handler = NULL;
+ }
+ res = TRUE;
+ break;
+ default:
+ res = FALSE;
+ break;
}
- gst_object_unref (demux);
-
- return TRUE;
+ return res;
}
+/* decide on push or pull based scheduling */
static gboolean
-gst_dvdemux_sink_activate_pull (GstPad * sinkpad, gboolean active)
+gst_dvdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
{
- GstDVDemux *demux = GST_DVDEMUX (gst_pad_get_parent (sinkpad));
+ GstQuery *query;
+ gboolean pull_mode;
- if (active) {
- demux->running = TRUE;
- demux->seek_handler = gst_dvdemux_handle_pull_seek;
- gst_pad_start_task (sinkpad, (GstTaskFunction) gst_dvdemux_loop, sinkpad);
- } else {
- demux->seek_handler = NULL;
- gst_pad_stop_task (sinkpad);
- demux->running = FALSE;
+ query = gst_query_new_scheduling ();
+
+ if (!gst_pad_peer_query (sinkpad, query)) {
+ gst_query_unref (query);
+ goto activate_push;
}
- gst_object_unref (demux);
+ pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
+ gst_query_unref (query);
- return TRUE;
-};
+ if (!pull_mode)
+ goto activate_push;
-/* decide on push or pull based scheduling */
-static gboolean
-gst_dvdemux_sink_activate (GstPad * sinkpad)
-{
- gboolean ret;
+ GST_DEBUG_OBJECT (sinkpad, "activating pull");
+ return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
- if (gst_pad_check_pull_range (sinkpad))
- ret = gst_pad_activate_pull (sinkpad, TRUE);
- else
- ret = gst_pad_activate_push (sinkpad, TRUE);
-
- return ret;
-};
+activate_push:
+ {
+ GST_DEBUG_OBJECT (sinkpad, "activating push");
+ return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
+ }
+}
static GstStateChangeReturn
gst_dvdemux_change_state (GstElement * element, GstStateChange transition)
break;
}
- ret = parent_class->change_state (element, transition);
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED: