}
static void
-gst_asf_demux_reset (GstASFDemux * demux)
+gst_asf_demux_reset (GstASFDemux * demux, gboolean chain_reset)
{
GST_LOG_OBJECT (demux, "resetting");
gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
demux->segment_running = FALSE;
- if (demux->adapter) {
+ if (demux->adapter && !chain_reset) {
gst_adapter_clear (demux->adapter);
g_object_unref (demux->adapter);
demux->adapter = NULL;
demux->first_ts = GST_CLOCK_TIME_NONE;
demux->segment_ts = GST_CLOCK_TIME_NONE;
demux->in_gap = 0;
- gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
+ if (!chain_reset)
+ gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
demux->state = GST_ASF_DEMUX_STATE_HEADER;
demux->seekable = FALSE;
demux->broadcast = FALSE;
demux->sidx_entries = NULL;
demux->speed_packets = 1;
+
+ if (chain_reset) {
+ GST_LOG_OBJECT (demux, "Restarting");
+ gst_segment_init (&demux->segment, GST_FORMAT_TIME);
+ demux->need_newsegment = TRUE;
+ demux->segment_running = FALSE;
+ demux->accurate = FALSE;
+ demux->metadata = gst_caps_new_empty ();
+ demux->global_metadata = gst_structure_empty_new ("metadata");
+ demux->data_size = 0;
+ demux->data_offset = 0;
+ demux->index_offset = 0;
+ }
}
static void
gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
/* set initial state */
- gst_asf_demux_reset (demux);
+ gst_asf_demux_reset (demux, FALSE);
}
static gboolean
guint64 size;
} AsfObject;
+
+/* expect is true when the user is expeting an object,
+ * when false, it will give no warnings if the object
+ * is not identified
+ */
static gboolean
asf_demux_peek_object (GstASFDemux * demux, const guint8 * data,
- guint data_len, AsfObject * object)
+ guint data_len, AsfObject * object, gboolean expect)
{
ASFGuid guid;
/* FIXME: make asf_demux_identify_object_guid() */
object->id = gst_asf_demux_identify_guid (asf_object_guids, &guid);
- if (object->id == ASF_OBJ_UNDEFINED) {
+ if (object->id == ASF_OBJ_UNDEFINED && expect) {
GST_WARNING_OBJECT (demux, "Unknown object %08x-%08x-%08x-%08x",
guid.v1, guid.v2, guid.v3, guid.v4);
}
if (cdata == NULL)
goto need_more_data;
- asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj);
+ asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
if (obj.id != ASF_OBJ_HEADER)
goto wrong_type;
GstFlowReturn flow;
AsfObject obj;
- asf_demux_peek_object (demux, GST_BUFFER_DATA (buf), 16 + 8, &obj);
+ asf_demux_peek_object (demux, GST_BUFFER_DATA (buf), 16 + 8, &obj, TRUE);
gst_buffer_replace (&buf, NULL);
/* check for sanity */
{
AsfObject obj;
- asf_demux_peek_object (demux, data, 50, &obj);
+ asf_demux_peek_object (demux, data, 50, &obj, TRUE);
if (obj.id != ASF_OBJ_DATA) {
GST_WARNING_OBJECT (demux, "headers not followed by a DATA object");
return FALSE;
if (!gst_asf_demux_pull_data (demux, 0, 16 + 8, &buf, NULL))
goto read_failed;
- asf_demux_peek_object (demux, GST_BUFFER_DATA (buf), 16 + 8, &obj);
+ asf_demux_peek_object (demux, GST_BUFFER_DATA (buf), 16 + 8, &obj, TRUE);
gst_buffer_replace (&buf, NULL);
if (obj.id != ASF_OBJ_HEADER)
}
}
+#define GST_ASF_DEMUX_CHECK_HEADER_YES 0
+#define GST_ASF_DEMUX_CHECK_HEADER_NO 1
+#define GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA 2
+
+static gint
+gst_asf_demux_check_header (GstASFDemux * demux)
+{
+ AsfObject obj;
+ guint8 *cdata = (guint8 *) gst_adapter_peek (demux->adapter,
+ ASF_OBJECT_HEADER_SIZE);
+ if (cdata == NULL) /* need more data */
+ return GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA;
+
+ asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, FALSE);
+ if (obj.id != ASF_OBJ_HEADER) {
+ return GST_ASF_DEMUX_CHECK_HEADER_NO;
+ } else {
+ return GST_ASF_DEMUX_CHECK_HEADER_YES;
+ }
+}
+
static GstFlowReturn
gst_asf_demux_chain (GstPad * pad, GstBuffer * buf)
{
gst_adapter_push (demux->adapter, buf);
switch (demux->state) {
+ case GST_ASF_DEMUX_STATE_INDEX:{
+ gint result = gst_asf_demux_check_header (demux);
+ if (result == GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA) /* need more data */
+ break;
+
+ if (result == GST_ASF_DEMUX_CHECK_HEADER_NO) {
+ /* we don't care about this, probably an index */
+ /* TODO maybe would be smarter to skip all the indices
+ * until we got a new header or EOS to decide */
+ GST_LOG_OBJECT (demux, "Received index object, its EOS");
+ goto eos;
+ } else {
+ GST_INFO_OBJECT (demux, "Chained asf starting");
+ /* cleanup and get ready for a chained asf */
+ gst_asf_demux_reset (demux, TRUE);
+ /* fall through */
+ }
+ }
case GST_ASF_DEMUX_STATE_HEADER:{
ret = gst_asf_demux_chain_headers (demux);
if (demux->state != GST_ASF_DEMUX_STATE_DATA)
while (gst_adapter_available (demux->adapter) >= data_size) {
GstBuffer *buf;
- /* do not overshoot data section when streaming */
- if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
- && demux->packet >= demux->num_packets))
- goto eos;
+ /* we don't know the length of the stream
+ * check for a chained asf everytime */
+ if (demux->num_packets == 0) {
+ gint result = gst_asf_demux_check_header (demux);
+
+ if (result == GST_ASF_DEMUX_CHECK_HEADER_YES) {
+ GST_INFO_OBJECT (demux, "Chained asf starting");
+ /* cleanup and get ready for a chained asf */
+ gst_asf_demux_reset (demux, TRUE);
+ break;
+ }
+ } else if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
+ && demux->packet >= demux->num_packets)) {
+ /* do not overshoot data section when streaming */
+ break;
+ }
buf = gst_adapter_take_buffer (demux->adapter, data_size);
if (demux->packet >= 0)
++demux->packet;
}
+ if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
+ && demux->packet >= demux->num_packets)) {
+ demux->state = GST_ASF_DEMUX_STATE_INDEX;
+ }
break;
}
default:
}
/* get size of the stream object */
- if (!asf_demux_peek_object (demux, data, size, &stream_obj))
+ if (!asf_demux_peek_object (demux, data, size, &stream_obj, TRUE))
goto not_enough_data;
if (stream_obj.id != ASF_OBJ_STREAM)
if (*p_size < ASF_OBJECT_HEADER_SIZE)
return ASF_FLOW_NEED_MORE_DATA;
- asf_demux_peek_object (demux, *p_data, ASF_OBJECT_HEADER_SIZE, &obj);
+ asf_demux_peek_object (demux, *p_data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, p_data, p_size);
obj_data_size = obj.size - ASF_OBJECT_HEADER_SIZE;
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
case GST_STATE_CHANGE_READY_TO_NULL:
- gst_asf_demux_reset (demux);
+ gst_asf_demux_reset (demux, FALSE);
break;
default:
break;