dv: port to 0.11

This commit is contained in:
Mark Nauwelaerts 2012-02-06 22:13:53 +01:00
parent 92a0c01732
commit 9be8a6f48c
6 changed files with 369 additions and 366 deletions

View file

@ -314,7 +314,7 @@ dnl Make sure you have a space before and after all plugins
GST_PLUGINS_NONPORTED="deinterlace interleave flx goom2k1 \ GST_PLUGINS_NONPORTED="deinterlace interleave flx goom2k1 \
imagefreeze interleave monoscope smpte \ imagefreeze interleave monoscope smpte \
videobox \ videobox \
cairo cairo_gobject dv1394 gdk_pixbuf libdv \ cairo cairo_gobject dv1394 gdk_pixbuf \
oss oss4 shout2 \ oss oss4 shout2 \
wavpack \ wavpack \
osx_video osx_audio " osx_video osx_audio "

View file

@ -3,7 +3,7 @@ plugin_LTLIBRARIES = libgstdv.la
libgstdv_la_SOURCES = gstdv.c gstdvdec.c gstdvdemux.c gstsmptetimecode.c 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_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(LIBDV_CFLAGS)
libgstdv_la_LIBADD = \ libgstdv_la_LIBADD = \
$(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) \ $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) -lgstvideo-$(GST_MAJORMINOR) \
$(GST_BASE_LIBS) $(GST_LIBS) $(LIBDV_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) $(LIBDV_LIBS)
libgstdv_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstdv_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstdv_la_LIBTOOLFLAGS = --tag=disable-static libgstdv_la_LIBTOOLFLAGS = --tag=disable-static

View file

@ -44,6 +44,7 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <gst/video/video.h> #include <gst/video/video.h>
#include <gst/video/gstvideopool.h>
#include "gstdvdec.h" #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", static GstStaticPadTemplate src_temp = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-yuv, " GST_STATIC_CAPS ("video/x-raw, "
"format = (fourcc) YUY2, " "format = (string) { YUY2, BGRx, RGB }, "
"width = (int) 720, " "framerate = (fraction) [ 1/1, 60/1 ], "
"framerate = (fraction) [ 1/1, 60/1 ];" "width = (int) 720, " "height = (int) { 576, 480 }")
"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 ]")
); );
#define GST_TYPE_DVDEC_QUALITY (gst_dvdec_quality_get_type()) #define GST_TYPE_DVDEC_QUALITY (gst_dvdec_quality_get_type())
@ -146,12 +130,13 @@ gst_dvdec_quality_get_type (void)
return qtype; 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 GstFlowReturn gst_dvdec_chain (GstPad * pad, GstObject * parent,
static gboolean gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps); GstBuffer * buffer);
static GstFlowReturn gst_dvdec_chain (GstPad * pad, GstBuffer * buffer); static gboolean gst_dvdec_sink_event (GstPad * pad, GstObject * parent,
static gboolean gst_dvdec_sink_event (GstPad * pad, GstEvent * event); GstEvent * event);
static GstStateChangeReturn gst_dvdec_change_state (GstElement * element, static GstStateChangeReturn gst_dvdec_change_state (GstElement * element,
GstStateChange transition); GstStateChange transition);
@ -161,24 +146,6 @@ static void gst_dvdec_set_property (GObject * object, guint prop_id,
static void gst_dvdec_get_property (GObject * object, guint prop_id, static void gst_dvdec_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); 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 static void
gst_dvdec_class_init (GstDVDecClass * klass) gst_dvdec_class_init (GstDVDecClass * klass)
{ {
@ -188,7 +155,6 @@ gst_dvdec_class_init (GstDVDecClass * klass)
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass; gstelement_class = (GstElementClass *) klass;
gobject_class->finalize = gst_dvdec_finalize;
gobject_class->set_property = gst_dvdec_set_property; gobject_class->set_property = gst_dvdec_set_property;
gobject_class->get_property = gst_dvdec_get_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, 1, G_MAXINT, DV_DEFAULT_DECODE_NTH,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); 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 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"); 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_chain_function (dvdec->sinkpad, gst_dvdec_chain);
gst_pad_set_event_function (dvdec->sinkpad, gst_dvdec_sink_event); gst_pad_set_event_function (dvdec->sinkpad, gst_dvdec_sink_event);
gst_element_add_pad (GST_ELEMENT (dvdec), dvdec->sinkpad); 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_luma = FALSE;
dvdec->clamp_chroma = FALSE; dvdec->clamp_chroma = FALSE;
dvdec->quality = DV_DEFAULT_QUALITY; 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 static gboolean
gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps) gst_dvdec_sink_setcaps (GstDVDec * dvdec, GstCaps * caps)
{ {
GstDVDec *dvdec;
GstStructure *s; GstStructure *s;
const GValue *par = NULL, *rate = NULL; const GValue *par = NULL, *rate = NULL;
dvdec = GST_DVDEC (gst_pad_get_parent (pad));
/* first parse the caps */ /* first parse the caps */
s = gst_caps_get_structure (caps, 0); s = gst_caps_get_structure (caps, 0);
@ -276,19 +238,64 @@ gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
dvdec->sink_negotiated = TRUE; dvdec->sink_negotiated = TRUE;
dvdec->src_negotiated = FALSE; dvdec->src_negotiated = FALSE;
gst_object_unref (dvdec);
return TRUE; return TRUE;
/* ERRORS */ /* ERRORS */
no_framerate: no_framerate:
{ {
GST_DEBUG_OBJECT (dvdec, "no framerate specified in caps"); GST_DEBUG_OBJECT (dvdec, "no framerate specified in caps");
gst_object_unref (dvdec);
return FALSE; 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 static gboolean
gst_dvdec_src_negotiate (GstDVDec * dvdec) gst_dvdec_src_negotiate (GstDVDec * dvdec)
{ {
@ -320,16 +327,24 @@ gst_dvdec_src_negotiate (GstDVDec * dvdec)
/* ignoring rgb, bgr0 for now */ /* ignoring rgb, bgr0 for now */
dvdec->bpp = 2; dvdec->bpp = 2;
othercaps = gst_caps_new_simple ("video/x-raw-yuv", gst_video_info_set_format (&dvdec->vinfo, GST_VIDEO_FORMAT_YUY2,
"format", GST_TYPE_FOURCC, GST_STR_FOURCC ("YUY2"), 720, dvdec->height);
"width", G_TYPE_INT, 720, dvdec->vinfo.fps_n = dvdec->framerate_numerator;
"height", G_TYPE_INT, dvdec->height, dvdec->vinfo.fps_d = dvdec->framerate_denominator;
"framerate", GST_TYPE_FRACTION, dvdec->framerate_numerator, dvdec->vinfo.par_n = dvdec->par_x;
dvdec->framerate_denominator, dvdec->vinfo.par_d = dvdec->par_y;
"pixel-aspect-ratio", GST_TYPE_FRACTION, dvdec->par_x, if (dvdec->interlaced) {
dvdec->par_y, "interlaced", G_TYPE_BOOLEAN, dvdec->interlaced, NULL); 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_pad_set_caps (dvdec->srcpad, othercaps);
gst_dvdec_negotiate_pool (dvdec, othercaps, &dvdec->vinfo);
gst_caps_unref (othercaps); gst_caps_unref (othercaps);
dvdec->src_negotiated = TRUE; dvdec->src_negotiated = TRUE;
@ -338,69 +353,77 @@ gst_dvdec_src_negotiate (GstDVDec * dvdec)
} }
static gboolean static gboolean
gst_dvdec_sink_event (GstPad * pad, GstEvent * event) gst_dvdec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{ {
GstDVDec *dvdec; GstDVDec *dvdec;
gboolean res = TRUE; gboolean res = TRUE;
dvdec = GST_DVDEC (gst_pad_get_parent (pad)); dvdec = GST_DVDEC (parent);
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_STOP: case GST_EVENT_FLUSH_STOP:
gst_segment_init (dvdec->segment, GST_FORMAT_UNDEFINED); gst_segment_init (&dvdec->segment, GST_FORMAT_UNDEFINED);
break; break;
case GST_EVENT_NEWSEGMENT:{ case GST_EVENT_SEGMENT:{
gboolean update; const GstSegment *segment;
gdouble rate, applied_rate;
GstFormat format;
gint64 start, stop, position;
gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, gst_event_parse_segment (event, &segment);
&format, &start, &stop, &position);
GST_DEBUG_OBJECT (dvdec, "Got NEWSEGMENT [%" GST_TIME_FORMAT GST_DEBUG_OBJECT (dvdec, "Got NEWSEGMENT %" GST_SEGMENT_FORMAT, &segment);
" - %" 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, gst_segment_copy_into (segment, &dvdec->segment);
applied_rate, format, start, stop, position);
break; 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: default:
break; break;
} }
if (event)
res = gst_pad_push_event (dvdec->srcpad, event); res = gst_pad_push_event (dvdec->srcpad, event);
return res; return res;
} }
static GstFlowReturn static GstFlowReturn
gst_dvdec_chain (GstPad * pad, GstBuffer * buf) gst_dvdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{ {
GstDVDec *dvdec; GstDVDec *dvdec;
guint8 *inframe; guint8 *inframe;
guint8 *outframe;
guint8 *outframe_ptrs[3]; guint8 *outframe_ptrs[3];
gint outframe_pitches[3]; gint outframe_pitches[3];
GstMapInfo map;
GstVideoFrame frame;
GstBuffer *outbuf; GstBuffer *outbuf;
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
guint length; guint length;
gint64 cstart, cstop; guint64 cstart, cstop;
gboolean PAL, wide; gboolean PAL, wide;
dvdec = GST_DVDEC (gst_pad_get_parent (pad)); dvdec = GST_DVDEC (parent);
inframe = GST_BUFFER_DATA (buf);
gst_buffer_map (buf, &map, GST_MAP_READ);
inframe = map.data;
/* buffer should be at least the size of one NTSC frame, this should /* buffer should be at least the size of one NTSC frame, this should
* be enough to decode the header. */ * 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; goto wrong_size;
/* preliminary dropping. unref and return if outside of configured segment */ /* preliminary dropping. unref and return if outside of configured segment */
if ((dvdec->segment->format == GST_FORMAT_TIME) && if ((dvdec->segment.format == GST_FORMAT_TIME) &&
(!(gst_segment_clip (dvdec->segment, GST_FORMAT_TIME, (!(gst_segment_clip (&dvdec->segment, GST_FORMAT_TIME,
GST_BUFFER_TIMESTAMP (buf), GST_BUFFER_TIMESTAMP (buf),
GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf), GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf),
&cstart, &cstop)))) &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 /* check the buffer is of right size after we know if we are
* dealing with PAL or NTSC */ * dealing with PAL or NTSC */
length = (PAL ? PAL_BUFFER : NTSC_BUFFER); length = (PAL ? PAL_BUFFER : NTSC_BUFFER);
if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < length)) if (G_UNLIKELY (map.size < length))
goto wrong_size; goto wrong_size;
dv_parse_packs (dvdec->decoder, inframe); dv_parse_packs (dvdec->decoder, inframe);
@ -441,32 +464,39 @@ gst_dvdec_chain (GstPad * pad, GstBuffer * buf)
goto not_negotiated; goto not_negotiated;
} }
ret = if (gst_pad_check_reconfigure (dvdec->srcpad)) {
gst_pad_alloc_buffer_and_set_caps (dvdec->srcpad, 0, GstCaps *caps;
(720 * dvdec->height) * dvdec->bpp,
GST_PAD_CAPS (dvdec->srcpad), &outbuf); 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)) if (G_UNLIKELY (ret != GST_FLOW_OK))
goto no_buffer; goto no_buffer;
outframe = GST_BUFFER_DATA (outbuf); gst_video_frame_map (&frame, &dvdec->vinfo, outbuf, GST_MAP_WRITE);
outframe_ptrs[0] = outframe; outframe_ptrs[0] = GST_VIDEO_FRAME_COMP_DATA (&frame, 0);
outframe_pitches[0] = 720 * dvdec->bpp; outframe_pitches[0] = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 0);
/* the rest only matters for YUY2 */ /* the rest only matters for YUY2 */
if (dvdec->bpp < 3) { if (dvdec->bpp < 3) {
outframe_ptrs[1] = outframe_ptrs[0] + 720 * dvdec->height; outframe_ptrs[1] = GST_VIDEO_FRAME_COMP_DATA (&frame, 1);
outframe_ptrs[2] = outframe_ptrs[1] + 360 * dvdec->height; outframe_ptrs[2] = GST_VIDEO_FRAME_COMP_DATA (&frame, 2);
outframe_pitches[1] = dvdec->height / 2; outframe_pitches[1] = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 1);
outframe_pitches[2] = outframe_pitches[1]; outframe_pitches[2] = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 2);
} }
GST_DEBUG_OBJECT (dvdec, "decoding and pushing buffer"); GST_DEBUG_OBJECT (dvdec, "decoding and pushing buffer");
dv_decode_full_frame (dvdec->decoder, inframe, dv_decode_full_frame (dvdec->decoder, inframe,
e_dv_color_yuv, outframe_ptrs, outframe_pitches); 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 (outbuf) = GST_BUFFER_OFFSET (buf);
GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_END (buf); GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_END (buf);
@ -479,8 +509,8 @@ skip:
dvdec->video_offset++; dvdec->video_offset++;
done: done:
gst_buffer_unmap (buf, &map);
gst_buffer_unref (buf); gst_buffer_unref (buf);
gst_object_unref (dvdec);
return ret; return ret;
@ -534,7 +564,8 @@ gst_dvdec_change_state (GstElement * element, GstStateChange transition)
dv_decoder_new (0, dvdec->clamp_luma, dvdec->clamp_chroma); dv_decoder_new (0, dvdec->clamp_luma, dvdec->clamp_chroma);
dvdec->decoder->quality = qualities[dvdec->quality]; dvdec->decoder->quality = qualities[dvdec->quality];
dv_set_error_log (dvdec->decoder, NULL); 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->src_negotiated = FALSE;
dvdec->sink_negotiated = FALSE; dvdec->sink_negotiated = FALSE;
/* /*
@ -549,7 +580,7 @@ gst_dvdec_change_state (GstElement * element, GstStateChange transition)
break; break;
} }
ret = parent_class->change_state (element, transition); ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) { switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED: 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: case GST_STATE_CHANGE_PAUSED_TO_READY:
dv_decoder_free (dvdec->decoder); dv_decoder_free (dvdec->decoder);
dvdec->decoder = NULL; dvdec->decoder = NULL;
if (dvdec->pool) {
gst_buffer_pool_set_active (dvdec->pool, FALSE);
gst_object_unref (dvdec->pool);
dvdec->pool = NULL;
}
break; break;
case GST_STATE_CHANGE_READY_TO_NULL: case GST_STATE_CHANGE_READY_TO_NULL:
break; break;

View file

@ -23,6 +23,8 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/video/video.h>
#include <libdv/dv.h> #include <libdv/dv.h>
@ -63,6 +65,7 @@ struct _GstDVDec {
/* input caps */ /* input caps */
gboolean sink_negotiated; gboolean sink_negotiated;
GstVideoInfo vinfo;
gint framerate_numerator; gint framerate_numerator;
gint framerate_denominator; gint framerate_denominator;
gint height; gint height;
@ -78,7 +81,8 @@ struct _GstDVDec {
gint video_offset; gint video_offset;
gint drop_factor; gint drop_factor;
GstSegment *segment; GstBufferPool *pool;
GstSegment segment;
}; };
struct _GstDVDecClass { struct _GstDVDecClass {

View file

@ -123,25 +123,23 @@ static GstStaticPadTemplate video_src_temp = GST_STATIC_PAD_TEMPLATE ("video",
static GstStaticPadTemplate audio_src_temp = GST_STATIC_PAD_TEMPLATE ("audio", static GstStaticPadTemplate audio_src_temp = GST_STATIC_PAD_TEMPLATE ("audio",
GST_PAD_SRC, GST_PAD_SRC,
GST_PAD_SOMETIMES, GST_PAD_SOMETIMES,
GST_STATIC_CAPS ("audio/x-raw-int, " GST_STATIC_CAPS ("audio/x-raw, "
"depth = (int) 16, " "format = (string) " GST_AUDIO_NE (S16) ", "
"width = (int) 16, " "layout = (string) interleaved, "
"signed = (boolean) TRUE, " "rate = (int) { 32000, 44100, 48000 }, " "channels = (int) {2, 4}")
"channels = (int) {2, 4}, "
"endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
"rate = (int) { 32000, 44100, 48000 }")
); );
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); static void gst_dvdemux_finalize (GObject * object);
/* query functions */ /* query functions */
static const GstQueryType *gst_dvdemux_get_src_query_types (GstPad * pad); static gboolean gst_dvdemux_src_query (GstPad * pad, GstObject * parent,
static gboolean gst_dvdemux_src_query (GstPad * pad, GstQuery * query); GstQuery * query);
static const GstQueryType *gst_dvdemux_get_sink_query_types (GstPad * pad); static gboolean gst_dvdemux_sink_query (GstPad * pad, GstObject * parent,
static gboolean gst_dvdemux_sink_query (GstPad * pad, GstQuery * query); GstQuery * query);
/* convert functions */ /* convert functions */
static gboolean gst_dvdemux_sink_convert (GstDVDemux * demux, static gboolean gst_dvdemux_sink_convert (GstDVDemux * demux,
@ -153,43 +151,25 @@ static gboolean gst_dvdemux_src_convert (GstDVDemux * demux, GstPad * pad,
/* event functions */ /* event functions */
static gboolean gst_dvdemux_send_event (GstElement * element, GstEvent * event); 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_src_event (GstPad * pad, GstObject * parent,
static gboolean gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * event); GstEvent * event);
static gboolean gst_dvdemux_handle_sink_event (GstPad * pad, GstObject * parent,
GstEvent * event);
/* scheduling functions */ /* scheduling functions */
static void gst_dvdemux_loop (GstPad * pad); static void gst_dvdemux_loop (GstPad * pad);
static GstFlowReturn gst_dvdemux_flush (GstDVDemux * dvdemux); 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 */ /* state change functions */
static gboolean gst_dvdemux_sink_activate (GstPad * sinkpad); static gboolean gst_dvdemux_sink_activate (GstPad * sinkpad,
static gboolean gst_dvdemux_sink_activate_push (GstPad * sinkpad, GstObject * parent);
gboolean active); static gboolean gst_dvdemux_sink_activate_mode (GstPad * sinkpad,
static gboolean gst_dvdemux_sink_activate_pull (GstPad * sinkpad, GstObject * parent, GstPadMode mode, gboolean active);
gboolean active);
static GstStateChangeReturn gst_dvdemux_change_state (GstElement * element, static GstStateChangeReturn gst_dvdemux_change_state (GstElement * element,
GstStateChange transition); 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 static void
gst_dvdemux_class_init (GstDVDemuxClass * klass) gst_dvdemux_class_init (GstDVDemuxClass * klass)
{ {
@ -203,10 +183,24 @@ gst_dvdemux_class_init (GstDVDemuxClass * klass)
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dvdemux_change_state); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dvdemux_change_state);
gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_dvdemux_send_event); 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 static void
gst_dvdemux_init (GstDVDemux * dvdemux, GstDVDemuxClass * g_class) gst_dvdemux_init (GstDVDemux * dvdemux)
{ {
gint i; gint i;
@ -216,11 +210,8 @@ gst_dvdemux_init (GstDVDemux * dvdemux, GstDVDemuxClass * g_class)
gst_pad_set_activate_function (dvdemux->sinkpad, gst_pad_set_activate_function (dvdemux->sinkpad,
GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate)); GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate));
/* the function to activate in push mode */ /* the function to activate in push mode */
gst_pad_set_activatepush_function (dvdemux->sinkpad, gst_pad_set_activatemode_function (dvdemux->sinkpad,
GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate_push)); GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate_mode));
/* the function to activate in pull mode */
gst_pad_set_activatepull_function (dvdemux->sinkpad,
GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate_pull));
/* for push mode, this is the chain function */ /* for push mode, this is the chain function */
gst_pad_set_chain_function (dvdemux->sinkpad, gst_pad_set_chain_function (dvdemux->sinkpad,
GST_DEBUG_FUNCPTR (gst_dvdemux_chain)); GST_DEBUG_FUNCPTR (gst_dvdemux_chain));
@ -230,8 +221,6 @@ gst_dvdemux_init (GstDVDemux * dvdemux, GstDVDemuxClass * g_class)
/* query functions */ /* query functions */
gst_pad_set_query_function (dvdemux->sinkpad, gst_pad_set_query_function (dvdemux->sinkpad,
GST_DEBUG_FUNCPTR (gst_dvdemux_sink_query)); 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 */ /* now add the pad */
gst_element_add_pad (GST_ELEMENT (dvdemux), dvdemux->sinkpad); 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_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_pad_set_event_function (pad,
GST_DEBUG_FUNCPTR (gst_dvdemux_handle_src_event)); GST_DEBUG_FUNCPTR (gst_dvdemux_handle_src_event));
gst_pad_use_fixed_caps (pad); gst_pad_use_fixed_caps (pad);
@ -311,14 +298,12 @@ gst_dvdemux_add_pad (GstDVDemux * dvdemux, GstStaticPadTemplate * template)
if (no_more_pads) if (no_more_pads)
gst_element_no_more_pads (GST_ELEMENT (dvdemux)); gst_element_no_more_pads (GST_ELEMENT (dvdemux));
gst_pad_push_event (pad, gst_event_new_new_segment (FALSE, gst_pad_push_event (pad, gst_event_new_segment (&dvdemux->time_segment));
dvdemux->byte_segment.rate, GST_FORMAT_TIME,
dvdemux->time_segment.start, dvdemux->time_segment.stop,
dvdemux->time_segment.start));
if (no_more_pads) { if (no_more_pads) {
gst_element_found_tags (GST_ELEMENT (dvdemux), gst_pad_push_event (pad,
gst_tag_list_new_full (GST_TAG_CONTAINER_FORMAT, "DV", NULL)); gst_event_new_tag (gst_tag_list_new (GST_TAG_CONTAINER_FORMAT, "DV",
NULL)));
} }
return pad; 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 static gboolean
gst_dvdemux_src_query (GstPad * pad, GstQuery * query) gst_dvdemux_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
{ {
gboolean res = TRUE; gboolean res = TRUE;
GstDVDemux *dvdemux; GstDVDemux *dvdemux;
dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad)); dvdemux = GST_DVDEMUX (parent);
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_POSITION: case GST_QUERY_POSITION:
@ -564,7 +536,7 @@ gst_dvdemux_src_query (GstPad * pad, GstQuery * query)
/* bring the position to the requested format. */ /* bring the position to the requested format. */
if (!(res = gst_dvdemux_src_convert (dvdemux, pad, 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))) &format, &cur)))
goto error; goto error;
gst_query_set_position (query, format, cur); gst_query_set_position (query, format, cur);
@ -618,40 +590,27 @@ gst_dvdemux_src_query (GstPad * pad, GstQuery * query)
break; break;
} }
default: default:
res = gst_pad_query_default (pad, query); res = gst_pad_query_default (pad, parent, query);
break; break;
} }
gst_object_unref (dvdemux);
return res; return res;
/* ERRORS */ /* ERRORS */
error: error:
{ {
gst_object_unref (dvdemux);
GST_DEBUG ("error source query"); GST_DEBUG ("error source query");
return FALSE; 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 static gboolean
gst_dvdemux_sink_query (GstPad * pad, GstQuery * query) gst_dvdemux_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
{ {
gboolean res = TRUE; gboolean res = TRUE;
GstDVDemux *dvdemux; GstDVDemux *dvdemux;
dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad)); dvdemux = GST_DVDEMUX (parent);
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CONVERT: case GST_QUERY_CONVERT:
@ -668,17 +627,15 @@ gst_dvdemux_sink_query (GstPad * pad, GstQuery * query)
break; break;
} }
default: default:
res = gst_pad_query_default (pad, query); res = gst_pad_query_default (pad, parent, query);
break; break;
} }
gst_object_unref (dvdemux);
return res; return res;
/* ERRORS */ /* ERRORS */
error: error:
{ {
gst_object_unref (dvdemux);
GST_DEBUG ("error handling sink query"); GST_DEBUG ("error handling sink query");
return FALSE; return FALSE;
} }
@ -704,9 +661,10 @@ gst_dvdemux_push_event (GstDVDemux * dvdemux, GstEvent * event)
} }
static gboolean 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; gboolean res = TRUE;
switch (GST_EVENT_TYPE (event)) { 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); gst_segment_init (&dvdemux->time_segment, GST_FORMAT_TIME);
res = gst_dvdemux_push_event (dvdemux, event); res = gst_dvdemux_push_event (dvdemux, event);
break; break;
case GST_EVENT_NEWSEGMENT: case GST_EVENT_SEGMENT:
{ {
gboolean update; const GstSegment *segment;
gdouble rate;
GstFormat format;
gint64 start, stop, time;
/* parse byte start and stop positions */ gst_event_parse_segment (event, &segment);
gst_event_parse_new_segment (event, &update, &rate, &format, switch (segment->format) {
&start, &stop, &time);
switch (format) {
case GST_FORMAT_BYTES: case GST_FORMAT_BYTES:
gst_segment_set_newsegment (&dvdemux->byte_segment, update, gst_segment_copy_into (segment, &dvdemux->byte_segment);
rate, format, start, stop, time);
#if 0
/* FIXME ?? no longer such subtle distinction in 0.11 */
/* the update can always be sent */ /* the update can always be sent */
if (update) { if (update) {
GstEvent *update; GstEvent *update;
update = gst_event_new_new_segment (TRUE, update = gst_event_new_new_segment (TRUE,
dvdemux->time_segment.rate, dvdemux->time_segment.format, 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); dvdemux->time_segment.time);
gst_dvdemux_push_event (dvdemux, update); gst_dvdemux_push_event (dvdemux, update);
@ -755,11 +708,12 @@ gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * event)
* frames, etc.. */ * frames, etc.. */
dvdemux->need_segment = TRUE; dvdemux->need_segment = TRUE;
} }
#endif
dvdemux->need_segment = TRUE;
gst_event_unref (event); gst_event_unref (event);
break; break;
case GST_FORMAT_TIME: case GST_FORMAT_TIME:
gst_segment_set_newsegment (&dvdemux->time_segment, update, gst_segment_copy_into (segment, &dvdemux->time_segment);
rate, format, start, stop, time);
/* and we can just forward this time event */ /* and we can just forward this time event */
res = gst_dvdemux_push_event (dvdemux, 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 */ /* and clear the adapter */
gst_adapter_clear (dvdemux->adapter); gst_adapter_clear (dvdemux->adapter);
break; break;
case GST_EVENT_CAPS:
gst_event_unref (event);
break;
default: default:
res = gst_dvdemux_push_event (dvdemux, event); res = gst_dvdemux_push_event (dvdemux, event);
break; break;
} }
gst_object_unref (dvdemux);
return res; return res;
} }
@ -947,22 +902,25 @@ gst_dvdemux_do_seek (GstDVDemux * demux, GstSegment * segment)
* timestamp can be found. */ * timestamp can be found. */
format = GST_FORMAT_BYTES; format = GST_FORMAT_BYTES;
res = gst_dvdemux_sink_convert (demux, res = gst_dvdemux_sink_convert (demux,
segment->format, segment->last_stop, segment->format, segment->position,
&format, &demux->byte_segment.last_stop); &format, (gint64 *) & demux->byte_segment.position);
if (!res) if (!res)
goto done; goto done;
/* update byte segment start */ /* update byte segment start */
gst_dvdemux_sink_convert (demux, 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 */ /* update byte segment stop */
gst_dvdemux_sink_convert (demux, 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 */ /* update byte segment time */
gst_dvdemux_sink_convert (demux, 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 */ /* calculate current frame number */
format = GST_FORMAT_DEFAULT; format = GST_FORMAT_DEFAULT;
@ -1043,34 +1001,22 @@ gst_dvdemux_handle_pull_seek (GstDVDemux * demux, GstPad * pad,
/* now configure the seek segment */ /* now configure the seek segment */
if (event) { 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); cur_type, cur, stop_type, stop, &update);
} }
GST_DEBUG_OBJECT (demux, "segment configured from %" G_GINT64_FORMAT GST_DEBUG_OBJECT (demux, "segment configured from %" G_GINT64_FORMAT
" to %" G_GINT64_FORMAT ", position %" 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); res = gst_dvdemux_do_seek (demux, &seeksegment);
/* and prepare to continue streaming */ /* and prepare to continue streaming */
if (flush) { if (flush) {
/* send flush stop, peer will accept data and events again. We /* send flush stop, peer will accept data and events again. We
* are not yet providing data as we still have the STREAM_LOCK. */ * are not yet providing data as we still have the STREAM_LOCK. */
gst_dvdemux_push_event (demux, gst_event_new_flush_stop ()); gst_dvdemux_push_event (demux, gst_event_new_flush_stop (TRUE));
} 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));
} }
/* if successfull seek, we update our real segment and push /* 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) { if (demux->time_segment.flags & GST_SEEK_FLAG_SEGMENT) {
gst_element_post_message (GST_ELEMENT_CAST (demux), gst_element_post_message (GST_ELEMENT_CAST (demux),
gst_message_new_segment_start (GST_OBJECT_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) if ((stop = demux->time_segment.stop) == -1)
stop = demux->time_segment.duration; stop = demux->time_segment.duration;
@ -1092,14 +1038,11 @@ gst_dvdemux_handle_pull_seek (GstDVDemux * demux, GstPad * pad,
if (demux->pending_segment) if (demux->pending_segment)
gst_event_unref (demux->pending_segment); gst_event_unref (demux->pending_segment);
demux->pending_segment = gst_event_new_new_segment (FALSE, demux->pending_segment = gst_event_new_segment (&demux->time_segment);
demux->time_segment.rate, demux->time_segment.format,
demux->time_segment.last_stop, stop, demux->time_segment.time);
demux->need_segment = FALSE; demux->need_segment = FALSE;
} }
demux->running = TRUE;
/* and restart the task in case it got paused explicitely or by /* and restart the task in case it got paused explicitely or by
* the FLUSH_START event we pushed out. */ * the FLUSH_START event we pushed out. */
gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_dvdemux_loop, 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 */ /* handle an event on the source pad, it's most likely a seek */
static gboolean 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; gboolean res = TRUE;
GstDVDemux *dvdemux; GstDVDemux *dvdemux;
dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad)); dvdemux = GST_DVDEMUX (parent);
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK: case GST_EVENT_SEEK:
@ -1186,7 +1130,8 @@ gst_dvdemux_handle_src_event (GstPad * pad, GstEvent * event)
res = FALSE; res = FALSE;
break; break;
case GST_EVENT_NAVIGATION: case GST_EVENT_NAVIGATION:
/* no navigation either... */ case GST_EVENT_CAPS:
/* no navigation or caps either... */
res = FALSE; res = FALSE;
break; break;
default: default:
@ -1197,8 +1142,6 @@ gst_dvdemux_handle_src_event (GstPad * pad, GstEvent * event)
if (event) if (event)
gst_event_unref (event); gst_event_unref (event);
gst_object_unref (dvdemux);
return res; return res;
} }
@ -1209,11 +1152,11 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer,
{ {
gint num_samples; gint num_samples;
GstFlowReturn ret; GstFlowReturn ret;
const guint8 *data; GstMapInfo map;
data = GST_BUFFER_DATA (buffer); gst_buffer_map (buffer, &map, GST_MAP_READ);
dv_decode_full_audio (dvdemux->decoder, map.data, dvdemux->audio_buffers);
dv_decode_full_audio (dvdemux->decoder, data, dvdemux->audio_buffers); gst_buffer_unmap (buffer, &map);
if (G_LIKELY ((num_samples = dv_get_num_samples (dvdemux->decoder)) > 0)) { if (G_LIKELY ((num_samples = dv_get_num_samples (dvdemux->decoder)) > 0)) {
gint16 *a_ptr; gint16 *a_ptr;
@ -1231,18 +1174,15 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer,
if (G_UNLIKELY ((frequency != dvdemux->frequency) if (G_UNLIKELY ((frequency != dvdemux->frequency)
|| (channels != dvdemux->channels))) { || (channels != dvdemux->channels))) {
GstCaps *caps; GstCaps *caps;
GstAudioInfo info;
dvdemux->frequency = frequency; dvdemux->frequency = frequency;
dvdemux->channels = channels; dvdemux->channels = channels;
/* and set new caps */ gst_audio_info_init (&info);
caps = gst_caps_new_simple ("audio/x-raw-int", gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16LE,
"rate", G_TYPE_INT, frequency, frequency, channels, NULL);
"depth", G_TYPE_INT, 16, caps = gst_audio_info_to_caps (&info);
"width", G_TYPE_INT, 16,
"signed", G_TYPE_BOOLEAN, TRUE,
"channels", G_TYPE_INT, channels,
"endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
gst_pad_set_caps (dvdemux->audiosrcpad, caps); gst_pad_set_caps (dvdemux->audiosrcpad, caps);
gst_caps_unref (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 * outbuf = gst_buffer_new_and_alloc (num_samples *
sizeof (gint16) * dvdemux->channels); 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 (i = 0; i < num_samples; i++) {
for (j = 0; j < dvdemux->channels; j++) { for (j = 0; j < dvdemux->channels; j++) {
*(a_ptr++) = dvdemux->audio_buffers[j][i]; *(a_ptr++) = dvdemux->audio_buffers[j][i];
} }
} }
gst_buffer_unmap (outbuf, &map);
GST_DEBUG ("pushing audio %" GST_TIME_FORMAT, 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_DURATION (outbuf) = duration;
GST_BUFFER_OFFSET (outbuf) = dvdemux->audio_offset; GST_BUFFER_OFFSET (outbuf) = dvdemux->audio_offset;
dvdemux->audio_offset += num_samples; dvdemux->audio_offset += num_samples;
@ -1269,7 +1211,6 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer,
if (dvdemux->new_media) if (dvdemux->new_media)
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); 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); ret = gst_pad_push (dvdemux->audiosrcpad, outbuf);
} else { } else {
@ -1337,19 +1278,18 @@ gst_dvdemux_demux_video (GstDVDemux * dvdemux, GstBuffer * buffer,
/* takes ownership of buffer here, we just need to modify /* takes ownership of buffer here, we just need to modify
* the metadata. */ * 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 (outbuf) = dvdemux->video_offset;
GST_BUFFER_OFFSET_END (outbuf) = dvdemux->video_offset + 1; GST_BUFFER_OFFSET_END (outbuf) = dvdemux->video_offset + 1;
GST_BUFFER_DURATION (outbuf) = duration; GST_BUFFER_DURATION (outbuf) = duration;
if (dvdemux->new_media) if (dvdemux->new_media)
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); 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_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); ret = gst_pad_push (dvdemux->videosrcpad, outbuf);
@ -1375,11 +1315,14 @@ static gboolean
gst_dvdemux_get_timecode (GstDVDemux * dvdemux, GstBuffer * buffer, gst_dvdemux_get_timecode (GstDVDemux * dvdemux, GstBuffer * buffer,
GstSMPTETimeCode * timecode) GstSMPTETimeCode * timecode)
{ {
guint8 *data = GST_BUFFER_DATA (buffer); guint8 *data;
GstMapInfo map;
int offset; int offset;
int dif; int dif;
int n_difs = dvdemux->decoder->num_dif_seqs; 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++) { for (dif = 0; dif < n_difs; dif++) {
offset = get_ssyb_offset (dif, 3); offset = get_ssyb_offset (dif, 3);
if (data[offset + 3] == 0x13) { if (data[offset + 3] == 0x13) {
@ -1393,23 +1336,28 @@ gst_dvdemux_get_timecode (GstDVDemux * dvdemux, GstBuffer * buffer,
(data[offset + 7] & 0xf); (data[offset + 7] & 0xf);
GST_DEBUG ("got timecode %" GST_SMPTE_TIME_CODE_FORMAT, GST_DEBUG ("got timecode %" GST_SMPTE_TIME_CODE_FORMAT,
GST_SMPTE_TIME_CODE_ARGS (timecode)); GST_SMPTE_TIME_CODE_ARGS (timecode));
gst_buffer_unmap (buffer, &map);
return TRUE; return TRUE;
} }
} }
gst_buffer_unmap (buffer, &map);
return FALSE; return FALSE;
} }
static gboolean static gboolean
gst_dvdemux_is_new_media (GstDVDemux * dvdemux, GstBuffer * buffer) gst_dvdemux_is_new_media (GstDVDemux * dvdemux, GstBuffer * buffer)
{ {
guint8 *data = GST_BUFFER_DATA (buffer); guint8 *data;
GstMapInfo map;
int aaux_offset; int aaux_offset;
int dif; int dif;
int n_difs; int n_difs;
n_difs = dvdemux->decoder->num_dif_seqs; 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++) { for (dif = 0; dif < n_difs; dif++) {
if (dif & 1) { if (dif & 1) {
aaux_offset = (dif * 12000) + (6 + 16 * 1) * 80 + 3; 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; aaux_offset = (dif * 12000) + (6 + 16 * 4) * 80 + 3;
} }
if (data[aaux_offset + 0] == 0x51) { 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; return TRUE;
} }
} }
}
gst_buffer_unmap (buffer, &map);
return FALSE; return FALSE;
} }
@ -1431,13 +1382,12 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer)
{ {
GstClockTime next_ts; GstClockTime next_ts;
GstFlowReturn aret, vret, ret; GstFlowReturn aret, vret, ret;
guint8 *data; GstMapInfo map;
guint64 duration; guint64 duration;
GstSMPTETimeCode timecode; GstSMPTETimeCode timecode;
int frame_number; int frame_number;
if (G_UNLIKELY (dvdemux->need_segment)) { if (G_UNLIKELY (dvdemux->need_segment)) {
GstEvent *event;
GstFormat format; GstFormat format;
/* convert to time and store as start/end_timestamp */ /* 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, if (!(gst_dvdemux_convert_sink_pair (dvdemux,
GST_FORMAT_BYTES, dvdemux->byte_segment.start, GST_FORMAT_BYTES, dvdemux->byte_segment.start,
dvdemux->byte_segment.stop, format, 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; goto segment_error;
dvdemux->time_segment.rate = dvdemux->byte_segment.rate; dvdemux->time_segment.rate = dvdemux->byte_segment.rate;
dvdemux->time_segment.abs_rate = dvdemux->byte_segment.abs_rate; dvdemux->time_segment.position = dvdemux->time_segment.start;
dvdemux->time_segment.last_stop = dvdemux->time_segment.start;
/* calculate current frame number */ /* calculate current frame number */
format = GST_FORMAT_DEFAULT; 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.stop),
GST_TIME_ARGS (dvdemux->time_segment.start)); GST_TIME_ARGS (dvdemux->time_segment.start));
event = gst_event_new_new_segment (FALSE, dvdemux->byte_segment.rate, gst_dvdemux_push_event (dvdemux,
GST_FORMAT_TIME, dvdemux->time_segment.start, gst_event_new_segment (&dvdemux->time_segment));
dvdemux->time_segment.stop, dvdemux->time_segment.start);
gst_dvdemux_push_event (dvdemux, event);
dvdemux->need_segment = FALSE; dvdemux->need_segment = FALSE;
} }
@ -1482,11 +1430,11 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer)
next_ts = gst_util_uint64_scale_int ( next_ts = gst_util_uint64_scale_int (
(dvdemux->frame_offset + 1) * GST_SECOND, (dvdemux->frame_offset + 1) * GST_SECOND,
dvdemux->framerate_denominator, dvdemux->framerate_numerator); dvdemux->framerate_denominator, dvdemux->framerate_numerator);
duration = next_ts - dvdemux->time_segment.last_stop; duration = next_ts - dvdemux->time_segment.position;
data = GST_BUFFER_DATA (buffer); gst_buffer_map (buffer, &map, GST_MAP_READ);
dv_parse_packs (dvdemux->decoder, map.data);
dv_parse_packs (dvdemux->decoder, data); gst_buffer_unmap (buffer, &map);
dvdemux->new_media = FALSE; dvdemux->new_media = FALSE;
if (gst_dvdemux_is_new_media (dvdemux, buffer) && if (gst_dvdemux_is_new_media (dvdemux, buffer) &&
dvdemux->frames_since_new_media > 2) { dvdemux->frames_since_new_media > 2) {
@ -1513,7 +1461,7 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer)
goto done; goto done;
} }
gst_segment_set_last_stop (&dvdemux->time_segment, GST_FORMAT_TIME, next_ts); dvdemux->time_segment.position = next_ts;
dvdemux->frame_offset++; dvdemux->frame_offset++;
/* check for the end of the segment */ /* check for the end of the segment */
@ -1545,11 +1493,14 @@ gst_dvdemux_flush (GstDVDemux * dvdemux)
gint length; gint length;
/* get the accumulated bytes */ /* 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 */ /* 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; goto parse_header_error;
}
gst_adapter_unmap (dvdemux->adapter);
/* after parsing the header we know the length of the data */ /* after parsing the header we know the length of the data */
length = dvdemux->frame_len = dvdemux->decoder->frame_size; 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)) { if (G_LIKELY (gst_adapter_available (dvdemux->adapter) >= length)) {
GstBuffer *buffer; GstBuffer *buffer;
data = gst_adapter_take (dvdemux->adapter, length); buffer = gst_adapter_take_buffer (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;
/* and decode the buffer, takes ownership */ /* and decode the buffer, takes ownership */
ret = gst_dvdemux_demux_frame (dvdemux, buffer); ret = gst_dvdemux_demux_frame (dvdemux, buffer);
@ -1600,13 +1545,13 @@ parse_header_error:
* accumulate data until we have a frame, then decode. * accumulate data until we have a frame, then decode.
*/ */
static GstFlowReturn static GstFlowReturn
gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer) gst_dvdemux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{ {
GstDVDemux *dvdemux; GstDVDemux *dvdemux;
GstFlowReturn ret; GstFlowReturn ret;
GstClockTime timestamp; 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 /* a discontinuity in the stream, we need to get rid of
* accumulated data in the adapter and assume a new frame * 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 */ /* a timestamp always should be respected */
timestamp = GST_BUFFER_TIMESTAMP (buffer); timestamp = GST_BUFFER_TIMESTAMP (buffer);
if (GST_CLOCK_TIME_IS_VALID (timestamp)) { if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
gst_segment_set_last_stop (&dvdemux->time_segment, GST_FORMAT_TIME, dvdemux->time_segment.position = timestamp;
timestamp);
/* FIXME, adjust frame_offset and other counters */ /* FIXME, adjust frame_offset and other counters */
} }
@ -1637,8 +1581,6 @@ gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer)
/* and try to flush pending frames */ /* and try to flush pending frames */
ret = gst_dvdemux_flush (dvdemux); ret = gst_dvdemux_flush (dvdemux);
gst_object_unref (dvdemux);
return ret; return ret;
} }
@ -1653,7 +1595,7 @@ gst_dvdemux_loop (GstPad * pad)
GstFlowReturn ret; GstFlowReturn ret;
GstDVDemux *dvdemux; GstDVDemux *dvdemux;
GstBuffer *buffer = NULL; GstBuffer *buffer = NULL;
const guint8 *data; GstMapInfo map;
dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad)); 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 /* pull in NTSC sized buffer to figure out the frame
* length */ * length */
ret = gst_pad_pull_range (dvdemux->sinkpad, 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)) if (G_UNLIKELY (ret != GST_FLOW_OK))
goto pause; goto pause;
/* check buffer size, don't want to read small buffers */ /* 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; 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 */ /* 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; goto parse_header_error;
}
gst_buffer_unmap (buffer, &map);
/* after parsing the header we know the length of the data */ /* after parsing the header we know the length of the data */
dvdemux->frame_len = dvdemux->decoder->frame_size; dvdemux->frame_len = dvdemux->decoder->frame_size;
@ -1736,15 +1680,15 @@ gst_dvdemux_loop (GstPad * pad)
if (G_LIKELY (buffer == NULL)) { if (G_LIKELY (buffer == NULL)) {
GST_DEBUG_OBJECT (dvdemux, "pulling buffer at offset %" G_GINT64_FORMAT, 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, 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) if (ret != GST_FLOW_OK)
goto pause; goto pause;
/* check buffer size, don't want to read small buffers */ /* 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; goto small_buffer;
} }
/* and decode the buffer */ /* and decode the buffer */
@ -1753,7 +1697,7 @@ gst_dvdemux_loop (GstPad * pad)
goto pause; goto pause;
/* and position ourselves for the next buffer */ /* and position ourselves for the next buffer */
dvdemux->byte_segment.last_stop += dvdemux->frame_len; dvdemux->byte_segment.position += dvdemux->frame_len;
done: done:
gst_object_unref (dvdemux); gst_object_unref (dvdemux);
@ -1766,7 +1710,6 @@ parse_header_error:
GST_ELEMENT_ERROR (dvdemux, STREAM, DECODE, GST_ELEMENT_ERROR (dvdemux, STREAM, DECODE,
(NULL), ("Error parsing DV header")); (NULL), ("Error parsing DV header"));
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
dvdemux->running = FALSE;
gst_pad_pause_task (dvdemux->sinkpad); gst_pad_pause_task (dvdemux->sinkpad);
gst_dvdemux_push_event (dvdemux, gst_event_new_eos ()); gst_dvdemux_push_event (dvdemux, gst_event_new_eos ());
goto done; goto done;
@ -1776,7 +1719,6 @@ small_buffer:
GST_ELEMENT_ERROR (dvdemux, STREAM, DECODE, GST_ELEMENT_ERROR (dvdemux, STREAM, DECODE,
(NULL), ("Error reading buffer")); (NULL), ("Error reading buffer"));
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
dvdemux->running = FALSE;
gst_pad_pause_task (dvdemux->sinkpad); gst_pad_pause_task (dvdemux->sinkpad);
gst_dvdemux_push_event (dvdemux, gst_event_new_eos ()); gst_dvdemux_push_event (dvdemux, gst_event_new_eos ());
goto done; goto done;
@ -1784,15 +1726,21 @@ small_buffer:
pause: pause:
{ {
GST_INFO_OBJECT (dvdemux, "pausing task, %s", gst_flow_get_name (ret)); GST_INFO_OBJECT (dvdemux, "pausing task, %s", gst_flow_get_name (ret));
dvdemux->running = FALSE;
gst_pad_pause_task (dvdemux->sinkpad); gst_pad_pause_task (dvdemux->sinkpad);
if (ret == GST_FLOW_EOS) { if (ret == GST_FLOW_EOS) {
GST_LOG_OBJECT (dvdemux, "got 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 */ /* perform EOS logic */
if (dvdemux->time_segment.flags & GST_SEEK_FLAG_SEGMENT) { if (dvdemux->time_segment.flags & GST_SEEK_FLAG_SEGMENT) {
gst_element_post_message (GST_ELEMENT (dvdemux), gst_element_post_message (GST_ELEMENT (dvdemux),
gst_message_new_segment_done (GST_OBJECT_CAST (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 { } else {
gst_dvdemux_push_event (dvdemux, gst_event_new_eos ()); gst_dvdemux_push_event (dvdemux, gst_event_new_eos ());
} }
@ -1807,53 +1755,69 @@ pause:
} }
static gboolean 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)); gboolean res;
GstDVDemux *demux = GST_DVDEMUX (parent);
switch (mode) {
case GST_PAD_MODE_PULL:
if (active) { 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; demux->seek_handler = gst_dvdemux_handle_push_seek;
} else { } else {
GST_DEBUG_OBJECT (demux, "deactivating push/chain function");
demux->seek_handler = NULL; demux->seek_handler = NULL;
} }
gst_object_unref (demux); res = TRUE;
break;
return TRUE; default:
res = FALSE;
break;
} }
return res;
static gboolean
gst_dvdemux_sink_activate_pull (GstPad * sinkpad, gboolean active)
{
GstDVDemux *demux = GST_DVDEMUX (gst_pad_get_parent (sinkpad));
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;
} }
gst_object_unref (demux);
return TRUE;
};
/* decide on push or pull based scheduling */ /* decide on push or pull based scheduling */
static gboolean static gboolean
gst_dvdemux_sink_activate (GstPad * sinkpad) gst_dvdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
{ {
gboolean ret; GstQuery *query;
gboolean pull_mode;
if (gst_pad_check_pull_range (sinkpad)) query = gst_query_new_scheduling ();
ret = gst_pad_activate_pull (sinkpad, TRUE);
else
ret = gst_pad_activate_push (sinkpad, TRUE);
return ret; if (!gst_pad_peer_query (sinkpad, query)) {
}; gst_query_unref (query);
goto activate_push;
}
pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
gst_query_unref (query);
if (!pull_mode)
goto activate_push;
GST_DEBUG_OBJECT (sinkpad, "activating pull");
return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
activate_push:
{
GST_DEBUG_OBJECT (sinkpad, "activating push");
return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
}
}
static GstStateChangeReturn static GstStateChangeReturn
gst_dvdemux_change_state (GstElement * element, GstStateChange transition) gst_dvdemux_change_state (GstElement * element, GstStateChange transition)
@ -1875,7 +1839,7 @@ gst_dvdemux_change_state (GstElement * element, GstStateChange transition)
break; break;
} }
ret = parent_class->change_state (element, transition); ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) { switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED: case GST_STATE_CHANGE_PLAYING_TO_PAUSED:

View file

@ -75,7 +75,6 @@ struct _GstDVDemux {
GstDVDemuxSeekHandler seek_handler; GstDVDemuxSeekHandler seek_handler;
GstSegment byte_segment; GstSegment byte_segment;
GstSegment time_segment; GstSegment time_segment;
gboolean running;
gboolean need_segment; gboolean need_segment;
gboolean new_media; gboolean new_media;
int frames_since_new_media; int frames_since_new_media;