mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
dv: port to 0.11
This commit is contained in:
parent
92a0c01732
commit
9be8a6f48c
6 changed files with 369 additions and 366 deletions
|
@ -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 "
|
||||
|
|
|
@ -3,7 +3,7 @@ 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_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
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/video/gstvideopool.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",
|
||||
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);
|
||||
|
@ -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,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void
|
||||
gst_dvdec_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_temp));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_temp));
|
||||
|
||||
gst_element_class_set_details_simple (element_class, "DV video decoder",
|
||||
"Codec/Decoder/Video",
|
||||
"Uses libdv to decode DV video (smpte314) (libdv.sourceforge.net)",
|
||||
"Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (dvdec_debug, "dvdec", 0, "DV decoding element");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_dvdec_class_init (GstDVDecClass * klass)
|
||||
{
|
||||
|
@ -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 <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (dvdec_debug, "dvdec", 0, "DV decoding element");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_dvdec_init (GstDVDec * dvdec, GstDVDecClass * g_class)
|
||||
gst_dvdec_init (GstDVDec * dvdec)
|
||||
{
|
||||
dvdec->sinkpad = gst_pad_new_from_static_template (&sink_temp, "sink");
|
||||
gst_pad_set_setcaps_function (dvdec->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_dvdec_sink_setcaps));
|
||||
gst_pad_set_chain_function (dvdec->sinkpad, gst_dvdec_chain);
|
||||
gst_pad_set_event_function (dvdec->sinkpad, gst_dvdec_sink_event);
|
||||
gst_element_add_pad (GST_ELEMENT (dvdec), dvdec->sinkpad);
|
||||
|
@ -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;
|
||||
case GST_EVENT_SEGMENT:{
|
||||
const GstSegment *segment;
|
||||
|
||||
gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
|
||||
&format, &start, &stop, &position);
|
||||
gst_event_parse_segment (event, &segment);
|
||||
|
||||
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_DEBUG_OBJECT (dvdec, "Got NEWSEGMENT %" GST_SEGMENT_FORMAT, &segment);
|
||||
|
||||
gst_segment_set_newsegment_full (dvdec->segment, update, rate,
|
||||
applied_rate, format, start, stop, position);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
#include <libdv/dv.h>
|
||||
|
||||
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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,43 +151,25 @@ 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 <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (dvdemux_debug, "dvdemux", 0, "DV demuxer element");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_dvdemux_class_init (GstDVDemuxClass * klass)
|
||||
{
|
||||
|
@ -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 <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (dvdemux_debug, "dvdemux", 0, "DV demuxer element");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_dvdemux_init (GstDVDemux * dvdemux, GstDVDemuxClass * g_class)
|
||||
gst_dvdemux_init (GstDVDemux * dvdemux)
|
||||
{
|
||||
gint i;
|
||||
|
||||
|
@ -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;
|
||||
const GstSegment *segment;
|
||||
|
||||
/* parse byte start and stop positions */
|
||||
gst_event_parse_new_segment (event, &update, &rate, &format,
|
||||
&start, &stop, &time);
|
||||
|
||||
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;
|
||||
duration = next_ts - dvdemux->time_segment.position;
|
||||
|
||||
data = GST_BUFFER_DATA (buffer);
|
||||
|
||||
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));
|
||||
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;
|
||||
}
|
||||
gst_object_unref (demux);
|
||||
|
||||
return TRUE;
|
||||
res = TRUE;
|
||||
break;
|
||||
default:
|
||||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
return res;
|
||||
}
|
||||
|
||||
gst_object_unref (demux);
|
||||
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
/* decide on push or pull based scheduling */
|
||||
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))
|
||||
ret = gst_pad_activate_pull (sinkpad, TRUE);
|
||||
else
|
||||
ret = gst_pad_activate_push (sinkpad, TRUE);
|
||||
query = gst_query_new_scheduling ();
|
||||
|
||||
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
|
||||
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:
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue