From 9be8a6f48c6a0d5881c730b91e34595934a95378 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 6 Feb 2012 22:13:53 +0100 Subject: [PATCH] dv: port to 0.11 --- configure.ac | 2 +- ext/dv/Makefile.am | 4 +- ext/dv/gstdvdec.c | 274 ++++++++++++++++++-------------- ext/dv/gstdvdec.h | 6 +- ext/dv/gstdvdemux.c | 450 ++++++++++++++++++++++++---------------------------- ext/dv/gstdvdemux.h | 1 - 6 files changed, 370 insertions(+), 367 deletions(-) diff --git a/configure.ac b/configure.ac index 51b5790..f7a2075 100644 --- a/configure.ac +++ b/configure.ac @@ -314,7 +314,7 @@ dnl Make sure you have a space before and after all plugins GST_PLUGINS_NONPORTED="deinterlace interleave flx goom2k1 \ imagefreeze interleave monoscope smpte \ videobox \ - cairo cairo_gobject dv1394 gdk_pixbuf libdv \ + cairo cairo_gobject dv1394 gdk_pixbuf \ oss oss4 shout2 \ wavpack \ osx_video osx_audio " diff --git a/ext/dv/Makefile.am b/ext/dv/Makefile.am index e63154d..4091a5e 100644 --- a/ext/dv/Makefile.am +++ b/ext/dv/Makefile.am @@ -3,8 +3,8 @@ plugin_LTLIBRARIES = libgstdv.la libgstdv_la_SOURCES = gstdv.c gstdvdec.c gstdvdemux.c gstsmptetimecode.c libgstdv_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(LIBDV_CFLAGS) libgstdv_la_LIBADD = \ - $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) \ - $(GST_BASE_LIBS) $(GST_LIBS) $(LIBDV_LIBS) + $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) -lgstvideo-$(GST_MAJORMINOR) \ + $(GST_BASE_LIBS) $(GST_LIBS) $(LIBDV_LIBS) libgstdv_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstdv_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/ext/dv/gstdvdec.c b/ext/dv/gstdvdec.c index e7fd946..84912e5 100644 --- a/ext/dv/gstdvdec.c +++ b/ext/dv/gstdvdec.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "gstdvdec.h" @@ -101,27 +102,10 @@ static GstStaticPadTemplate sink_temp = GST_STATIC_PAD_TEMPLATE ("sink", 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()) @@ -146,12 +130,13 @@ gst_dvdec_quality_get_type (void) 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); @@ -162,24 +147,6 @@ static void gst_dvdec_get_property (GObject * object, guint prop_id, 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 ," "Wim Taymans "); - - GST_DEBUG_CATEGORY_INIT (dvdec_debug, "dvdec", 0, "DV decoding element"); -} - -static void gst_dvdec_class_init (GstDVDecClass * klass) { GObjectClass *gobject_class; @@ -188,7 +155,6 @@ gst_dvdec_class_init (GstDVDecClass * klass) 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; @@ -207,15 +173,25 @@ gst_dvdec_class_init (GstDVDecClass * klass) 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 ," "Wim Taymans "); + + 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); @@ -232,28 +208,14 @@ gst_dvdec_init (GstDVDec * dvdec, GstDVDecClass * g_class) 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); @@ -276,19 +238,64 @@ gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps) 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) { @@ -320,16 +327,24 @@ 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; @@ -338,69 +353,77 @@ gst_dvdec_src_negotiate (GstDVDec * dvdec) } 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)))) @@ -416,7 +439,7 @@ gst_dvdec_chain (GstPad * pad, GstBuffer * buf) /* 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); @@ -441,32 +464,39 @@ gst_dvdec_chain (GstPad * pad, GstBuffer * buf) 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); @@ -479,8 +509,8 @@ skip: dvdec->video_offset++; done: + gst_buffer_unmap (buf, &map); gst_buffer_unref (buf); - gst_object_unref (dvdec); return ret; @@ -534,7 +564,8 @@ gst_dvdec_change_state (GstElement * element, GstStateChange transition) 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; /* @@ -549,7 +580,7 @@ gst_dvdec_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: @@ -557,6 +588,11 @@ gst_dvdec_change_state (GstElement * element, GstStateChange transition) 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; diff --git a/ext/dv/gstdvdec.h b/ext/dv/gstdvdec.h index de8481d..0e52de0 100644 --- a/ext/dv/gstdvdec.h +++ b/ext/dv/gstdvdec.h @@ -23,6 +23,8 @@ #include +#include + #include @@ -63,6 +65,7 @@ struct _GstDVDec { /* input caps */ gboolean sink_negotiated; + GstVideoInfo vinfo; gint framerate_numerator; gint framerate_denominator; gint height; @@ -78,7 +81,8 @@ struct _GstDVDec { gint video_offset; gint drop_factor; - GstSegment *segment; + GstBufferPool *pool; + GstSegment segment; }; struct _GstDVDecClass { diff --git a/ext/dv/gstdvdemux.c b/ext/dv/gstdvdemux.c index fe0617e..aecef4f 100644 --- a/ext/dv/gstdvdemux.c +++ b/ext/dv/gstdvdemux.c @@ -123,25 +123,23 @@ static GstStaticPadTemplate video_src_temp = GST_STATIC_PAD_TEMPLATE ("video", 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, @@ -153,44 +151,26 @@ static gboolean gst_dvdemux_src_convert (GstDVDemux * demux, GstPad * pad, /* 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 , Wim Taymans "); - - GST_DEBUG_CATEGORY_INIT (dvdemux_debug, "dvdemux", 0, "DV demuxer element"); -} - -static void gst_dvdemux_class_init (GstDVDemuxClass * klass) { GObjectClass *gobject_class; @@ -203,10 +183,24 @@ gst_dvdemux_class_init (GstDVDemuxClass * klass) 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 , Wim Taymans "); + + 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; @@ -216,11 +210,8 @@ gst_dvdemux_init (GstDVDemux * dvdemux, GstDVDemuxClass * g_class) 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)); @@ -230,8 +221,6 @@ gst_dvdemux_init (GstDVDemux * dvdemux, GstDVDemuxClass * g_class) /* 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); @@ -296,8 +285,6 @@ gst_dvdemux_add_pad (GstDVDemux * dvdemux, GstStaticPadTemplate * template) 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); @@ -311,14 +298,12 @@ gst_dvdemux_add_pad (GstDVDemux * dvdemux, GstStaticPadTemplate * template) 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; @@ -532,26 +517,13 @@ error: } } -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: @@ -564,7 +536,7 @@ gst_dvdemux_src_query (GstPad * pad, GstQuery * query) /* 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); @@ -618,40 +590,27 @@ gst_dvdemux_src_query (GstPad * pad, GstQuery * query) 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: @@ -668,17 +627,15 @@ gst_dvdemux_sink_query (GstPad * pad, GstQuery * query) 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; } @@ -704,9 +661,10 @@ gst_dvdemux_push_event (GstDVDemux * dvdemux, GstEvent * event) } 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)) { @@ -723,29 +681,24 @@ gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * 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); @@ -755,11 +708,12 @@ gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * event) * 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); @@ -780,13 +734,14 @@ gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * 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; } @@ -947,22 +902,25 @@ gst_dvdemux_do_seek (GstDVDemux * demux, GstSegment * segment) * 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; @@ -1043,34 +1001,22 @@ gst_dvdemux_handle_pull_seek (GstDVDemux * demux, GstPad * pad, /* 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 @@ -1081,7 +1027,7 @@ gst_dvdemux_handle_pull_seek (GstDVDemux * demux, GstPad * pad, 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; @@ -1092,14 +1038,11 @@ gst_dvdemux_handle_pull_seek (GstDVDemux * demux, GstPad * pad, 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, @@ -1166,12 +1109,13 @@ gst_dvdemux_send_event (GstElement * element, GstEvent * event) /* 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: @@ -1186,7 +1130,8 @@ gst_dvdemux_handle_src_event (GstPad * pad, GstEvent * event) res = FALSE; break; case GST_EVENT_NAVIGATION: - /* no navigation either... */ + case GST_EVENT_CAPS: + /* no navigation or caps either... */ res = FALSE; break; default: @@ -1197,8 +1142,6 @@ gst_dvdemux_handle_src_event (GstPad * pad, GstEvent * event) if (event) gst_event_unref (event); - gst_object_unref (dvdemux); - return res; } @@ -1209,11 +1152,11 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer, { 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; @@ -1231,18 +1174,15 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer, 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); } @@ -1250,18 +1190,20 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer, 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; @@ -1269,7 +1211,6 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer, 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 { @@ -1337,19 +1278,18 @@ gst_dvdemux_demux_video (GstDVDemux * dvdemux, GstBuffer * buffer, /* 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); @@ -1375,11 +1315,14 @@ static gboolean 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) { @@ -1393,23 +1336,28 @@ gst_dvdemux_get_timecode (GstDVDemux * dvdemux, GstBuffer * buffer, (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; @@ -1417,11 +1365,14 @@ gst_dvdemux_is_new_media (GstDVDemux * dvdemux, GstBuffer * buffer) 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; } @@ -1431,13 +1382,12 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer) { 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 */ @@ -1445,12 +1395,12 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer) 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; @@ -1465,10 +1415,8 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer) 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; } @@ -1482,11 +1430,11 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer) 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) { @@ -1513,7 +1461,7 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer) 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 */ @@ -1545,11 +1493,14 @@ gst_dvdemux_flush (GstDVDemux * dvdemux) 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; @@ -1569,13 +1520,7 @@ gst_dvdemux_flush (GstDVDemux * dvdemux) 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); @@ -1600,13 +1545,13 @@ parse_header_error: * 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 @@ -1617,8 +1562,7 @@ gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer) /* 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 */ } @@ -1637,8 +1581,6 @@ gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer) /* and try to flush pending frames */ ret = gst_dvdemux_flush (dvdemux); - gst_object_unref (dvdemux); - return ret; } @@ -1653,7 +1595,7 @@ gst_dvdemux_loop (GstPad * pad) GstFlowReturn ret; GstDVDemux *dvdemux; GstBuffer *buffer = NULL; - const guint8 *data; + GstMapInfo map; dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad)); @@ -1662,19 +1604,21 @@ gst_dvdemux_loop (GstPad * 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; @@ -1736,15 +1680,15 @@ gst_dvdemux_loop (GstPad * pad) 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 */ @@ -1753,7 +1697,7 @@ gst_dvdemux_loop (GstPad * pad) 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); @@ -1766,7 +1710,6 @@ parse_header_error: 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; @@ -1776,7 +1719,6 @@ small_buffer: 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; @@ -1784,15 +1726,21 @@ small_buffer: 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 ()); } @@ -1807,53 +1755,69 @@ pause: } 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) @@ -1875,7 +1839,7 @@ 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: diff --git a/ext/dv/gstdvdemux.h b/ext/dv/gstdvdemux.h index 9a4173d..9303e4d 100644 --- a/ext/dv/gstdvdemux.h +++ b/ext/dv/gstdvdemux.h @@ -75,7 +75,6 @@ struct _GstDVDemux { GstDVDemuxSeekHandler seek_handler; GstSegment byte_segment; GstSegment time_segment; - gboolean running; gboolean need_segment; gboolean new_media; int frames_since_new_media; -- 2.7.4