summaryrefslogtreecommitdiffstats
path: root/gst/flv
diff options
context:
space:
mode:
authorJulien Moutte <julien@moutte.net>2007-07-25 13:29:04 +0000
committerJulien Moutte <julien@moutte.net>2007-07-25 13:29:04 +0000
commit0a10191772eecb23d31c1ac7442a2efc22eff074 (patch)
treef9b4b3b017236426639e71183351f7d17245c339 /gst/flv
parent3ff914844181a756f4c27ddd6241edb24f860704 (diff)
downloadgst-plugins-bad-0a10191772eecb23d31c1ac7442a2efc22eff074.tar.gz
gst-plugins-bad-0a10191772eecb23d31c1ac7442a2efc22eff074.tar.bz2
gst-plugins-bad-0a10191772eecb23d31c1ac7442a2efc22eff074.zip
gst/flv/: Handle not linked pads, try to make it reusable, more safety checks.
Original commit message from CVS: 2007-07-25 Julien MOUTTE <julien@moutte.net> (gst_flv_demux_chain), (gst_flv_demux_pull_tag), (gst_flv_demux_change_state), (gst_flv_demux_dispose), (gst_flv_demux_init): * gst/flv/gstflvdemux.h: * gst/flv/gstflvparse.c: (FLV_GET_STRING), (gst_flv_parse_metadata_item), (gst_flv_parse_tag_script), (gst_flv_parse_tag_audio), (gst_flv_parse_tag_video), (gst_flv_parse_header): * gst/flv/gstflvparse.h: Handle not linked pads, try to make it reusable, more safety checks.
Diffstat (limited to 'gst/flv')
-rw-r--r--gst/flv/gstflvdemux.c74
-rw-r--r--gst/flv/gstflvdemux.h48
-rw-r--r--gst/flv/gstflvparse.c63
-rw-r--r--gst/flv/gstflvparse.h8
4 files changed, 151 insertions, 42 deletions
diff --git a/gst/flv/gstflvdemux.c b/gst/flv/gstflvdemux.c
index f91763db..dac3ab0a 100644
--- a/gst/flv/gstflvdemux.c
+++ b/gst/flv/gstflvdemux.c
@@ -74,6 +74,46 @@ static void
gst_flv_demux_cleanup (GstFLVDemux * demux)
{
GST_DEBUG_OBJECT (demux, "cleaning up FLV demuxer");
+
+ demux->state = FLV_STATE_HEADER;
+
+ demux->need_header = TRUE;
+ demux->audio_need_segment = TRUE;
+ demux->video_need_segment = TRUE;
+ demux->audio_need_discont = TRUE;
+ demux->video_need_discont = TRUE;
+
+ /* By default we consider them as linked */
+ demux->audio_linked = TRUE;
+ demux->video_linked = TRUE;
+
+ demux->has_audio = FALSE;
+ demux->has_video = FALSE;
+ demux->push_tags = FALSE;
+
+ demux->video_offset = 0;
+ demux->audio_offset = 0;
+ demux->offset = demux->tag_size = demux->tag_data_size = 0;
+ demux->duration = GST_CLOCK_TIME_NONE;
+
+ if (demux->new_seg_event) {
+ gst_event_unref (demux->new_seg_event);
+ demux->new_seg_event = NULL;
+ }
+
+ gst_adapter_clear (demux->adapter);
+
+ if (demux->audio_pad) {
+ gst_element_remove_pad (GST_ELEMENT (demux), demux->audio_pad);
+ gst_object_unref (demux->audio_pad);
+ demux->audio_pad = NULL;
+ }
+
+ if (demux->video_pad) {
+ gst_element_remove_pad (GST_ELEMENT (demux), demux->video_pad);
+ gst_object_unref (demux->video_pad);
+ demux->video_pad = NULL;
+ }
}
static GstFlowReturn
@@ -177,6 +217,13 @@ parse:
}
beach:
+ if (G_UNLIKELY (ret == GST_FLOW_NOT_LINKED)) {
+ /* If either audio or video is linked we return GST_FLOW_OK */
+ if (demux->audio_linked || demux->video_linked) {
+ ret = GST_FLOW_OK;
+ }
+ }
+
gst_object_unref (demux);
return ret;
@@ -256,6 +303,13 @@ gst_flv_demux_pull_tag (GstPad * pad, GstFLVDemux * demux)
/* Ready for the next tag */
demux->state = FLV_STATE_TAG_TYPE;
+ if (G_UNLIKELY (ret == GST_FLOW_NOT_LINKED)) {
+ /* If either audio or video is linked we return GST_FLOW_OK */
+ if (demux->audio_linked || demux->video_linked) {
+ ret = GST_FLOW_OK;
+ }
+ }
+
beach:
return ret;
}
@@ -547,10 +601,7 @@ gst_flv_demux_change_state (GstElement * element, GstStateChange transition)
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
- demux->state = FLV_STATE_HEADER;
- demux->need_header = TRUE;
- demux->audio_need_discont = TRUE;
- demux->video_need_discont = TRUE;
+ gst_flv_demux_cleanup (demux);
break;
default:
break;
@@ -599,6 +650,16 @@ gst_flv_demux_dispose (GObject * object)
demux->new_seg_event = NULL;
}
+ if (demux->audio_pad) {
+ gst_object_unref (demux->audio_pad);
+ demux->audio_pad = NULL;
+ }
+
+ if (demux->video_pad) {
+ gst_object_unref (demux->video_pad);
+ demux->video_pad = NULL;
+ }
+
GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
}
@@ -652,10 +713,7 @@ gst_flv_demux_init (GstFLVDemux * demux, GstFLVDemuxClass * g_class)
demux->taglist = gst_tag_list_new ();
gst_segment_init (demux->segment, GST_FORMAT_TIME);
- demux->offset = 0;
-
- demux->strict = FALSE;
- demux->push_tags = FALSE;
+ gst_flv_demux_cleanup (demux);
}
static gboolean
diff --git a/gst/flv/gstflvdemux.h b/gst/flv/gstflvdemux.h
index 09de14fd..63878f1d 100644
--- a/gst/flv/gstflvdemux.h
+++ b/gst/flv/gstflvdemux.h
@@ -24,7 +24,6 @@
#include <gst/base/gstadapter.h>
G_BEGIN_DECLS
-
#define GST_TYPE_FLV_DEMUX \
(gst_flv_demux_get_type())
#define GST_FLV_DEMUX(obj) \
@@ -35,11 +34,11 @@ G_BEGIN_DECLS
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FLV_DEMUX))
#define GST_IS_FLV_DEMUX_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FLV_DEMUX))
-
typedef struct _GstFLVDemux GstFLVDemux;
typedef struct _GstFLVDemuxClass GstFLVDemuxClass;
-typedef enum {
+typedef enum
+{
FLV_STATE_HEADER,
FLV_STATE_TAG_TYPE,
FLV_STATE_TAG_VIDEO,
@@ -49,29 +48,30 @@ typedef enum {
FLV_STATE_NONE
} GstFLVDemuxState;
-struct _GstFLVDemux {
+struct _GstFLVDemux
+{
GstElement element;
- GstPad * sinkpad;
-
- GstPad * audio_pad;
- GstPad * video_pad;
-
- GstAdapter * adapter;
-
- GstSegment * segment;
-
- GstEvent * new_seg_event;
-
- GstTagList * taglist;
-
+ GstPad *sinkpad;
+
+ GstPad *audio_pad;
+ GstPad *video_pad;
+
+ GstAdapter *adapter;
+
+ GstSegment *segment;
+
+ GstEvent *new_seg_event;
+
+ GstTagList *taglist;
+
GstFLVDemuxState state;
-
+
guint64 offset;
GstClockTime duration;
guint64 tag_size;
guint64 tag_data_size;
-
+
/* Audio infos */
guint16 rate;
guint16 channels;
@@ -80,7 +80,8 @@ struct _GstFLVDemux {
guint64 audio_offset;
gboolean audio_need_discont;
gboolean audio_need_segment;
-
+ gboolean audio_linked;
+
/* Video infos */
guint32 w;
guint32 h;
@@ -88,7 +89,8 @@ struct _GstFLVDemux {
guint64 video_offset;
gboolean video_need_discont;
gboolean video_need_segment;
-
+ gboolean video_linked;
+
gboolean random_access;
gboolean need_header;
gboolean has_audio;
@@ -97,12 +99,12 @@ struct _GstFLVDemux {
gboolean strict;
};
-struct _GstFLVDemuxClass {
+struct _GstFLVDemuxClass
+{
GstElementClass parent_class;
};
GType gst_flv_demux_get_type (void);
G_END_DECLS
-
#endif /* __FLV_DEMUX_H__ */
diff --git a/gst/flv/gstflvparse.c b/gst/flv/gstflvparse.c
index 023df66c..ef0f1f34 100644
--- a/gst/flv/gstflvparse.c
+++ b/gst/flv/gstflvparse.c
@@ -48,6 +48,9 @@ FLV_GET_STRING (const guint8 * data, size_t data_size)
g_return_val_if_fail (data_size >= 3, 0);
string_size = GST_READ_UINT16_BE (data);
+ if (G_UNLIKELY (string_size > data_size)) {
+ return NULL;
+ }
string = g_try_malloc0 (string_size + 1);
if (G_UNLIKELY (!string)) {
@@ -135,6 +138,10 @@ gst_flv_parse_metadata_item (GstFLVDemux * demux, const guint8 * data,
/* Name of the tag */
tag_name = FLV_GET_STRING (data, data_size);
+ if (G_UNLIKELY (!tag_name)) {
+ GST_WARNING_OBJECT (demux, "failed reading tag name");
+ goto beach;
+ }
offset += strlen (tag_name) + 2;
@@ -245,6 +252,7 @@ gst_flv_parse_metadata_item (GstFLVDemux * demux, const guint8 * data,
g_free (tag_name);
+beach:
return offset;
}
@@ -278,8 +286,14 @@ gst_flv_parse_tag_script (GstFLVDemux * demux, const guint8 * data,
GST_DEBUG_OBJECT (demux, "there are %d elements in the array", nb_elems);
while (nb_elems--) {
- offset += gst_flv_parse_metadata_item (demux, data + offset,
+ size_t read = gst_flv_parse_metadata_item (demux, data + offset,
data_size - offset);
+
+ if (G_UNLIKELY (!read)) {
+ GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
+ break;
+ }
+ offset += read;
}
demux->push_tags = TRUE;
@@ -299,13 +313,18 @@ gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
GstFlowReturn ret = GST_FLOW_OK;
GstBuffer *buffer = NULL;
guint32 pts = 0, codec_tag = 0, rate = 0, width = 0, channels = 0;
- guint32 codec_data = 0;
+ guint32 codec_data = 0, pts_ext = 0;
guint8 flags = 0;
GST_LOG_OBJECT (demux, "parsing an audio tag");
/* Grab information about audio tag */
pts = FLV_GET_BEUI24 (data, data_size);
+ /* read the pts extension to 32 bits integer */
+ pts_ext = GST_READ_UINT8 (data + 3);
+ /* Combine them */
+ pts |= pts_ext << 24;
+ /* Skip the stream id and go directly to the flags */
flags = GST_READ_UINT8 (data + 7);
/* Channels */
@@ -392,6 +411,9 @@ gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
gst_pad_set_caps (demux->audio_pad, caps);
+ GST_DEBUG_OBJECT (demux, "created audio pad with caps %" GST_PTR_FORMAT,
+ caps);
+
gst_caps_unref (caps);
/* Store the caps we have set */
@@ -407,7 +429,14 @@ gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
GST_DEBUG_FUNCPTR (gst_flv_demux_query));
/* We need to set caps before adding */
- gst_element_add_pad (GST_ELEMENT (demux), demux->audio_pad);
+ gst_element_add_pad (GST_ELEMENT (demux),
+ gst_object_ref (demux->audio_pad));
+
+ if ((demux->has_audio & (demux->audio_pad != NULL)) &&
+ (demux->has_video & (demux->video_pad != NULL))) {
+ GST_DEBUG_OBJECT (demux, "emitting no more pads");
+ gst_element_no_more_pads (GST_ELEMENT (demux));
+ }
}
/* Check if caps have changed */
@@ -468,9 +497,14 @@ gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
GST_WARNING_OBJECT (demux, "failed allocating a %d bytes buffer",
demux->tag_data_size);
+ if (ret == GST_FLOW_NOT_LINKED) {
+ demux->audio_linked = FALSE;
+ }
goto beach;
}
+ demux->audio_linked = TRUE;
+
/* Fill buffer with data */
GST_BUFFER_TIMESTAMP (buffer) = pts * GST_MSECOND;
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
@@ -578,10 +612,10 @@ gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
caps = gst_caps_new_simple ("video/x-flash-video", NULL);
break;
case 4:
- caps = gst_caps_new_simple ("video/x-vp6", NULL);
+ caps = gst_caps_new_simple ("video/x-vp6-flash", NULL);
break;
case 5:
- caps = gst_caps_new_simple ("video/x-vp6", NULL);
+ caps = gst_caps_new_simple ("video/x-vp6-flash", NULL);
break;
default:
GST_WARNING_OBJECT (demux, "unsupported video codec tag %d", codec_tag);
@@ -597,6 +631,9 @@ gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
gst_pad_set_caps (demux->video_pad, caps);
+ GST_DEBUG_OBJECT (demux, "created video pad with caps %" GST_PTR_FORMAT,
+ caps);
+
gst_caps_unref (caps);
/* Store the caps we have set */
@@ -609,7 +646,14 @@ gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
GST_DEBUG_FUNCPTR (gst_flv_demux_query));
/* We need to set caps before adding */
- gst_element_add_pad (GST_ELEMENT (demux), demux->video_pad);
+ gst_element_add_pad (GST_ELEMENT (demux),
+ gst_object_ref (demux->video_pad));
+
+ if ((demux->has_audio & (demux->audio_pad != NULL)) &&
+ (demux->has_video & (demux->video_pad != NULL))) {
+ GST_DEBUG_OBJECT (demux, "emitting no more pads");
+ gst_element_no_more_pads (GST_ELEMENT (demux));
+ }
}
/* Check if caps have changed */
@@ -667,9 +711,14 @@ gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
GST_WARNING_OBJECT (demux, "failed allocating a %d bytes buffer",
demux->tag_data_size);
+ if (ret == GST_FLOW_NOT_LINKED) {
+ demux->video_linked = FALSE;
+ }
goto beach;
}
+ demux->video_linked = TRUE;
+
/* Fill buffer with data */
GST_BUFFER_TIMESTAMP (buffer) = pts * GST_MSECOND;
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
@@ -779,6 +828,8 @@ gst_flv_parse_header (GstFLVDemux * demux, const guint8 * data,
{
guint8 flags = data[0];
+ demux->has_video = demux->has_audio = FALSE;
+
if (flags & 1) {
GST_DEBUG_OBJECT (demux, "there is a video stream");
demux->has_video = TRUE;
diff --git a/gst/flv/gstflvparse.h b/gst/flv/gstflvparse.h
index 027aaeda..7b9d498e 100644
--- a/gst/flv/gstflvparse.h
+++ b/gst/flv/gstflvparse.h
@@ -16,15 +16,14 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
-
+
#ifndef __FLV_PARSE_H__
#define __FLV_PARSE_H__
#include "gstflvdemux.h"
G_BEGIN_DECLS
-
-GstFlowReturn gst_flv_parse_tag_script (GstFLVDemux * demux,
+ GstFlowReturn gst_flv_parse_tag_script (GstFLVDemux * demux,
const guint8 * data, size_t data_size);
GstFlowReturn gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
@@ -32,7 +31,7 @@ GstFlowReturn gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
GstFlowReturn gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
size_t data_size);
-
+
GstFlowReturn gst_flv_parse_tag_type (GstFLVDemux * demux, const guint8 * data,
size_t data_size);
@@ -40,5 +39,4 @@ GstFlowReturn gst_flv_parse_header (GstFLVDemux * demux, const guint8 * data,
size_t data_size);
G_END_DECLS
-
#endif /* __FLV_PARSE_H__ */