dnl our libraries and install dirs use major.minor as a version
GST_MAJORMINOR=$GST_PLUGINS_BAD_VERSION_MAJOR.$GST_PLUGINS_BAD_VERSION_MINOR
dnl we override it here if we need to for the release candidate of new series
-GST_MAJORMINOR=0.10
+GST_MAJORMINOR=0.11
AC_SUBST(GST_MAJORMINOR)
+ dnl CURRENT, REVISION, AGE
+ dnl - library source changed -> increment REVISION
+ dnl - interfaces added/removed/changed -> increment CURRENT, REVISION = 0
+ dnl - interfaces added -> increment AGE
+ dnl - interfaces removed -> AGE = 0
+ dnl sets GST_LT_LDFLAGS
+ AS_LIBTOOL(GST, 24, 0, 0)
+
AG_GST_LIBTOOL_PREPARE
dnl FIXME: this macro doesn't actually work;
AM_PROG_LIBTOOL
dnl *** required versions of GStreamer stuff ***
++<<<<<<< HEAD
+GST_REQ=0.11.3
+GSTPB_REQ=0.11.3
++=======
+ GST_REQ=0.10.36
+ GSTPB_REQ=0.10.36
++>>>>>>> origin/0.10
dnl *** autotools stuff ****
gint * offset, gint * length);
static GstFlowReturn gst_dtsdec_handle_frame (GstAudioDecoder * dec,
GstBuffer * buffer);
- static GstFlowReturn gst_dtsdec_pre_push (GstAudioDecoder * bdec,
- GstBuffer ** buffer);
-static GstFlowReturn gst_dtsdec_chain (GstPad * pad, GstBuffer * buf);
+static GstFlowReturn gst_dtsdec_chain (GstPad * pad, GstObject * parent,
+ GstBuffer * buf);
static void gst_dtsdec_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
/* set up modplug to output the negotiated format */
structure = gst_caps_get_structure (newcaps, 0);
- gst_structure_get_int (structure, "depth", &modplug->bits);
+ format = gst_structure_get_string (structure, "format");
+
+ if (g_str_equal (format, GST_AUDIO_NE (S32)))
+ modplug->bits = 32;
+ else if (g_str_equal (format, GST_AUDIO_NE (S16)))
+ modplug->bits = 16;
+ else
+ modplug->bits = 8;
+
gst_structure_get_int (structure, "channels", &modplug->channel);
gst_structure_get_int (structure, "rate", &modplug->frequency);
+
+ GST_DEBUG_OBJECT (modplug,
+ "Audio settings: %d bits, %d channel(s), %d Hz sampling rate",
+ modplug->bits, modplug->channel, modplug->frequency);
gst_pad_set_caps (modplug->srcpad, newcaps);
gst_caps_unref (newcaps);
/* actually load it */
if (modplug->offset == modplug->song_size) {
- GstEvent *newsegment;
GstTagList *tags;
gboolean ok;
- gchar comment[16384];
+ #define COMMENT_SIZE 16384
+ gchar comment[COMMENT_SIZE];
+ GstSegment seg;
ok = gst_modplug_load_song (modplug);
gst_buffer_unref (modplug->buffer);
}
/* read and output a buffer */
- out = gst_buffer_new_allocate (NULL, modplug->read_bytes, NULL);
+ GST_LOG_OBJECT (modplug, "Read %d bytes", (gint)modplug->read_bytes);
+ /* libmodplug 0.8.7 trashes memory */
- flow = gst_pad_alloc_buffer_and_set_caps (modplug->srcpad,
- GST_BUFFER_OFFSET_NONE, modplug->read_bytes * 2,
- GST_PAD_CAPS (modplug->srcpad), &out);
- GST_BUFFER_SIZE (out) = modplug->read_bytes;
++ out = gst_buffer_new_allocate (NULL, modplug->read_bytes * 2, NULL);
- if (flow != GST_FLOW_OK) {
- GST_LOG_OBJECT (modplug, "pad alloc flow: %s", gst_flow_get_name (flow));
- goto pause;
- }
-
- if (!modplug->mSoundFile->Read (GST_BUFFER_DATA (out), modplug->read_bytes))
+ gst_buffer_map (out, &map, GST_MAP_WRITE);
+ if (!modplug->mSoundFile->Read (map.data, modplug->read_bytes)) {
+ gst_buffer_unmap (out, &map);
goto eos;
+ }
+ gst_buffer_unmap (out, &map);
++ gst_buffer_resize (out, 0, modplug->read_bytes);
- GST_BUFFER_SIZE (out) = modplug->read_bytes;
GST_BUFFER_DURATION (out) =
gst_util_uint64_scale_int (modplug->read_samples, GST_SECOND,
modplug->frequency);
static GstFlowReturn
gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
{
- guint8 *bdata, *data, *mdata = NULL;
+ guint8 *bdata = NULL, *data, *mdata = NULL;
gsize bsize, size;
- gsize bytes;
+ gsize bytes = enc->frame_samples * enc->n_channels * 2;
gint ret = GST_FLOW_OK;
+ GstMapInfo map;
++ GstMapInfo omap;
+ gint outsize;
+ GstBuffer *outbuf;
g_mutex_lock (enc->property_lock);
goto done;
}
- while (size) {
- gint encoded_size;
- GstBuffer *outbuf;
- GstMapInfo omap;
-
- outbuf = gst_buffer_new_and_alloc (enc->max_payload_size * enc->n_channels);
- if (!outbuf)
- goto done;
-
- GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)",
- enc->frame_samples, (int) bytes);
-
- gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);
- encoded_size =
- opus_multistream_encode (enc->state, (const gint16 *) data,
- enc->frame_samples, omap.data, enc->max_payload_size * enc->n_channels);
- gst_buffer_unmap (outbuf, &omap);
-
- if (encoded_size < 0) {
- GST_ERROR_OBJECT (enc, "Encoding failed: %d", encoded_size);
- ret = GST_FLOW_ERROR;
- goto done;
- } else if (encoded_size > enc->max_payload_size) {
- GST_WARNING_OBJECT (enc,
- "Encoded size %d is higher than max payload size (%d bytes)",
- encoded_size, enc->max_payload_size);
- ret = GST_FLOW_ERROR;
- goto done;
- }
+ g_assert (size == bytes);
+
- ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc),
- GST_BUFFER_OFFSET_NONE, enc->max_payload_size * enc->n_channels,
- GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf);
-
- if (GST_FLOW_OK != ret)
++ outbuf = gst_buffer_new_and_alloc (enc->max_payload_size * enc->n_channels);
++ if (!outbuf)
+ goto done;
+
++ GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)",
++ enc->frame_samples, (int) bytes);
++
++ gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);
+
- GST_DEBUG_OBJECT (enc, "Output packet is %u bytes", encoded_size);
- gst_buffer_set_size (outbuf, encoded_size);
+ GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)",
+ enc->frame_samples, (int) bytes);
- ret =
- gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc), outbuf,
- enc->frame_samples);
+ outsize =
+ opus_multistream_encode (enc->state, (const gint16 *) data,
+ enc->frame_samples, GST_BUFFER_DATA (outbuf),
+ enc->max_payload_size * enc->n_channels);
- if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret))
- goto done;
++ gst_buffer_unmap (outbuf, &omap);
+
- data += bytes;
- size -= bytes;
+ if (outsize < 0) {
+ GST_ERROR_OBJECT (enc, "Encoding failed: %d", outsize);
+ ret = GST_FLOW_ERROR;
+ goto done;
+ } else if (outsize > enc->max_payload_size) {
+ GST_WARNING_OBJECT (enc,
+ "Encoded size %d is higher than max payload size (%d bytes)",
+ outsize, enc->max_payload_size);
+ ret = GST_FLOW_ERROR;
+ goto done;
}
+ GST_DEBUG_OBJECT (enc, "Output packet is %u bytes", outsize);
+ GST_BUFFER_SIZE (outbuf) = outsize;
+
+ ret =
+ gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc), outbuf,
+ enc->frame_samples);
+
done:
+ if (bdata)
+ gst_buffer_unmap (buf, &map);
g_mutex_unlock (enc->property_lock);
if (mdata)
if (frame->coder_hook_destroy_notify && frame->coder_hook)
frame->coder_hook_destroy_notify (frame->coder_hook);
- g_slice_free (GstVideoFrame, frame);
+ g_slice_free (GstVideoFrameState, frame);
+}
+
+/**
+ * gst_base_video_codec_new_frame:
+ * @base_video_codec: a #GstBaseVideoCodec
+ *
+ * Creates a new #GstVideoFrameState for usage in decoders or encoders.
+ *
+ * Returns: (transfer full): The new #GstVideoFrameState, call
+ * #gst_video_frame_state_unref() when done with it.
+ */
+GstVideoFrameState *
+gst_base_video_codec_new_frame (GstBaseVideoCodec * base_video_codec)
+{
+ GstVideoFrameState *frame;
+
+ frame = g_slice_new0 (GstVideoFrameState);
+
+ frame->ref_count = 1;
+
+ GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_codec);
+ frame->system_frame_number = base_video_codec->system_frame_number;
+ base_video_codec->system_frame_number++;
+ GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_codec);
+
+ GST_LOG_OBJECT (base_video_codec, "Created new frame %p (sfn:%d)",
+ frame, frame->system_frame_number);
+
+ return frame;
}
- * gst_video_frame_ref:
- * @frame: a #GstVideoFrame
+ /**
-GstVideoFrame *
-gst_video_frame_ref (GstVideoFrame * frame)
++ * gst_video_frame_state_ref:
++ * @frame: a #GstVideoFrameState
+ *
+ * Increases the refcount of the given frame by one.
+ *
+ * Returns: @buf
+ */
+GstVideoFrameState *
+gst_video_frame_state_ref (GstVideoFrameState * frame)
{
g_return_val_if_fail (frame != NULL, NULL);
return frame;
}
- * gst_video_frame_unref:
- * @frame: a #GstVideoFrame
+ /**
++ * gst_video_frame_state_unref:
++ * @frame: a #GstVideoFrameState
+ *
+ * Decreases the refcount of the frame. If the refcount reaches 0, the frame
+ * will be freed.
+ */
void
-gst_video_frame_unref (GstVideoFrame * frame)
+gst_video_frame_state_unref (GstVideoFrameState * frame)
{
g_return_if_fail (frame != NULL);
g_return_if_fail (frame->ref_count > 0);
*/
#define GST_BASE_VIDEO_CODEC_FLOW_NEED_DATA GST_FLOW_CUSTOM_SUCCESS
-#define GST_BASE_VIDEO_CODEC_STREAM_LOCK(codec) g_static_rec_mutex_lock (&GST_BASE_VIDEO_CODEC (codec)->stream_lock)
+ /**
+ * GST_BASE_VIDEO_CODEC_STREAM_LOCK:
+ * @codec: video codec instance
+ *
+ * Obtain a lock to protect the codec function from concurrent access.
+ *
+ * Since: 0.10.22
+ */
-#define GST_BASE_VIDEO_CODEC_STREAM_UNLOCK(codec) g_static_rec_mutex_unlock (&GST_BASE_VIDEO_CODEC (codec)->stream_lock)
+#define GST_BASE_VIDEO_CODEC_STREAM_LOCK(codec) g_rec_mutex_lock (&GST_BASE_VIDEO_CODEC (codec)->stream_lock)
+ /**
+ * GST_BASE_VIDEO_CODEC_STREAM_UNLOCK:
+ * @codec: video codec instance
+ *
+ * Release the lock that protects the codec function from concurrent access.
+ *
+ * Since: 0.10.22
+ */
+#define GST_BASE_VIDEO_CODEC_STREAM_UNLOCK(codec) g_rec_mutex_unlock (&GST_BASE_VIDEO_CODEC (codec)->stream_lock)
typedef struct _GstVideoState GstVideoState;
-typedef struct _GstVideoFrame GstVideoFrame;
+typedef struct _GstVideoFrameState GstVideoFrameState;
typedef struct _GstBaseVideoCodec GstBaseVideoCodec;
typedef struct _GstBaseVideoCodecClass GstBaseVideoCodecClass;
/* protects all data processing, i.e. is locked
* in the chain function, finish_frame and when
* processing serialized events */
- GStaticRecMutex stream_lock;
+ GRecMutex stream_lock;
- guint64 system_frame_number;
+ guint64 system_frame_number;
- GList *frames; /* Protected with OBJECT_LOCK */
- GstVideoState state;
- GstSegment segment;
+ GList *frames; /* Protected with OBJECT_LOCK */
+ GstVideoState state; /* Compressed video pad */
+ GstVideoInfo info; /* Raw video pad */
+ GstSegment segment;
- gdouble proportion;
- GstClockTime earliest_time;
- gboolean discont;
+ /* QoS properties */
+ gdouble proportion;
+ GstClockTime earliest_time;
+ gboolean discont;
- gint64 bytes;
- gint64 time;
+ gint64 bytes;
+ gint64 time;
/* FIXME before moving to base */
- void *padding[GST_PADDING_LARGE];
+ void *padding[GST_PADDING_LARGE];
};
+ /**
+ * GstBaseVideoCodecClass:
+ *
+ * The opaque #GstBaseVideoCodecClass data structure.
+ */
struct _GstBaseVideoCodecClass
{
+ /*< private >*/
GstElementClass element_class;
/* FIXME before moving to base */
}
/**
- * gst_base_video_decoder_finish_frame:
+ * gst_base_video_decoder_add_to_frame:
* @base_video_decoder: a #GstBaseVideoDecoder
- * @n_bytes: an encoded #GstVideoFrame
+ * @n_bytes: an encoded #GstVideoFrameState
*
* Removes next @n_bytes of input data and adds it to currently parsed frame.
*/
* gst_base_video_decoder_get_oldest_frame:
* @base_video_decoder: a #GstBaseVideoDecoder
*
- * Get the oldest pending unfinished #GstVideoFrame
++ * Get the oldest pending unfinished #GstVideoFrameState
+ *
- * Returns: oldest pending unfinished #GstVideoFrame.
+ * Returns: oldest pending unfinished #GstVideoFrameState.
*/
-GstVideoFrame *
+GstVideoFrameState *
gst_base_video_decoder_get_oldest_frame (GstBaseVideoDecoder *
base_video_decoder)
{
* @base_video_decoder: a #GstBaseVideoDecoder
* @frame_number: system_frame_number of a frame
*
- * Get a pending unfinished #GstVideoFrame
- *
- * Returns: pending unfinished #GstVideoFrame identified by @frame_number.
++ * Get a pending unfinished #GstVideoFrameState
++ *
+ * Returns: pending unfinished #GstVideoFrameState identified by @frame_number.
*/
-GstVideoFrame *
+GstVideoFrameState *
gst_base_video_decoder_get_frame (GstBaseVideoDecoder * base_video_decoder,
int frame_number)
{
* gst_base_video_decoder_set_src_caps:
* @base_video_decoder: a #GstBaseVideoDecoder
*
-- * Sets src pad caps according to currently configured #GstVideoState.
- *
+ * The #GstVideoInfo and #GstBufferPool will be created and negotiated
+ * according to those values.
*
- * Returns: #TRUE if the caps were accepted downstream, else #FALSE.
+ * Returns: %TRUE if the format was properly negotiated, else %FALSE.
*/
gboolean
gst_base_video_decoder_set_src_caps (GstBaseVideoDecoder * base_video_decoder)
* gst_base_video_decoder_alloc_src_buffer:
* @base_video_decoder: a #GstBaseVideoDecoder
*
- * Helper function that uses @gst_pad_alloc_buffer_and_set_caps()
- * to allocate a buffer to hold a video frame for @base_video_decoder's
- * current #GstVideoState.
+ * Helper function that returns a buffer from the decoders' configured
+ * #GstBufferPool.
*
- * Returns: allocated buffer
+ * Returns: (transfer full): allocated buffer
*/
GstBuffer *
gst_base_video_decoder_alloc_src_buffer (GstBaseVideoDecoder *
/**
* gst_base_video_decoder_alloc_src_frame:
* @base_video_decoder: a #GstBaseVideoDecoder
- * @frame: a #GstVideoFrame
+ * @frame: a #GstVideoFrameState
*
- * Helper function that uses gst_pad_alloc_buffer_and_set_caps
+ * Helper function that uses @gst_pad_alloc_buffer_and_set_caps()
* to allocate a buffer to hold a video frame for @base_video_decoder's
* current #GstVideoState. Subclass should already have configured video state
* and set src pad caps.
void *padding[GST_PADDING_LARGE];
};
- void gst_base_video_decoder_class_set_capture_pattern (GstBaseVideoDecoderClass *klass,
+ void gst_base_video_decoder_class_set_capture_pattern (GstBaseVideoDecoderClass *base_video_decoder_class,
guint32 mask, guint32 pattern);
-GstVideoFrame *gst_base_video_decoder_get_frame (GstBaseVideoDecoder *base_video_decoder,
+GstVideoFrameState *gst_base_video_decoder_get_frame (GstBaseVideoDecoder *coder,
int frame_number);
-GstVideoFrame *gst_base_video_decoder_get_oldest_frame (GstBaseVideoDecoder *base_video_decoder);
+GstVideoFrameState *gst_base_video_decoder_get_oldest_frame (GstBaseVideoDecoder *coder);
void gst_base_video_decoder_add_to_frame (GstBaseVideoDecoder *base_video_decoder,
int n_bytes);
* gst_base_video_encoder_get_oldest_frame:
* @base_video_encoder: a #GstBaseVideoEncoder
*
- * Get the oldest unfinished pending #GstVideoFrame
++ * Get the oldest unfinished pending #GstVideoFrameState
+ *
- * Returns: oldest unfinished pending #GstVideoFrame
+ * Returns: oldest unfinished pending #GstVideoFrameState
*/
-GstVideoFrame *
+GstVideoFrameState *
gst_base_video_encoder_get_oldest_frame (GstBaseVideoEncoder *
base_video_encoder)
{
* Allows closing external resources.
* @set_format: Optional.
* Notifies subclass of incoming data format.
- * GstVideoState fields have already been
+ * GstVideoInfo fields have already been
* set according to provided caps.
* @handle_frame: Provides input frame to subclass.
+ * @reset: Optional.
+ * Allows subclass (codec) to perform post-seek semantics reset.
* @finish: Optional.
* Called to request subclass to dispatch any pending remaining
* data (e.g. at EOS).
GType gst_base_video_encoder_get_type (void);
- const GstVideoState* gst_base_video_encoder_get_state (GstBaseVideoEncoder *coder);
+ const GstVideoState* gst_base_video_encoder_get_state (GstBaseVideoEncoder *base_video_encoder);
-GstVideoFrame* gst_base_video_encoder_get_oldest_frame (GstBaseVideoEncoder *base_video_encoder);
+GstVideoFrameState* gst_base_video_encoder_get_oldest_frame (GstBaseVideoEncoder *coder);
GstFlowReturn gst_base_video_encoder_finish_frame (GstBaseVideoEncoder *base_video_encoder,
- GstVideoFrame *frame);
+ GstVideoFrameState *frame);
void gst_base_video_encoder_set_latency (GstBaseVideoEncoder *base_video_encoder,
GstClockTime min_latency, GstClockTime max_latency);
# flags used to compile this plugin
# add other _CFLAGS and _LIBS as needed
-libgstadpcmdec_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
+libgstadpcmdec_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
- libgstadpcmdec_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) -lgstaudio-@GST_MAJORMINOR@ \
- $(GST_LIBS)
+ libgstadpcmdec_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) -lgstaudio-@GST_MAJORMINOR@ \
+ $(GST_BASE_LIBS) $(GST_LIBS)
libgstadpcmdec_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstadpcmdec_la_LIBTOOLFLAGS = --tag=disable-static
/* we want to take less or more, depending on spf : req_spf */
if (avail - sbpf >= sbpf) {
gst_adapter_flush (scope->adapter, sbpf);
- } else if (avail - sbpf >= 0) {
+ gst_adapter_unmap (scope->adapter);
+ } else if (avail >= sbpf) {
/* just flush a bit and stop */
gst_adapter_flush (scope->adapter, (avail - sbpf));
+ gst_adapter_unmap (scope->adapter);
break;
}
avail = gst_adapter_available (scope->adapter);
"Overlays SVG graphics over a detected face in a video stream",
"Laura Lucas Alday <lauralucas@gmail.com>");
- gst_element_class_add_static_pad_template (element_class, &src_factory);
- gst_element_class_add_static_pad_template (element_class, &sink_factory);
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&src_factory));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&sink_factory));
}
- /* initialize the faceoverlay's class */
- /* the _class_init() function is used to initialise the class only once
- * (specifying what signals, arguments and virtual functions the class has and
- * setting up global state) */
static void
gst_face_overlay_class_init (GstFaceOverlayClass * klass)
{
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
- gst_element_class_add_static_pad_template (element_class,
- &gst_inter_audio_sink_sink_template);
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_inter_audio_sink_sink_template));
- gst_element_class_set_details_simple (element_class, "FIXME Long name",
- "Generic", "FIXME Description", "FIXME <fixme@example.com>");
+ gst_element_class_set_details_simple (element_class,
+ "Internal audio sink",
+ "Sink/Audio",
+ "Virtual audio sink for internal process communication",
+ "David Schleef <ds@schleef.org>");
}
static void
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
- gst_element_class_add_static_pad_template (element_class,
- &gst_inter_audio_src_src_template);
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_inter_audio_src_src_template));
- gst_element_class_set_details_simple (element_class, "FIXME Long name",
- "Generic", "FIXME Description", "FIXME <fixme@example.com>");
+ gst_element_class_set_details_simple (element_class,
+ "Internal audio source",
+ "Source/Audio",
+ "Virtual audio source for internal process communication",
+ "David Schleef <ds@schleef.org>");
}
static void
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
- gst_element_class_add_static_pad_template (element_class,
- &gst_inter_video_sink_sink_template);
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_inter_video_sink_sink_template));
- gst_element_class_set_details_simple (element_class, "FIXME Long name",
- "Generic", "FIXME Description", "FIXME <fixme@example.com>");
+ gst_element_class_set_details_simple (element_class,
+ "Internal video sink",
+ "Sink/Video",
+ "Virtual video sink for internal process communication",
+ "David Schleef <ds@schleef.org>");
}
static void
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
- gst_element_class_add_static_pad_template (element_class,
- &gst_inter_video_src_src_template);
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_inter_video_src_src_template));
- gst_element_class_set_details_simple (element_class, "FIXME Long name",
- "Generic", "FIXME Description", "FIXME <fixme@example.com>");
+ gst_element_class_set_details_simple (element_class,
+ "Internal video source",
+ "Source/Video",
+ "Virtual video source for internal process communication",
+ "David Schleef <ds@schleef.org>");
}
static void
base->mode = BASE_MODE_STREAMING;
base->seen_pat = FALSE;
- base->first_pat_offset = -1;
- base->in_gap = 0;
- base->first_buf_ts = GST_CLOCK_TIME_NONE;
+ base->seek_offset = -1;
+
+ base->upstream_live = FALSE;
+ base->queried_latency = FALSE;
+ base->upstream_live = FALSE;
+ base->query_latency = FALSE;
+
if (klass->reset)
klass->reset (base);
}
gst_event_type_get_name (GST_EVENT_TYPE (event)));
switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_NEWSEGMENT:
- {
- gboolean update;
- gdouble rate, applied_rate;
- GstFormat format;
- gint64 start, stop, position;
-
- gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
- &format, &start, &stop, &position);
- GST_DEBUG_OBJECT (base,
- "Segment update:%d, rate:%f, applied_rate:%f, format:%s", update,
- rate, applied_rate, gst_format_get_name (format));
- GST_DEBUG_OBJECT (base,
- " start:%" G_GINT64_FORMAT ", stop:%" G_GINT64_FORMAT
- ", position:%" G_GINT64_FORMAT, start, stop, position);
- gst_segment_set_newsegment_full (&base->segment, update, rate,
- applied_rate, format, start, stop, position);
+ case GST_EVENT_SEGMENT:
- {
+ gst_event_copy_segment (event, &base->segment);
+
gst_event_unref (event);
-
- base->in_gap = GST_CLOCK_TIME_NONE;
- base->first_buf_ts = GST_CLOCK_TIME_NONE;
-- }
break;
case GST_EVENT_EOS:
res = gst_mpegts_base_handle_eos (base);
MpegTSPacketizer2 *packetizer;
MpegTSPacketizerPacket packet;
- base = GST_MPEGTS_BASE (gst_object_get_parent (GST_OBJECT (pad)));
+ base = GST_MPEGTS_BASE (parent);
packetizer = base->packetizer;
- if (G_UNLIKELY (base->query_latency == FALSE)) {
+ if (G_UNLIKELY (base->queried_latency == FALSE)) {
query_upstream_latency (base);
}
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (base->first_buf_ts)) &&
- GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
- base->first_buf_ts = GST_BUFFER_TIMESTAMP (buf);
- GST_DEBUG_OBJECT (base, "first buffer timestamp %" GST_TIME_FORMAT,
- GST_TIME_ARGS (base->first_buf_ts));
- }
-
mpegts_packetizer_push (base->packetizer, buf);
- while (((pret = mpegts_packetizer_next_packet (base->packetizer,
- &packet)) != PACKET_NEED_MORE) && res == GST_FLOW_OK) {
+
+ while (res == GST_FLOW_OK) {
+ pret = mpegts_packetizer_next_packet (base->packetizer, &packet);
+
+ /* If we don't have enough data, return */
+ if (G_UNLIKELY (pret == PACKET_NEED_MORE))
+ break;
+
+ /* bad header, skip the packet */
if (G_UNLIKELY (pret == PACKET_BAD))
- /* bad header, skip the packet */
goto next;
+ GST_DEBUG ("Got packet (buffer:%p)", packet.buffer);
+
/* base PSI data */
if (packet.payload != NULL && mpegts_base_is_psi (base, &packet)) {
MpegTSPacketizerSection section;
}
}
- GST_WARNING ("Didn't find initial sync point");
- ret = GST_FLOW_ERROR;
-
beach:
+ GST_DEBUG ("Returning %s", gst_flow_get_name (ret));
mpegts_packetizer_clear (base->packetizer);
return ret;
error:
{
const gchar *reason = gst_flow_get_name (ret);
+
GST_DEBUG_OBJECT (base, "Pausing task, reason %s", reason);
- if (ret == GST_FLOW_EOS)
- GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, gst_event_new_eos ());
- else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
- if (ret == GST_FLOW_UNEXPECTED) {
++ if (ret == GST_FLOW_EOS) {
+ /* Push EOS downstream */
+ if (!GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base,
+ gst_event_new_eos ())) {
+ /* If that failed, emit an error so the pipeline can be stopped */
+ GST_ELEMENT_ERROR (base, STREAM, DEMUX, (NULL),
+ ("got eos but no streams (yet)"));
+
+ }
- } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
++ } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
GST_ELEMENT_ERROR (base, STREAM, FAILED,
(_("Internal data stream error.")),
("stream stopped, reason %s", reason));
if (flush) {
/* send a FLUSH_STOP for the sinkpad, since we need data for seeking */
GST_DEBUG_OBJECT (base, "sending flush stop");
- gst_pad_push_event (base->sinkpad, gst_event_new_flush_stop ());
+ gst_pad_push_event (base->sinkpad, gst_event_new_flush_stop (TRUE));
+ /* And actually flush our pending data */
+ mpegts_base_flush (base);
+ mpegts_packetizer_flush (base->packetizer);
}
if (flags & (GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_SKIP)) {
}
static gboolean
-mpegts_base_sink_activate_push (GstPad * pad, gboolean active)
+mpegts_base_sink_activate_mode (GstPad * pad, GstObject * parent,
+ GstPadMode mode, gboolean active)
{
- MpegTSBase *base = GST_MPEGTS_BASE (GST_OBJECT_PARENT (pad));
- base->mode = BASE_MODE_PUSHING;
- base->packetizer->calculate_skew = TRUE;
- return TRUE;
-}
+ gboolean res;
+ MpegTSBase *base = GST_MPEGTS_BASE (parent);
+ switch (mode) {
+ case GST_PAD_MODE_PUSH:
+ base->mode = BASE_MODE_PUSHING;
++ base->packetizer->calculate_skew = TRUE;
+ res = TRUE;
+ break;
+ case GST_PAD_MODE_PULL:
+ if (active) {
+ base->mode = BASE_MODE_SCANNING;
++ base->packetizer->calculate_offset = TRUE;
+ res =
+ gst_pad_start_task (pad, (GstTaskFunction) mpegts_base_loop, base);
+ } else
+ res = gst_pad_stop_task (pad);
+ break;
+ default:
+ res = FALSE;
+ break;
+ }
+ return res;
+}
static GstStateChangeReturn
mpegts_base_change_state (GstElement * element, GstStateChange transition)
/* Whether we saw a PAT yet */
gboolean seen_pat;
- /* Offset from the origin to the first PAT (pullmode) */
- guint64 first_pat_offset;
-
- /* interpolation gap between the upstream timestamp and the pts */
- GstClockTime in_gap;
- GstClockTime first_buf_ts;
+ /* Whether upstream is live or not */
+ gboolean upstream_live;
+ /* Whether we queried the upstream latency or not */
+ gboolean queried_latency;
+ /* Whether upstream is live or not */
+ gboolean upstream_live;
+ /* Whether we queried the upstream latency or not */
+ gboolean query_latency;
+
/* Upstream segment */
GstSegment segment;
};
packet->data_end = packet->data_start + 188;
GST_BUFFER_OFFSET (packet->buffer) = packet->offset = packetizer->offset;
GST_DEBUG ("offset %" G_GUINT64_FORMAT, packet->offset);
+
packetizer->offset += packetizer->packet_size;
- GST_MEMDUMP ("buffer", GST_BUFFER_DATA (packet->buffer), 16);
+ GST_MEMDUMP ("buffer", bufdata, 16);
GST_MEMDUMP ("data_start", packet->data_start, 16);
+ GST_BUFFER_TIMESTAMP (packet->buffer) =
+ gst_adapter_prev_timestamp (packetizer->adapter, NULL);
/* Check sync byte */
- if (G_UNLIKELY (packet->data_start[0] != 0x47)) {
- guint i;
- GstBuffer *tmpbuf;
-
- GST_LOG ("Lost sync %d", packetizer->packet_size);
- /* Find the 0x47 in the buffer */
- for (i = 0; i < packetizer->packet_size; i++)
- if (GST_BUFFER_DATA (packet->buffer)[i] == 0x47)
- break;
- if (G_UNLIKELY (i == packetizer->packet_size)) {
- GST_ERROR ("REALLY lost the sync");
- gst_buffer_unref (packet->buffer);
- goto done;
- }
+ if (G_LIKELY (packet->data_start[0] == 0x47))
+ goto got_valid_packet;
- if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) {
- if (i >= 4)
- i -= 4;
- else
- i += 188;
- }
+ GST_LOG ("Lost sync %d", packetizer->packet_size);
+
+ /* Find the 0x47 in the buffer */
+ for (i = 0; i < packetizer->packet_size; i++)
+ if (bufdata[i] == 0x47)
+ break;
- /* Pop out the remaining data... */
- GST_BUFFER_DATA (packet->buffer) += i;
- GST_BUFFER_SIZE (packet->buffer) -= i;
- GST_BUFFER_OFFSET (packet->buffer) += i;
- tmpbuf =
- gst_adapter_take_buffer (packetizer->adapter,
- packetizer->adapter->size);
- /* ... and push everything back in */
- gst_adapter_push (packetizer->adapter, packet->buffer);
- gst_adapter_push (packetizer->adapter, tmpbuf);
- continue;
+ if (G_UNLIKELY (i == packetizer->packet_size)) {
+ GST_ERROR ("REALLY lost the sync");
+ gst_buffer_unmap (packet->buffer, &packet->bufmap);
+ gst_buffer_unref (packet->buffer);
+ goto done;
}
- return mpegts_packetizer_parse_packet (packetizer, packet);
+ if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) {
+ if (i >= 4)
+ i -= 4;
+ else
+ i += 188;
+ }
+
+ /* Pop out the remaining data... */
+ gst_buffer_resize (packet->buffer, i, packet->bufmap.size - i);
+ GST_BUFFER_OFFSET (packet->buffer) += i;
+ tmpbuf =
+ gst_adapter_take_buffer (packetizer->adapter,
+ packetizer->adapter->size);
+ /* ... and push everything back in */
+ gst_adapter_push (packetizer->adapter, packet->buffer);
+ gst_adapter_push (packetizer->adapter, tmpbuf);
}
done:
return PACKET_NEED_MORE;
+
+got_valid_packet:
+ return mpegts_packetizer_parse_packet (packetizer, packet);
}
+ MpegTSPacketizerPacketReturn
+ mpegts_packetizer_process_next_packet (MpegTSPacketizer2 * packetizer)
+ {
+ MpegTSPacketizerPacket packet;
+
+ return mpegts_packetizer_next_packet (packetizer, &packet);
+ }
+
void
mpegts_packetizer_clear_packet (MpegTSPacketizer2 * packetizer,
MpegTSPacketizerPacket * packet)
if (packet->pid == 0x14) {
table_id = data[0];
section->section_length = GST_READ_UINT24_BE (data) & 0x000FFF;
- if (data - GST_BUFFER_DATA (packet->buffer) + section->section_length + 3 >
- GST_BUFFER_SIZE (packet->buffer)) {
++ if (data - packet->bufmap.data + section->section_length + 3 >
++ packet->bufmap.size) {
+ GST_WARNING ("PID %dd PSI section length extends past the end "
+ "of the buffer", packet->pid);
+ goto out;
+ }
- section->buffer = gst_buffer_create_sub (packet->buffer,
- data - GST_BUFFER_DATA (packet->buffer), section->section_length + 3);
+ section->buffer =
+ gst_buffer_copy_region (packet->buffer, GST_BUFFER_COPY_ALL,
+ data - packet->bufmap.data, section->section_length + 3);
section->table_id = table_id;
section->complete = TRUE;
res = TRUE;
gboolean mpegts_packetizer_has_packets (MpegTSPacketizer2 *packetizer);
MpegTSPacketizerPacketReturn mpegts_packetizer_next_packet (MpegTSPacketizer2 *packetizer,
MpegTSPacketizerPacket *packet);
+ MpegTSPacketizerPacketReturn
+ mpegts_packetizer_process_next_packet(MpegTSPacketizer2 * packetizer);
void mpegts_packetizer_clear_packet (MpegTSPacketizer2 *packetizer,
- MpegTSPacketizerPacket *packet);
+ MpegTSPacketizerPacket *packet);
void mpegts_packetizer_remove_stream(MpegTSPacketizer2 *packetizer,
gint16 pid);
GstBuffer *pendingbuffers[TS_MAX_PENDING_BUFFERS];
guint8 nbpending;
+ /* Size of data to push (if known) */
+ guint expected_size;
+ /* Size of currently queued data */
+ guint current_size;
+
/* Current data to be pushed out */
- GstBufferList *current;
- GstBufferListIterator *currentit;
GList *currentlist;
/* Current PTS/DTS for this stream */
};
/* Pad functions */
- static gboolean gst_ts_demux_srcpad_query (GstPad * pad, GstObject * parent,
- GstQuery * query);
-
-
/* mpegtsbase methods */
static void
gst_ts_demux_program_started (MpegTSBase * base, MpegTSBaseProgram * program);
}
}
+ static const GstQueryType *
+ gst_ts_demux_srcpad_query_types (GstPad * pad)
+ {
+ static const GstQueryType query_types[] = {
+ GST_QUERY_DURATION,
+ GST_QUERY_SEEKING,
+ GST_QUERY_LATENCY,
+ 0
+ };
+
+ return query_types;
+ }
+
static gboolean
-gst_ts_demux_srcpad_query (GstPad * pad, GstQuery * query)
+gst_ts_demux_srcpad_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
gboolean res = TRUE;
GstFormat format;
res = FALSE;
}
break;
+ }
default:
- res = gst_pad_query_default (pad, query);
+ res = gst_pad_query_default (pad, parent, query);
}
- gst_object_unref (demux);
return res;
}
desc = mpegts_get_descriptor_from_program (program, DESC_REGISTRATION);
if (desc) {
if (DESC_REGISTRATION_format_identifier (desc) == DRF_ID_HDMV) {
- template = gst_static_pad_template_get (&audio_template);
- name = g_strdup_printf ("audio_%04x", bstream->pid);
- caps = gst_caps_new_empty_simple ("audio/x-eac3");
+ guint8 *ac3_desc;
+
+ /* ATSC ac3 audio descriptor */
+ ac3_desc =
+ mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream,
+ DESC_AC3_AUDIO_STREAM);
+ if (ac3_desc && DESC_AC_AUDIO_STREAM_bsid (ac3_desc) != 16) {
+ GST_LOG ("ac3 audio");
+ template = gst_static_pad_template_get (&audio_template);
+ name = g_strdup_printf ("audio_%04x", bstream->pid);
+ caps = gst_caps_new_simple ("audio/x-ac3", NULL);
+
+ g_free (ac3_desc);
+ } else {
+ template = gst_static_pad_template_get (&audio_template);
+ name = g_strdup_printf ("audio_%04x", bstream->pid);
+ caps = gst_caps_new_simple ("audio/x-eac3", NULL);
+ }
-
}
+
g_free (desc);
}
if (template)
if (stream->pad) {
GST_DEBUG_OBJECT (tsdemux, "Activating pad %s:%s for stream %p",
GST_DEBUG_PAD_NAME (stream->pad), stream);
- gst_pad_set_active (stream->pad, TRUE);
gst_element_add_pad ((GstElement *) tsdemux, stream->pad);
+ stream->active = TRUE;
GST_DEBUG_OBJECT (stream->pad, "done adding pad");
} else
GST_WARNING_OBJECT (tsdemux,
G_GUINT64_FORMAT, bs->pid,
GST_TIME_ARGS (PCRTIME_TO_GSTTIME (opcr)), offset);
+ /* FIXME : packetizer should record this */
+
if (G_UNLIKELY (demux->emit_statistics)) {
GstStructure *st;
- st = gst_structure_id_empty_new (QUARK_TSDEMUX);
+ st = gst_structure_new_id_empty (QUARK_TSDEMUX);
gst_structure_id_set (st,
QUARK_PID, G_TYPE_UINT, bs->pid,
QUARK_OFFSET, G_TYPE_UINT64, offset,
GST_TIME_ARGS (stream->pts),
GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (header.DTS)));
- /* FIXME : This will only work if the PES header is contained
- * at the beginning of an incoming GstBuffer */
- /* FIXME : Handle wrap-around ? */
- if (base->upstream_live && GST_CLOCK_TIME_IS_VALID (origts)
- && !GST_CLOCK_TIME_IS_VALID (demux->pts_delta)) {
- if (GST_CLOCK_TIME_IS_VALID (MPEGTIME_TO_GSTTIME (header.DTS)))
- demux->pts_delta = MPEGTIME_TO_GSTTIME (header.DTS) - origts;
- else
- demux->pts_delta = stream->pts - origts;
- GST_DEBUG_OBJECT (base, "buffer timestamp %" GST_TIME_FORMAT,
- GST_TIME_ARGS (origts));
- GST_DEBUG_OBJECT (base, "delta %" GST_TIME_FORMAT,
- GST_TIME_ARGS (demux->pts_delta));
- }
-
- /* safe default if insufficient upstream info */
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (base->in_gap) &&
- GST_CLOCK_TIME_IS_VALID (base->first_buf_ts) &&
- base->mode == BASE_MODE_PUSHING &&
- base->segment.format == GST_FORMAT_TIME)) {
- /* Find the earliest current PTS we're going to push */
- GstClockTime firstpts = GST_CLOCK_TIME_NONE;
- GList *tmp;
-
- for (tmp = demux->program->stream_list; tmp; tmp = tmp->next) {
- TSDemuxStream *pstream = (TSDemuxStream *) tmp->data;
- if (!GST_CLOCK_TIME_IS_VALID (firstpts) || pstream->pts < firstpts)
- firstpts = pstream->pts;
- }
+ {
+ MpegTSPacketizer2 *packetizer = base->packetizer;
- base->in_gap = base->first_buf_ts - firstpts;
- GST_DEBUG_OBJECT (base, "upstream segment start %" GST_TIME_FORMAT
- ", first buffer timestamp: %" GST_TIME_FORMAT
- ", first PTS: %" GST_TIME_FORMAT
- ", interpolation gap: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (base->segment.start),
- GST_TIME_ARGS (base->first_buf_ts), GST_TIME_ARGS (firstpts),
- GST_TIME_ARGS (base->in_gap));
+ GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]) =
+ mpegts_packetizer_pts_to_ts (packetizer, stream->pts);
}
-
- if (!GST_CLOCK_TIME_IS_VALID (base->in_gap))
- base->in_gap = 0;
-
- if (base->upstream_live) {
- if (GST_CLOCK_TIME_IS_VALID (demux->pts_delta))
- GST_BUFFER_TIMESTAMP (buf) = stream->pts - demux->pts_delta;
- else
- GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
- } else
- GST_BUFFER_TIMESTAMP (buf) = stream->pts + base->in_gap;
GST_DEBUG ("buf %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
+ GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0])));
}
+ if (header.DTS != -1)
+ gst_ts_demux_record_dts (demux, stream, header.DTS, bufferoffset);
+
+ gst_buffer_unmap (buf, &map);
+
/* Remove PES headers */
- GST_DEBUG ("Moving data forward by %d bytes", header.header_size);
+ GST_DEBUG ("Moving data forward by %d bytes (packet_size:%d, have:%d)",
+ header.header_size, header.packet_length,
+ GST_BUFFER_SIZE (stream->pendingbuffers[0]));
+ stream->expected_size = header.packet_length;
- GST_BUFFER_DATA (stream->pendingbuffers[0]) += header.header_size;
- GST_BUFFER_SIZE (stream->pendingbuffers[0]) -= header.header_size;
+ gst_buffer_resize (buf, header.header_size, map.size - header.header_size);
/* FIXME : responsible for switching to PENDING_PACKET_BUFFER and
* creating the bufferlist */
for (tmp = demux->program->stream_list; tmp; tmp = tmp->next) {
TSDemuxStream *pstream = (TSDemuxStream *) tmp->data;
- if (!GST_CLOCK_TIME_IS_VALID (firstpts) || pstream->pts < firstpts)
- firstpts = pstream->pts;
+ if (GST_CLOCK_TIME_IS_VALID (pstream->pts)) {
+ if (!GST_CLOCK_TIME_IS_VALID (lowest_pts) || pstream->pts < lowest_pts)
+ lowest_pts = pstream->pts;
+ }
+ if (GST_CLOCK_TIME_IS_VALID (pstream->dts)) {
+ if (!GST_CLOCK_TIME_IS_VALID (lowest_pts) || pstream->dts < lowest_pts)
+ lowest_pts = pstream->dts;
+ }
}
- if (base->mode == BASE_MODE_PUSHING) {
- /* FIXME : We're just ignore the upstream format for the time being */
- /* FIXME : We should use base->segment.format and a upstream latency query
- * to decide if we need to use live values or not */
- GST_DEBUG ("push-based. base Segment start:%" GST_TIME_FORMAT " duration:%"
- GST_TIME_FORMAT ", stop:%" GST_TIME_FORMAT ", time:%" GST_TIME_FORMAT,
- GST_TIME_ARGS (base->segment.start),
- GST_TIME_ARGS (base->segment.duration),
- GST_TIME_ARGS (base->segment.stop), GST_TIME_ARGS (base->segment.time));
- GST_DEBUG ("push-based. demux Segment start:%" GST_TIME_FORMAT " duration:%"
- GST_TIME_FORMAT ", stop:%" GST_TIME_FORMAT ", time:%" GST_TIME_FORMAT,
- GST_TIME_ARGS (demux->segment.start),
- GST_TIME_ARGS (demux->segment.duration),
- GST_TIME_ARGS (demux->segment.stop),
- GST_TIME_ARGS (demux->segment.time));
-
- GST_DEBUG ("stream pts: %" GST_TIME_FORMAT " first pts: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (stream->pts), GST_TIME_ARGS (firstpts));
-
- if (base->segment.format == GST_FORMAT_TIME) {
- start = base->segment.start;
- stop = base->segment.stop;
- if (!base->upstream_live) {
- /* Shift the start depending on our position in the stream */
- start += firstpts + base->in_gap - base->first_buf_ts;
- }
+
- demux->update_segment =
- gst_event_new_new_segment_full (TRUE, demux->segment.rate,
- demux->segment.applied_rate, GST_FORMAT_TIME, demux->segment.start,
- firstts, demux->segment.time);
+ if (GST_CLOCK_TIME_IS_VALID (lowest_pts))
+ firstts = mpegts_packetizer_pts_to_ts (base->packetizer, lowest_pts);
+ GST_DEBUG ("lowest_pts %" G_GUINT64_FORMAT " => clocktime %" GST_TIME_FORMAT,
+ lowest_pts, GST_TIME_ARGS (firstts));
+
+ if (demux->calculate_update_segment) {
+ GST_DEBUG ("Calculating update segment");
+ /* If we have a valid segment, create an update of that */
+ if (demux->segment.format == GST_FORMAT_TIME) {
+ GST_DEBUG ("Re-using segment " SEGMENT_FORMAT,
+ SEGMENT_ARGS (demux->segment));
++ demux->update_segment = gst_event_new_segment (&demux->segment);
+ GST_EVENT_SRC (demux->update_segment) = gst_object_ref (demux);
}
- position = start;
- } else {
- /* pull mode */
- GST_DEBUG ("pull-based. Segment start:%" GST_TIME_FORMAT " duration:%"
- GST_TIME_FORMAT ", time:%" GST_TIME_FORMAT,
- GST_TIME_ARGS (demux->segment.start),
- GST_TIME_ARGS (demux->segment.duration),
- GST_TIME_ARGS (demux->segment.time));
-
- GST_DEBUG ("firstpcr gsttime : %" GST_TIME_FORMAT,
- GST_TIME_ARGS (demux->first_pcr.gsttime));
-
- /* FIXME : This is not entirely correct. We should be using the PTS time
- * realm and not the PCR one. Doesn't matter *too* much if PTS/PCR values
- * aren't too far apart, but still. */
- start = demux->first_pcr.gsttime + demux->segment.start;
- stop = demux->first_pcr.gsttime + demux->segment.duration;
- position = demux->segment.time;
+ demux->calculate_update_segment = FALSE;
}
- GST_DEBUG ("new segment: start: %" GST_TIME_FORMAT " stop: %"
- GST_TIME_FORMAT " time: %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
- GST_TIME_ARGS (stop), GST_TIME_ARGS (position));
+ if (!demux->segment_event) {
+ GST_DEBUG ("Calculating actual segment");
+ /* FIXME : Set proper values */
- demux->segment_event =
- gst_event_new_new_segment_full (FALSE, 1.0, 1.0, GST_FORMAT_TIME,
- firstts, GST_CLOCK_TIME_NONE, firstts);
++ demux->segment_event = gst_event_new_segment (&demux->segment);
+ GST_EVENT_SRC (demux->segment_event) = gst_object_ref (demux);
+ }
- newsegmentevent = gst_event_new_segment (&demux->segment);
+ push_new_segment:
+ if (demux->update_segment) {
+ GST_DEBUG_OBJECT (stream->pad, "Pushing update segment");
+ gst_event_ref (demux->update_segment);
+ gst_pad_push_event (stream->pad, demux->update_segment);
+ }
- push_event ((MpegTSBase *) demux, newsegmentevent);
+ if (demux->segment_event) {
+ GST_DEBUG_OBJECT (stream->pad, "Pushing newsegment event");
+ gst_event_ref (demux->segment_event);
+ gst_pad_push_event (stream->pad, demux->segment_event);
+ }
- demux->need_newsegment = FALSE;
+ stream->need_newsegment = FALSE;
}
static GstFlowReturn
gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
{
GstFlowReturn res = GST_FLOW_OK;
+ GList *tmp;
MpegTSBaseStream *bs = (MpegTSBaseStream *) stream;
- GstBuffer *buf;
- GstClockTime ts;
+ /* MpegTSBase *base = (MpegTSBase*) demux; */
+ GstBuffer *firstbuffer = NULL;
+ MpegTSPacketizer2 *packetizer = MPEG_TS_BASE_PACKETIZER (demux);
GST_DEBUG_OBJECT (stream->pad,
"stream:%p, pid:0x%04x stream_type:%d state:%d", stream, bs->pid,
calculate_and_push_newsegment (demux, stream);
/* We have a confirmed buffer, let's push it out */
- GST_LOG ("Putting pending data into GstBufferList");
-
- GST_LOG_OBJECT (stream->pad, "Putting pending data into GstBufferList");
++ GST_LOG_OBJECT (stream->pad, "Putting pending data into buffer list");
stream->currentlist = g_list_reverse (stream->currentlist);
- gst_buffer_list_iterator_add_list (stream->currentit, stream->currentlist);
- gst_buffer_list_iterator_free (stream->currentit);
+ buf = (GstBuffer *) stream->currentlist->data;
+
+ ts = GST_BUFFER_TIMESTAMP (buf);
+
+ GST_DEBUG_OBJECT (stream->pad,
+ "ts %" GST_TIME_FORMAT " delta %" GST_TIME_FORMAT " stream->pts %"
+ GST_TIME_FORMAT, GST_TIME_ARGS (ts), GST_TIME_ARGS (demux->pts_delta),
+ GST_TIME_ARGS (stream->pts));
+
+ if (GST_CLOCK_TIME_IS_VALID (demux->pts_delta)
+ && GST_CLOCK_TIME_IS_VALID (stream->pts)
+ && !GST_CLOCK_TIME_IS_VALID (ts)) {
+ ts = stream->pts - demux->pts_delta;
+ }
+
+ for (tmp = stream->currentlist->next; tmp; tmp = tmp->next) {
+ buf = gst_buffer_append (buf, (GstBuffer *) tmp->data);
+ }
- GST_BUFFER_TIMESTAMP (buf) = ts;
+ firstbuffer = gst_buffer_list_get (stream->current, 0, 0);
+
+ GST_DEBUG_OBJECT (stream->pad, "stream->pts %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (stream->pts));
+ if (GST_CLOCK_TIME_IS_VALID (stream->pts)
+ && !GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (firstbuffer)))
+ GST_BUFFER_TIMESTAMP (firstbuffer) =
+ mpegts_packetizer_pts_to_ts (packetizer, stream->pts);
+
GST_DEBUG_OBJECT (stream->pad,
- "Pushing buffer with timestamp: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
+ "Pushing buffer list with timestamp: %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (firstbuffer)));
- res = gst_pad_push_list (stream->pad, stream->current);
+ res = gst_pad_push (stream->pad, buf);
GST_DEBUG_OBJECT (stream->pad, "Returned %s", gst_flow_get_name (res));
res = tsdemux_combine_flows (demux, stream, res);
GST_DEBUG_OBJECT (stream->pad, "combined %s", gst_flow_get_name (res));
gint i, sps_size = 0, pps_size = 0, num_sps = 0, num_pps = 0;
guint8 profile_idc = 0, profile_comp = 0, level_idc = 0;
gboolean found = FALSE;
+ GstMapInfo map;
guint8 *data;
+ gint nl;
/* only nal payload in stored nals */
if (!found || !num_pps)
return NULL;
- buf = gst_buffer_new_and_alloc (5 + 1 + sps_size + 1 + pps_size);
- data = GST_BUFFER_DATA (buf);
+ buf = gst_buffer_new_allocate (NULL, 5 + 1 + sps_size + 1 + pps_size, NULL);
+ gst_buffer_map (buf, &map, GST_MAP_WRITE);
+ data = map.data;
+ nl = h264parse->nal_length_size;
data[0] = 1; /* AVC Decoder Configuration Record ver. 1 */
data[1] = profile_idc; /* profile_idc */
GstBuffer *new_buf;
const gboolean bs = h264parse->format == GST_H264_PARSE_FORMAT_BYTE;
- gst_byte_writer_init_with_size (&bw, GST_BUFFER_SIZE (buffer), FALSE);
- gst_byte_writer_put_data_unchecked (&bw, GST_BUFFER_DATA (buffer),
+ gst_byte_writer_init_with_size (&bw, gst_buffer_get_size (buffer),
+ FALSE);
- gst_byte_writer_put_buffer (&bw, buffer, 0, h264parse->idr_pos);
++ gst_byte_writer_put_buffer_unchecked (&bw, buffer, 0,
+ h264parse->idr_pos);
GST_DEBUG_OBJECT (h264parse, "- inserting SPS/PPS");
for (i = 0; i < GST_H264_MAX_SPS_COUNT; i++) {
if ((codec_nal = h264parse->sps_nals[i])) {
+ gsize nal_size = gst_buffer_get_size (codec_nal);
GST_DEBUG_OBJECT (h264parse, "inserting SPS nal");
- gst_byte_writer_put_uint32_be (&bw, bs ? 1 : nal_size);
- gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
- gst_byte_writer_put_uint32_be_unchecked (&bw,
- bs ? 1 : GST_BUFFER_SIZE (codec_nal));
- gst_byte_writer_put_data_unchecked (&bw,
- GST_BUFFER_DATA (codec_nal), GST_BUFFER_SIZE (codec_nal));
++ gst_byte_writer_put_uint32_be_unchecked (&bw, bs ? 1 : nal_size);
++ gst_byte_writer_put_buffer_unchecked (&bw, codec_nal, 0,
++ nal_size);
h264parse->last_report = new_ts;
}
}
for (i = 0; i < GST_H264_MAX_PPS_COUNT; i++) {
if ((codec_nal = h264parse->pps_nals[i])) {
+ gsize nal_size = gst_buffer_get_size (codec_nal);
GST_DEBUG_OBJECT (h264parse, "inserting PPS nal");
- gst_byte_writer_put_uint32_be (&bw, bs ? 1 : nal_size);
- gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
- gst_byte_writer_put_uint32_be_unchecked (&bw,
- bs ? 1 : GST_BUFFER_SIZE (codec_nal));
- gst_byte_writer_put_data_unchecked (&bw,
- GST_BUFFER_DATA (codec_nal), GST_BUFFER_SIZE (codec_nal));
++ gst_byte_writer_put_uint32_be_unchecked (&bw, bs ? 1 : nal_size);
++ gst_byte_writer_put_buffer_unchecked (&bw, codec_nal, 0,
++ nal_size);
h264parse->last_report = new_ts;
}
}
- gst_byte_writer_put_buffer (&bw, buffer, h264parse->idr_pos, -1);
- gst_byte_writer_put_data_unchecked (&bw,
- GST_BUFFER_DATA (buffer) + h264parse->idr_pos,
- GST_BUFFER_SIZE (buffer) - h264parse->idr_pos);
++ gst_byte_writer_put_buffer_unchecked (&bw, buffer, h264parse->idr_pos,
++ -1);
/* collect result and push */
new_buf = gst_byte_writer_reset_and_get_buffer (&bw);
- gst_buffer_copy_metadata (new_buf, buffer, GST_BUFFER_COPY_ALL);
+ gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_METADATA, 0,
+ -1);
/* should already be keyframe/IDR, but it may not have been,
* so mark it as such to avoid being discarded by picky decoder */
GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_DELTA_UNIT);
WININET_DIR=
endif
- if USE_ACM
- ACM_DIR=acmenc acmmp3dec
+ if USE_VCD
+ VCD_DIR=vcd
else
- ACM_DIR=
+ VCD_DIR=
endif
-if USE_VDPAU
-VDPAU_DIR=vdpau
-else
-VDPAU_DIR=
-endif
+#if USE_VDPAU
+#VDPAU_DIR=vdpau
+#else
+#VDPAU_DIR=
+#endif
-
- if USE_SHM
- SHM_DIR=shm
+ if USE_DIRECT3D9
+ WINSCREENCAP_DIR=winscreencap
else
- SHM_DIR=
- endif
-
- if USE_AVC
- AVC_DIR=avc
- else
- AVC_DIR=
- endif
-
- if USE_PVR
- PVR_DIR=pvr2d
- else
- PVR_DIR=
+ WINSCREENCAP_DIR=
endif
- SUBDIRS = $(ACM_DIR) $(APPLE_MEDIA_DIR) $(AVC_DIR) $(D3DVIDEOSINK_DIR) $(DECKLINK_DIR) $(DIRECTDRAW_DIR) $(DIRECTSOUND_DIR) $(DVB_DIR) $(FBDEV_DIR) $(LINSYS_DIR) $(OSX_VIDEO_DIR) $(QT_DIR) $(SHM_DIR) $(VCD_DIR) $(VDPAU_DIR) $(WININET_DIR) $(PVR_DIR)
+ SUBDIRS = $(ACM_DIR) $(APPLE_MEDIA_DIR) $(AVC_DIR) $(D3DVIDEOSINK_DIR) $(DECKLINK_DIR) $(DIRECTDRAW_DIR) $(DIRECTSOUND_DIR) $(DVB_DIR) $(FBDEV_DIR) $(LINSYS_DIR) $(OSX_VIDEO_DIR) $(PVR_DIR) $(QT_DIR) $(SHM_DIR) $(VCD_DIR) $(VDPAU_DIR) $(WININET_DIR) $(WINSCREENCAP_DIR)
DIST_SUBDIRS = acmenc acmmp3dec applemedia avc d3dvideosink decklink directdraw directsound dvb linsys fbdev dshowdecwrapper dshowsrcwrapper dshowvideosink \
- osxvideo qtwrapper shm vcd vdpau wasapi wininet winks winscreencap pvr2d
+ osxvideo pvr2d qtwrapper shm vcd vdpau wasapi wininet winks winscreencap
include $(top_srcdir)/common/parallel-subdirs.mak
gst_decklink_sink_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+ GstPadTemplate *pad_template;
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_decklink_sink_videosink_template));
+ pad_template =
+ gst_pad_template_new ("videosink", GST_PAD_SINK, GST_PAD_ALWAYS,
+ gst_decklink_mode_get_template_caps ());
+ gst_element_class_add_pad_template (element_class, pad_template);
+ gst_object_unref (pad_template);
- gst_element_class_add_static_pad_template (element_class,
- &gst_decklink_sink_audiosink_template);
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_decklink_sink_audiosink_template));
gst_element_class_set_details_simple (element_class, "Decklink Sink",
"Video/Sink", "Decklink Sink", "David Schleef <ds@entropywave.com>");
count = count + nread;
}
}
- GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
+ gst_buffer_unmap (buf, &map);
+ gst_buffer_resize (buf, 0, count);
- GST_BUFFER_SIZE (buf) = count;
+
return buf;
stopped:
"True if the element cannot produce data in PAUSED", FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- gst_element_class_set_details_simple (gstelement_class,
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&srctemplate));
+
- "Receive data from the sharem memory sink",
++ gst_element_class_set_details_simple (element_class,
+ "Shared Memory Source",
+ "Source",
++ "Receive data from the shared memory sink",
+ "Olivier Crete <olivier.crete@collabora.co.uk>");
+
GST_DEBUG_CATEGORY_INIT (shmsrc_debug, "shmsrc", 0, "Shared Memory Source");
}