2005-05-25 Wim Taymans <wim@fluendo.com>
+ * ext/ogg/gstoggdemux.c: (gst_ogg_pad_dispose),
+ (gst_ogg_pad_typefind), (gst_ogg_pad_submit_packet),
+ (gst_ogg_chain_new_stream), (gst_ogg_demux_perform_seek),
+ (gst_ogg_demux_chain), (gst_ogg_demux_loop),
+ (gst_ogg_demux_sink_activate):
+ * ext/theora/theoradec.c: (theora_dec_src_event),
+ (theora_handle_comment_packet), (theora_dec_chain),
+ (theora_dec_change_state):
+ * ext/vorbis/vorbisdec.c: (vorbis_dec_sink_event),
+ (vorbis_handle_data_packet), (vorbis_dec_chain),
+ (vorbis_dec_change_state):
+ Remove STREAM locks as they are taken in core now.
+ Never set bogus granulepos on vorbis/theora.
+ Fix leaks in theoradec tag parsing.
+
+2005-05-25 Wim Taymans <wim@fluendo.com>
+
* ext/gnomevfs/gstgnomevfssrc.c: (gst_gnomevfssrc_create):
Fix memleaks, GST_BUFFER_DATA() is not freed.
GST_OGG_PAD_MODE_STREAMING, /* we are streaming buffers to the outside */
} GstOggPadMode;
+//#define PARENT GstPad
+//#define PARENTCLASS GstPadClass
+#define PARENT GstRealPad
+#define PARENTCLASS GstRealPadClass
+
/* all information needed for one ogg stream */
struct _GstOggPad
{
- GstRealPad pad; /* subclass GstRealPad */
+ PARENT pad; /* subclass GstPad */
GstOggPadMode mode;
gint64 packetno;
gint64 offset;
- GstEvent *new_segment;
gint64 start;
gint64 stop;
struct _GstOggPadClass
{
- GstRealPadClass parent_class;
+ PARENTCLASS parent_class;
};
typedef enum
static GstCaps *gst_ogg_pad_getcaps (GstPad * pad);
static GstCaps *gst_ogg_type_find (ogg_packet * packet);
-static GstRealPadClass *ogg_pad_parent_class = NULL;
+static GstPadClass *ogg_pad_parent_class = NULL;
static GType
gst_ogg_pad_get_type (void)
g_list_free (pad->headers);
pad->headers = NULL;
- if (pad->new_segment) {
- gst_event_unref (pad->new_segment);
- pad->new_segment = NULL;
- }
ogg_stream_reset (&pad->stream);
G_OBJECT_CLASS (ogg_pad_parent_class)->dispose (object);
gst_element_factory_create (GST_ELEMENT_FACTORY (factories->data),
NULL);
if (element) {
+ GstCaps *any;
+
/* this is ours */
gst_object_ref (GST_OBJECT (element));
gst_object_sink (GST_OBJECT (element));
gst_pad_set_chain_function (pad->elem_out,
gst_ogg_pad_internal_chain);
gst_pad_set_element_private (pad->elem_out, pad);
- gst_pad_set_caps (pad->elem_out, gst_caps_new_any ());
+ any = gst_caps_new_any ();
+ gst_pad_set_caps (pad->elem_out, any);
+ gst_caps_unref (any);
gst_pad_set_active (pad->elem_out, TRUE);
/* and this pad may not be named src.. */
"%p streaming to peer serial %08lx, packetno %lld", pad, pad->serialno,
pad->packetno);
- if (pad->new_segment) {
- ret = gst_pad_push_event (GST_PAD (pad), pad->new_segment);
- pad->new_segment = NULL;
- }
if (buf) {
memcpy (buf->data, packet->packet, packet->bytes);
GST_BUFFER_OFFSET (buf) = -1;
GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
- ret = GST_RPAD_CHAINFUNC (pad->elem_pad) (pad->elem_pad, buf);
+ ret = gst_pad_chain (pad->elem_pad, buf);
}
#if 0
list = gst_tag_list_new ();
name = g_strdup_printf ("serial_%08lx", serialno);
- GST_RPAD_DIRECTION (ret) = GST_PAD_SRC;
+ GST_PAD_DIRECTION (ret) = GST_PAD_SRC;
ret->chain = chain;
ret->ogg = chain->ogg;
gst_object_set_name (GST_OBJECT (ret), name);
for (j = 0; j < chain->streams->len; j++) {
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, j);
- gst_event_ref (event);
- /* queue the event for the streaming thread */
- pad->new_segment = event;
gst_pad_push_event (GST_PAD (pad), gst_event_new_flush (TRUE));
+
+ /* and the discont */
+ gst_event_ref (event);
+ gst_pad_push_event (GST_PAD (pad), event);
}
}
gst_event_unref (event);
/* restart our task since it might have been stopped when we did the
* flush. */
- gst_task_start (GST_RPAD_TASK (ogg->sinkpad));
+ gst_pad_start_task (ogg->sinkpad, (GstTaskFunction) gst_ogg_demux_loop,
+ ogg->sinkpad);
}
/* switch to different chain */
* the serialno, submit pages and packets to the oggpads
*/
static GstFlowReturn
-gst_ogg_demux_chain_unlocked (GstPad * pad, GstBuffer * buffer)
+gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
{
GstOggDemux *ogg;
gint ret = -1;
return result;
}
-static GstFlowReturn
-gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstFlowReturn ret;
-
- GST_STREAM_LOCK (pad);
- ret = gst_ogg_demux_chain_unlocked (pad, buffer);
- GST_STREAM_UNLOCK (pad);
-
- return ret;
-}
-
static void
gst_ogg_demux_send_eos (GstOggDemux * ogg)
{
ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (pad));
- GST_STREAM_LOCK (pad);
if (ogg->need_chains) {
gboolean got_chains;
ogg->offset += GST_BUFFER_SIZE (buffer);
- ret = gst_ogg_demux_chain_unlocked (ogg->sinkpad, buffer);
+ ret = gst_ogg_demux_chain (ogg->sinkpad, buffer);
if (ret != GST_FLOW_OK) {
GST_LOG_OBJECT (ogg, "got unexpected %d, pausing", ret);
goto pause;
}
-
- GST_STREAM_UNLOCK (pad);
return;
pause:
GST_LOG_OBJECT (ogg, "pausing task");
- gst_task_pause (GST_RPAD_TASK (ogg->sinkpad));
- GST_STREAM_UNLOCK (pad);
+ gst_pad_pause_task (ogg->sinkpad);
return;
}
break;
case GST_ACTIVATE_PULL:
/* if we have a scheduler we can start the task */
- if (GST_ELEMENT_SCHEDULER (ogg)) {
- gst_pad_peer_set_active (sinkpad, mode);
- GST_STREAM_LOCK (sinkpad);
- GST_RPAD_TASK (sinkpad) =
- gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (ogg),
- (GstTaskFunction) gst_ogg_demux_loop, sinkpad);
-
- ogg->need_chains = TRUE;
- ogg->seekable = TRUE;
- gst_task_start (GST_RPAD_TASK (sinkpad));
- GST_STREAM_UNLOCK (sinkpad);
- result = TRUE;
- }
+ gst_pad_peer_set_active (sinkpad, mode);
+ ogg->need_chains = TRUE;
+ ogg->seekable = TRUE;
+ result =
+ gst_pad_start_task (sinkpad, (GstTaskFunction) gst_ogg_demux_loop,
+ sinkpad);
break;
case GST_ACTIVATE_NONE:
/* step 1, unblock clock sync (if any) */
/* step 2, make sure streaming finishes */
- GST_STREAM_LOCK (sinkpad);
-
- /* step 3, stop the task */
- if (GST_RPAD_TASK (sinkpad)) {
- gst_task_stop (GST_RPAD_TASK (sinkpad));
- gst_object_unref (GST_OBJECT (GST_RPAD_TASK (sinkpad)));
- GST_RPAD_TASK (sinkpad) = NULL;
- }
- GST_STREAM_UNLOCK (sinkpad);
-
- result = TRUE;
+ result = gst_pad_stop_task (sinkpad);
break;
}
return result;
format, value);
res = gst_pad_send_event (GST_PAD_PEER (dec->sinkpad), real_seek);
- if (!res)
- goto error;
- error:
gst_event_unref (event);
break;
}
}
return res;
+
+error:
+ gst_event_unref (event);
+ return res;
}
static gboolean
GST_DEBUG ("parsing comment packet");
buf = gst_buffer_new_and_alloc (packet->bytes);
- GST_BUFFER_DATA (buf) = packet->packet;
+ memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
list =
gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\201theora", 7,
GST_TAG_VIDEO_CODEC, "Theora", NULL);
//gst_element_found_tags_for_pad (GST_ELEMENT (dec), dec->srcpad, 0, list);
+ gst_tag_list_free (list);
return GST_FLOW_OK;
}
dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
- GST_STREAM_LOCK (pad);
-
if (dec->packetno >= 3) {
/* try timestamp first */
outtime = GST_BUFFER_TIMESTAMP (buf);
* offset before we can generate valid timestamps */
dec->queued = g_list_append (dec->queued, buf);
GST_DEBUG_OBJECT (dec, "queued buffer");
- GST_STREAM_UNLOCK (pad);
return GST_FLOW_OK;
} else {
/* granulepos to time */
done:
dec->packetno++;
_inc_granulepos (dec);
- GST_STREAM_UNLOCK (pad);
gst_buffer_unref (buf);
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
- GST_STREAM_LOCK (dec->sinkpad);
theora_clear (&dec->state);
theora_comment_clear (&dec->comment);
theora_info_clear (&dec->info);
dec->packetno = 0;
dec->granulepos = -1;
- GST_STREAM_UNLOCK (dec->sinkpad);
break;
case GST_STATE_READY_TO_NULL:
break;
GST_LOG_OBJECT (dec, "handling event");
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_DISCONTINUOUS:
+ GST_STREAM_LOCK (pad);
if (gst_event_discont_get_value (event, GST_FORMAT_DEFAULT,
(gint64 *) & start_value, &end_value)) {
dec->granulepos = start_value;
} else {
GST_WARNING_OBJECT (dec,
"discont event didn't include offset, we might set it wrong now");
+ dec->granulepos = -1;
}
}
+ GST_DEBUG ("vd: discont %lld", dec->granulepos);
+ dec->granulepos = -1;
if (dec->packetno < 3) {
if (dec->granulepos != 0)
GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
("can't handle discont before parsing first 3 packets"));
dec->packetno = 0;
+#if 0
gst_pad_push_event (dec->srcpad, gst_event_new_discontinuous (FALSE,
GST_FORMAT_TIME, (guint64) 0, GST_FORMAT_DEFAULT,
(guint64) 0, GST_FORMAT_BYTES, (guint64) 0, 0));
+#endif
+ gst_event_ref (event);
+ gst_pad_push_event (dec->srcpad, event);
} else {
GstFormat time_format, default_format, bytes_format;
dec->granulepos, &time_format, &time)
&& vorbis_dec_convert (dec->srcpad, GST_FORMAT_DEFAULT,
dec->granulepos, &bytes_format, &bytes)) {
- gst_pad_push_event (dec->srcpad,
- gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
- time, GST_FORMAT_DEFAULT, dec->granulepos,
- GST_FORMAT_BYTES, bytes, 0));
+
+ gst_event_ref (event);
+ gst_pad_push_event (dec->srcpad, event);
+ /*
+ gst_pad_push_event (dec->srcpad,
+ gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
+ time, GST_FORMAT_DEFAULT, dec->granulepos,
+ GST_FORMAT_BYTES, bytes, 0));
+ */
} else {
GST_ERROR_OBJECT (dec,
"failed to parse data for DISCONT event, not sending any");
+ gst_event_ref (event);
+ gst_pad_push_event (dec->srcpad, event);
}
#ifdef HAVE_VORBIS_SYNTHESIS_RESTART
vorbis_synthesis_restart (&dec->vd);
#endif
}
+ GST_STREAM_UNLOCK (pad);
gst_event_unref (event);
break;
default:
- ret = gst_pad_event_default (dec->sinkpad, event);
+ ret = gst_pad_event_default (pad, event);
break;
}
return ret;
GST_BUFFER_OFFSET (out) = vd->granulepos;
GST_BUFFER_OFFSET_END (out) = vd->granulepos + sample_count;
- GST_BUFFER_TIMESTAMP (out) = vd->granulepos * GST_SECOND / vd->vi.rate;
+ if (vd->granulepos != -1)
+ GST_BUFFER_TIMESTAMP (out) = vd->granulepos * GST_SECOND / vd->vi.rate;
+ else
+ GST_BUFFER_TIMESTAMP (out) = -1;
GST_BUFFER_DURATION (out) = sample_count * GST_SECOND / vd->vi.rate;
result = gst_pad_push (vd->srcpad, out);
- vd->granulepos += sample_count;
+ if (vd->granulepos != -1)
+ vd->granulepos += sample_count;
} else {
/* no buffer.. */
result = GST_FLOW_OK;
ogg_packet packet;
GstFlowReturn result = GST_FLOW_OK;
- GST_STREAM_LOCK (pad);
-
vd = GST_VORBIS_DEC (GST_PAD_PARENT (pad));
/* make ogg_packet out of the buffer */
packet.packet = GST_BUFFER_DATA (buffer);
packet.bytes = GST_BUFFER_SIZE (buffer);
- packet.granulepos = GST_BUFFER_OFFSET_END (buffer);
+ packet.granulepos = vd->granulepos;
packet.packetno = vd->packetno++;
/*
* FIXME. Is there anyway to know that this is the last packet and
result = vorbis_handle_data_packet (vd, &packet);
}
+ GST_DEBUG ("offset end: %lld", GST_BUFFER_OFFSET_END (buffer));
+
/* granulepos is the last sample in the packet */
if (GST_BUFFER_OFFSET_END_IS_VALID (buffer))
vd->granulepos = GST_BUFFER_OFFSET_END (buffer);;
done:
- GST_STREAM_UNLOCK (pad);
-
gst_buffer_unref (buffer);
return result;
vorbis_info_init (&vd->vi);
vorbis_comment_init (&vd->vc);
vd->initialized = FALSE;
- vd->granulepos = 0;
+ vd->granulepos = -1;
vd->packetno = 0;
break;
case GST_STATE_PAUSED_TO_PLAYING:
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
- GST_STREAM_LOCK (vd->sinkpad);
vorbis_block_clear (&vd->vb);
vorbis_dsp_clear (&vd->vd);
vorbis_comment_clear (&vd->vc);
vorbis_info_clear (&vd->vi);
- vd->packetno = 0;
- vd->granulepos = 0;
- GST_STREAM_UNLOCK (vd->sinkpad);
break;
case GST_STATE_READY_TO_NULL:
break;