diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2008-11-20 21:31:19 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2008-11-20 21:31:19 +0000 |
commit | 3838bdb40dc2c52d2f693fa6db8ee6fdca344ca6 (patch) | |
tree | 41e59c31012e790868ffe60b80b9501f0e91b366 | |
parent | 4a8c73e6946ae0e2d4199b4281277a80ea1f7e45 (diff) |
gst/asfdemux/gstasfdemux.c: Remove duplicate and broken code for the streaming case and simply reuse the much better ...
Original commit message from CVS:
* gst/asfdemux/gstasfdemux.c: (gst_asf_demux_chain):
Remove duplicate and broken code for the streaming case and simply reuse
the much better working pull based code. Fixes #560348.
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | gst/asfdemux/gstasfdemux.c | 757 |
2 files changed, 64 insertions, 699 deletions
@@ -1,3 +1,9 @@ +2008-11-20 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_chain): + Remove duplicate and broken code for the streaming case and simply reuse + the much better working pull based code. Fixes #560348. + 2008-11-20 Jan Schmidt <jan.schmidt@sun.com> * configure.ac: diff --git a/gst/asfdemux/gstasfdemux.c b/gst/asfdemux/gstasfdemux.c index 392640d4..54e0fa39 100644 --- a/gst/asfdemux/gstasfdemux.c +++ b/gst/asfdemux/gstasfdemux.c @@ -98,8 +98,6 @@ gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux); static void gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux); static gboolean gst_asf_demux_pull_headers (GstASFDemux * demux); static void gst_asf_demux_pull_indices (GstASFDemux * demux); -static GstFlowReturn gst_asf_demux_handle_data (GstASFDemux * demux, - guint8 ** p_data, guint64 * p_size); static void gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * asf); static gboolean gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data); @@ -724,92 +722,6 @@ gst_asf_demux_aggregate_flow_return (GstASFDemux * demux) return GST_FLOW_NOT_LINKED; } -static GstFlowReturn -gst_asf_demux_chain (GstPad * pad, GstBuffer * buf) -{ - GstFlowReturn ret = GST_FLOW_OK; - GstASFDemux *demux; - - demux = GST_ASF_DEMUX (GST_PAD_PARENT (pad)); - - GST_LOG_OBJECT (demux, "buffer: size=%u, offset=%" G_GINT64_FORMAT, - GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf)); - - if (GST_BUFFER_IS_DISCONT (buf)) - gst_asf_demux_reset_stream_state_after_discont (demux); - - gst_adapter_push (demux->adapter, buf); - - switch (demux->state) { - case GST_ASF_DEMUX_STATE_HEADER:{ - ret = gst_asf_demux_chain_headers (demux); - if (demux->state != GST_ASF_DEMUX_STATE_DATA) - break; - /* otherwise fall through */ - } - case GST_ASF_DEMUX_STATE_DATA:{ - - if (demux->need_newsegment) { - GST_DEBUG_OBJECT (demux, "sending new-segment event from %" - GST_SEGMENT_FORMAT, &demux->segment); - - /* FIXME: check last parameter, streams may have non-zero start */ - gst_asf_demux_send_event_unlocked (demux, - gst_event_new_new_segment (FALSE, demux->segment.rate, - GST_FORMAT_TIME, demux->segment.start, demux->segment.stop, - demux->segment.start)); - - demux->need_newsegment = FALSE; - demux->segment_running = TRUE; - } - - while (gst_adapter_available (demux->adapter) >= demux->packet_size) { - guint64 data_size; - guint8 *data; - - data_size = demux->packet_size; - data = (guint8 *) gst_adapter_peek (demux->adapter, data_size); - g_assert (data != NULL); - - ret = gst_asf_demux_handle_data (demux, &data, &data_size); - - /* FIXME: check if this can happen, shouldn't really, should it? */ - if (ret == ASF_FLOW_NEED_MORE_DATA) { - GST_DEBUG_OBJECT (demux, "not flushing, flow was need-more-data"); - - /* FIXME: we always know the packet size, this code is weird */ - /* if we know the packet size and still do a - * short read, then something is fishy */ -/* - GST_ELEMENT_ERROR (demux, STREAM, DEMUX, - ("Error parsing packet"), - ("Unexpected short read in packet at offset %" G_GINT64_FORMAT, - gst_asf_demux_get_current_offset (demux, NULL))); - - ret = GST_FLOW_ERROR; -*/ - gst_adapter_flush (demux->adapter, demux->packet_size); - ret = GST_FLOW_OK; - break; /* bail out */ - } else { - GST_DEBUG ("flushing packet (%u bytes)", demux->packet_size); - gst_adapter_flush (demux->adapter, demux->packet_size); - } - } - break; - } - default: - g_assert_not_reached (); - } - - /* FIXME: eradicate ASF_FLOW_NEED_MORE_DATA */ - - if (ret != GST_FLOW_OK) - GST_DEBUG_OBJECT (demux, "flow: %s", gst_flow_get_name (ret)); - - return ret; -} - static gboolean gst_asf_demux_pull_data (GstASFDemux * demux, guint64 offset, guint size, GstBuffer ** p_buf, GstFlowReturn * p_flow) @@ -1393,6 +1305,64 @@ parse_error: } } +static GstFlowReturn +gst_asf_demux_chain (GstPad * pad, GstBuffer * buf) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstASFDemux *demux; + + demux = GST_ASF_DEMUX (GST_PAD_PARENT (pad)); + + GST_LOG_OBJECT (demux, "buffer: size=%u, offset=%" G_GINT64_FORMAT, + GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf)); + + if (GST_BUFFER_IS_DISCONT (buf)) + gst_asf_demux_reset_stream_state_after_discont (demux); + + gst_adapter_push (demux->adapter, buf); + + switch (demux->state) { + case GST_ASF_DEMUX_STATE_HEADER:{ + ret = gst_asf_demux_chain_headers (demux); + if (demux->state != GST_ASF_DEMUX_STATE_DATA) + break; + /* otherwise fall through */ + } + case GST_ASF_DEMUX_STATE_DATA: + { + guint64 data_size; + + data_size = demux->packet_size; + + while (gst_adapter_available (demux->adapter) >= data_size) { + GstBuffer *buf; + + buf = gst_adapter_take_buffer (demux->adapter, data_size); + + /* FIXME: maybe we should just skip broken packets and error out only + * after a few broken packets in a row? */ + if (!gst_asf_demux_parse_packet (demux, buf)) { + GST_WARNING_OBJECT (demux, "Parse error"); + } + + gst_buffer_unref (buf); + + ret = gst_asf_demux_push_complete_payloads (demux, FALSE); + + ++demux->packet; + } + break; + } + default: + g_assert_not_reached (); + } + + if (ret != GST_FLOW_OK) + GST_DEBUG_OBJECT (demux, "flow: %s", gst_flow_get_name (ret)); + + return ret; +} + static inline gboolean gst_asf_demux_skip_bytes (guint num_bytes, guint8 ** p_data, guint64 * p_size) { @@ -1561,18 +1531,6 @@ gst_asf_demux_get_guid (ASFGuid * guid, guint8 ** p_data, guint64 * p_size) } static gboolean -gst_asf_demux_get_obj_data_correction (asf_obj_data_correction * object, - guint8 ** p_data, guint64 * p_size) -{ - if (*p_size < (1 + 1)) - return FALSE; - - object->type = gst_asf_demux_get_uint8 (p_data, p_size); - object->cycle = gst_asf_demux_get_uint8 (p_data, p_size); - return TRUE; -} - -static gboolean gst_asf_demux_get_stream_audio (asf_stream_audio * audio, guint8 ** p_data, guint64 * p_size) { @@ -3241,605 +3199,6 @@ gst_asf_demux_send_event_unlocked (GstASFDemux * demux, GstEvent * event) return ret; } -static GstFlowReturn -gst_asf_demux_push_buffer (GstASFDemux * demux, AsfStream * stream, - GstBuffer * buf) -{ - buf = gst_buffer_make_metadata_writable (buf); - - /* need to send tags? */ - if (stream->pending_tags) { - GST_LOG_OBJECT (stream->pad, "tags %" GST_PTR_FORMAT, stream->pending_tags); - gst_element_found_tags_for_pad (GST_ELEMENT (demux), stream->pad, - stream->pending_tags); - stream->pending_tags = NULL; - } - - /* don't set the same time stamp on multiple consecutive outgoing - * video buffers, set it on the first one and set NONE on the others, - * it's the decoder's job to fill the missing bits properly */ - if (stream->is_video && GST_BUFFER_TIMESTAMP_IS_VALID (buf) && - GST_BUFFER_TIMESTAMP (buf) == stream->last_buffer_timestamp) { - GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE; - } - - /* make sure segment.last_stop is continually increasing */ - if (GST_BUFFER_TIMESTAMP_IS_VALID (buf) && - demux->segment.last_stop < (gint64) GST_BUFFER_TIMESTAMP (buf)) { - gst_segment_set_last_stop (&demux->segment, GST_FORMAT_TIME, - GST_BUFFER_TIMESTAMP (buf)); - } - - if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) - stream->last_buffer_timestamp = GST_BUFFER_TIMESTAMP (buf); - - gst_buffer_set_caps (buf, stream->caps); - - GST_LOG_OBJECT (stream->pad, "pushing buffer, ts=%" GST_TIME_FORMAT " %s", - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), - (stream->discont) ? "discont" : ""); - - if (stream->discont) { - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); - stream->discont = FALSE; - } - - stream->last_flow = gst_pad_push (stream->pad, buf); - - return stream->last_flow; -} - -static GstFlowReturn -gst_asf_demux_process_chunk (GstASFDemux * demux, - asf_packet_info * packet_info, asf_segment_info * segment_info, - guint8 ** p_data, guint64 * p_size) -{ - GstFlowReturn ret = GST_FLOW_OK; - AsfStream *stream; - GstBuffer *buffer; - - stream = gst_asf_demux_get_stream (demux, segment_info->stream_number); - if (stream == NULL) { - GST_WARNING ("invalid stream number %d", segment_info->stream_number); - if (!gst_asf_demux_skip_bytes (segment_info->chunk_size, p_data, p_size)) - ret = ASF_FLOW_NEED_MORE_DATA; - goto done; - } - - GST_DEBUG ("Processing %s chunk of size %u (frag_offset=%d)", - GST_PAD_NAME (stream->pad), segment_info->chunk_size, - stream->frag_offset); - - if (segment_info->frag_offset == 0) { - /* new packet */ - stream->sequence = segment_info->sequence; - if (!GST_CLOCK_TIME_IS_VALID (stream->first_pts)) - stream->first_pts = segment_info->frag_timestamp - demux->preroll; - demux->pts = - segment_info->frag_timestamp - demux->preroll - stream->first_pts; - - /* - if (stream->is_video) { - GST_DEBUG ("%s: demux->pts=%lld (frag_timestamp=%ld, preroll=%lld)", - GST_PAD_NAME (stream->pad), demux->pts, - segment_info->frag_timestamp, demux->preroll); - } - */ - - if (!gst_asf_demux_get_buffer (&buffer, segment_info->chunk_size, - p_data, p_size)) { - return ASF_FLOW_NEED_MORE_DATA; - } - - GST_DEBUG ("BUFFER: Copied stream to buffer %p", buffer); - stream->payload = buffer; - } else { - GST_DEBUG ("segment_info->sequence=%d, stream->sequence=%d," - " segment_info->frag_offset=%d, stream->frag_offset=%d", - segment_info->sequence, stream->sequence, segment_info->frag_offset, - stream->frag_offset); - - if (segment_info->sequence == stream->sequence && - segment_info->frag_offset == stream->frag_offset) { - GstBuffer *new_buffer; - - /* continuing packet */ - GST_INFO ("continuation packet"); - - if (!gst_asf_demux_get_buffer (&buffer, segment_info->chunk_size, - p_data, p_size)) { - return ASF_FLOW_NEED_MORE_DATA; - } - - GST_DEBUG ("copied stream to buffer %p", buffer); - - new_buffer = gst_buffer_merge (stream->payload, buffer); - GST_DEBUG_OBJECT (demux, - "BUFFER: Merged new_buffer (%p - %d) from stream->payload (%p - %d)" - " and buffer (%p - %d)", new_buffer, - GST_MINI_OBJECT_REFCOUNT_VALUE (new_buffer), stream->payload, - GST_MINI_OBJECT_REFCOUNT_VALUE (stream->payload), buffer, - GST_MINI_OBJECT_REFCOUNT_VALUE (buffer)); - gst_buffer_unref (stream->payload); - gst_buffer_unref (buffer); - stream->payload = new_buffer; - } else { - /* cannot continue current packet: free it */ - if (stream->frag_offset != 0) { - /* cannot create new packet */ - GST_DEBUG ("BUFFER: Freeing stream->payload (%p)", stream->payload); - gst_buffer_unref (stream->payload); -#if 0 - /* FIXME: is this right/needed? we already do that below, no? */ - packet_info->size_left -= segment_info->chunk_size; -#endif - stream->frag_offset = 0; - } - demux->pts = - segment_info->frag_timestamp - demux->preroll - stream->first_pts; - - /* - if (stream->is_video) { - GST_DEBUG ("%s: demux->pts=%lld (frag_timestamp=%ld, preroll=%lld)", - GST_PAD_NAME (stream->pad), demux->pts, - segment_info->frag_timestamp, demux->preroll); - } - */ - - goto done; -#if 0 - /* FIXME: where did this come from / fit in ? */ - return TRUE; - else { - /* create new packet */ - stream->sequence = segment_info->sequence; - } -#endif - } - } - - stream->frag_offset += segment_info->chunk_size; - - GST_DEBUG ("frag_offset = %d segment_size = %d ", stream->frag_offset, - segment_info->segment_size); - - if (stream->frag_offset < segment_info->segment_size) { - /* We don't have the whole packet yet */ - } else { - /* We have the whole packet now so we should push the packet to - the src pad now. First though we should check if we need to do - descrambling */ - if (demux->span > 1) { - gst_asf_demux_descramble_buffer (demux, stream, &stream->payload); - } - - if (stream->is_video) { - GST_DEBUG ("%s: demux->pts=%lld=%" GST_TIME_FORMAT - ", stream->last_pts=%lld=%" GST_TIME_FORMAT, - GST_PAD_NAME (stream->pad), demux->pts, - GST_TIME_ARGS (GST_MSECOND * demux->pts), stream->last_pts, - GST_TIME_ARGS (GST_MSECOND * stream->last_pts)); - } - - /* FIXME: last_pts is not a GstClockTime and not in nanoseconds, so - * this is not really 100% right ... */ - if (demux->pts >= stream->last_pts || - !GST_CLOCK_TIME_IS_VALID (stream->last_pts)) { - stream->last_pts = demux->pts; - } - - GST_BUFFER_TIMESTAMP (stream->payload) = GST_MSECOND * stream->last_pts; - - GST_DEBUG ("sending stream %d of size %d, ts=%" GST_TIME_FORMAT, - stream->id, segment_info->chunk_size, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (stream->payload))); - - if (!stream->fps_known) { - if (!stream->cache) { - stream->cache = stream->payload; - } else { - gdouble fps; - gint64 diff; - gint num, denom; - - /* why is all this needed anyway? (tpm) */ - diff = GST_BUFFER_TIMESTAMP (stream->payload) - - GST_BUFFER_TIMESTAMP (stream->cache); - - fps = (gdouble) GST_SECOND / diff; - - /* artificial cap */ - if (fps >= 50.0) { - num = 50; - denom = 1; - } else if (fps <= 5.0) { - num = 5; - denom = 1; - } else { - /* crack alert */ - num = (gint) GST_SECOND; - while (diff > G_MAXINT) { - num = num >> 1; - diff = diff >> 1; - } - denom = (gint) diff; - } - stream->fps_known = TRUE; - stream->caps = gst_caps_make_writable (stream->caps); - gst_caps_set_simple (stream->caps, - "framerate", GST_TYPE_FRACTION, num, denom, NULL); - GST_DEBUG ("set up stream with fps %d/%d", num, denom); - gst_pad_use_fixed_caps (stream->pad); - gst_pad_set_caps (stream->pad, stream->caps); - - ret = gst_asf_demux_push_buffer (demux, stream, stream->cache); - stream->cache = NULL; - - ret = gst_asf_demux_push_buffer (demux, stream, stream->payload); - stream->payload = NULL; - } - } else { - ret = gst_asf_demux_push_buffer (demux, stream, stream->payload); - stream->payload = NULL; - } - - stream->frag_offset = 0; - } - -done: - - packet_info->size_left -= segment_info->chunk_size; - - return ret; -} - -static GstFlowReturn -gst_asf_demux_process_segment (GstASFDemux * demux, - asf_packet_info * packet_info, guint8 ** p_data, guint64 * p_size) -{ - GstFlowReturn ret = GST_FLOW_OK; - asf_segment_info segment_info; - gboolean has_key_frame; - guint64 start_size; - guint32 replic_size; - guint32 time_start; - guint32 frag_size; - guint32 rsize; - guint8 time_delta; - guint8 byte; - - start_size = *p_size; - - if (*p_size < 1) - return ASF_FLOW_NEED_MORE_DATA; - - byte = gst_asf_demux_get_uint8 (p_data, p_size); - segment_info.stream_number = byte & 0x7f; - has_key_frame = ((byte & 0x80) == 0x80); /* FIXME: use this somewhere? */ - - GST_INFO ("processing segment for stream %u%s", segment_info.stream_number, - (has_key_frame) ? " (has keyframe)" : ""); - - /* FIXME: check (doesn't work) */ -#if 0 - { - AsfStream *stream; - - stream = gst_asf_demux_get_stream (demux, segment_info.stream_number); - if (stream && stream->last_pts == GST_CLOCK_TIME_NONE && - stream->is_video && !has_key_frame) { - g_print ("skipping segment, waiting for a key unit\n"); - if (!gst_asf_demux_skip_bytes (segment_info.segment_size - 1, p_data, - p_size)) - return ASF_FLOW_NEED_MORE_DATA; - packet_info->size_left -= segment_info.segment_size; - return GST_FLOW_OK; - } - } -#endif - - { - const guint lengths[4] = { 0, 1, 2, 4 }; - guint needed; - - needed = lengths[packet_info->seqtype] - + lengths[packet_info->fragoffsettype] - + lengths[packet_info->replicsizetype]; - - if (*p_size < needed) - return ASF_FLOW_NEED_MORE_DATA; - } - - segment_info.sequence = - gst_asf_demux_get_var_length (packet_info->seqtype, p_data, p_size); - segment_info.frag_offset = - gst_asf_demux_get_var_length (packet_info->fragoffsettype, p_data, - p_size); - replic_size = - gst_asf_demux_get_var_length (packet_info->replicsizetype, p_data, - p_size); - - GST_DEBUG ("sequence=%u, frag_offset=%u, replic_size=%u", - segment_info.sequence, segment_info.frag_offset, replic_size); - - if (replic_size > 1) { - segment_info.compressed = FALSE; - - /* It's uncompressed with replic data */ - if (*p_size < (4 + 4)) - goto short_repdata; - - segment_info.segment_size = gst_asf_demux_get_uint32 (p_data, p_size); - segment_info.frag_timestamp = gst_asf_demux_get_uint32 (p_data, p_size); - - GST_LOG ("frag_timestamp: %" GST_TIME_FORMAT, - GST_TIME_ARGS (segment_info.frag_timestamp * GST_MSECOND)); - - if (replic_size > 8) { - if (!gst_asf_demux_skip_bytes ((replic_size - 8), p_data, p_size)) - return ASF_FLOW_NEED_MORE_DATA; - } - } else if (replic_size == 1) { - /* It's compressed */ - segment_info.compressed = TRUE; - if (*p_size < 1) - return ASF_FLOW_NEED_MORE_DATA; - time_delta = gst_asf_demux_get_uint8 (p_data, p_size); - GST_DEBUG ("time_delta = %u", time_delta); - - time_start = segment_info.frag_offset; - segment_info.frag_offset = 0; - segment_info.frag_timestamp = time_start; /* was: demux->timestamp */ - } else { - segment_info.compressed = FALSE; - - time_start = segment_info.frag_offset; - segment_info.frag_offset = 0; - segment_info.frag_timestamp = time_start; /* was: demux->timestamp */ - } - - GST_DEBUG ("multiple = %u, compressed = %u", - packet_info->multiple, segment_info.compressed); - - if (packet_info->multiple) { - const guint lengths[4] = { 0, 1, 2, 4 }; - - if (*p_size < lengths[packet_info->segsizetype]) - return ASF_FLOW_NEED_MORE_DATA; - - frag_size = gst_asf_demux_get_var_length (packet_info->segsizetype, - p_data, p_size); - } else { - frag_size = packet_info->size_left - (start_size - *p_size); - } - - rsize = start_size - *p_size; - - packet_info->size_left -= rsize; - - GST_DEBUG ("size left = %u, frag size = %u, rsize = %u", - packet_info->size_left, frag_size, rsize); - - if (segment_info.compressed) { - while (frag_size > 0) { - if (*p_size < 1) - return ASF_FLOW_NEED_MORE_DATA; - byte = gst_asf_demux_get_uint8 (p_data, p_size); - packet_info->size_left--; - segment_info.chunk_size = byte; - segment_info.segment_size = segment_info.chunk_size; - - if (segment_info.chunk_size > packet_info->size_left) { - return ASF_FLOW_NEED_MORE_DATA; - /* or is this an error? - * GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), - * ("Payload chunk overruns packet size.")); - * return GST_FLOW_ERROR; */ - } - - ret = gst_asf_demux_process_chunk (demux, packet_info, &segment_info, - p_data, p_size); - - if (ret != GST_FLOW_OK) - break; - - if (segment_info.chunk_size < frag_size) - frag_size -= segment_info.chunk_size + 1; - else { -/* - GST_ELEMENT_ERROR (demux, STREAM, DEMUX, - ("Invalid data in stream"), - ("Invalid fragment size indicator in segment")); - ret = GST_FLOW_ERROR; -*/ - return ASF_FLOW_NEED_MORE_DATA; - } - } - } else { - segment_info.chunk_size = frag_size; - ret = gst_asf_demux_process_chunk (demux, packet_info, &segment_info, - p_data, p_size); - } - - return ret; - -/* ERRORS */ -short_repdata: - { - if (replic_size < 8) { - GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), - ("payload has replicated data, but size is less than 8")); - } else { - GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), - ("payload has %u bytes of replicated data, but size is only %u", - replic_size, (guint) * p_size)); - } - return GST_FLOW_ERROR; - } -} - -static GstFlowReturn -gst_asf_demux_handle_data (GstASFDemux * demux, guint8 ** p_data, - guint64 * p_size) -{ - asf_packet_info packet_info; - gboolean correction; - guint64 start_size; - guint32 sequence; - guint32 packet_length; - guint32 rsize; - guint16 duration; - guint8 num_segments; - guint8 segment; - guint8 flags; - guint8 property; - - start_size = *p_size; - - GST_LOG ("processing packet %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, - demux->packet + 1, demux->num_packets); - - if (demux->num_packets > 0 && demux->packet >= demux->num_packets) { - GST_LOG_OBJECT (demux, "reached EOS"); - return GST_FLOW_UNEXPECTED; - } - - ++demux->packet; - - if (*p_size < 1) { - GST_WARNING ("unexpected end of data"); /* unexpected, why? */ - return ASF_FLOW_NEED_MORE_DATA; - } - - correction = ((gst_asf_demux_get_uint8 (p_data, p_size) & 0x80) == 0x80); - - /* Uses error correction? */ - if (correction) { - asf_obj_data_correction corr_obj; - - GST_DEBUG ("data has error correction"); - if (!gst_asf_demux_get_obj_data_correction (&corr_obj, p_data, p_size)) { - GST_WARNING ("unexpected end of data"); - return ASF_FLOW_NEED_MORE_DATA; - } - } - - /* Read the packet flags */ - if (*p_size < (1 + 1)) { - GST_WARNING ("unexpected end of data"); - return ASF_FLOW_NEED_MORE_DATA; - } - flags = gst_asf_demux_get_uint8 (p_data, p_size); - property = gst_asf_demux_get_uint8 (p_data, p_size); - - packet_info.multiple = ((flags & 0x01) == 0x01); - - { - const guint lengths[4] = { 0, 1, 2, 4 }; - guint needed; - - needed = lengths[(flags >> 5) & 0x03] - + lengths[(flags >> 3) & 0x03] - + lengths[(flags >> 1) & 0x03]; - - if (*p_size < needed) - return ASF_FLOW_NEED_MORE_DATA; - } - - packet_length = - gst_asf_demux_get_var_length ((flags >> 5) & 0x03, p_data, p_size); - - sequence = gst_asf_demux_get_var_length ((flags >> 1) & 0x03, p_data, p_size); - - packet_info.padsize = - gst_asf_demux_get_var_length ((flags >> 3) & 0x03, p_data, p_size); - - if (packet_length == 0) - packet_length = demux->packet_size; - - GST_DEBUG ("multiple = %u, sequence = %u, padsize = %u, " - "packet length = %u", packet_info.multiple, sequence, - packet_info.padsize, packet_length); - - /* Read the property flags */ - packet_info.replicsizetype = property & 0x03; - packet_info.fragoffsettype = (property >> 2) & 0x03; - packet_info.seqtype = (property >> 4) & 0x03; - - if (*p_size < (4 + 2)) { - GST_WARNING ("unexpected end of data"); - return ASF_FLOW_NEED_MORE_DATA; - } - - /* FIXME: isn't this the send time, ie. not the presentation time? (tpm) */ - demux->timestamp = gst_asf_demux_get_uint32 (p_data, p_size); - duration = gst_asf_demux_get_uint16 (p_data, p_size); - - GST_DEBUG ("timestamp = %" GST_TIME_FORMAT ", duration = %" GST_TIME_FORMAT, - GST_TIME_ARGS ((gint64) demux->timestamp * GST_MSECOND), - GST_TIME_ARGS ((gint64) duration * GST_MSECOND)); - - /* Are there multiple payloads? */ - if (packet_info.multiple) { - guint8 multi_flags; - - if (*p_size < 1) - return ASF_FLOW_NEED_MORE_DATA; - - multi_flags = gst_asf_demux_get_uint8 (p_data, p_size); - packet_info.segsizetype = (multi_flags >> 6) & 0x03; - num_segments = multi_flags & 0x3f; - } else { - packet_info.segsizetype = 2; - num_segments = 1; - } - - rsize = start_size - *p_size; - - packet_info.size_left = packet_length - packet_info.padsize - rsize; - - GST_DEBUG ("rsize: %u, size left: %u", rsize, packet_info.size_left); - - for (segment = 0; segment < num_segments; ++segment) { - GstFlowReturn ret; - - ret = gst_asf_demux_process_segment (demux, &packet_info, p_data, p_size); - if (ret != GST_FLOW_OK) { - GST_DEBUG ("process_segment %u returned %s", segment, - gst_asf_get_flow_name (ret)); - } - } - - /* Skip the padding */ - if (packet_info.padsize > 0) { - if (*p_size < packet_info.padsize) { - GST_WARNING ("unexpected end of data"); - return ASF_FLOW_NEED_MORE_DATA; - } - - if (!gst_asf_demux_skip_bytes (packet_info.padsize, p_data, p_size)) - return ASF_FLOW_NEED_MORE_DATA; - } - - GST_DEBUG ("remaining size left: %u", packet_info.size_left); - - /* FIXME: this doesn't really make sense, does it? if we don't have enough - * bytes left to skip the stuff at the end and we've already sent out - * buffers, just returning NEED_MORE_DATA isn't really right. Should we - * just throw an error in that case (can it happen with a non-broken - * stream?) */ - if (packet_info.size_left > 0) { - if (!gst_asf_demux_skip_bytes (packet_info.size_left, p_data, p_size)) { - GST_WARNING - ("unexpected end of data, *p_size=%lld,packet_info.size_left=%u", - *p_size, packet_info.size_left); - return ASF_FLOW_NEED_MORE_DATA; - } - } - - return gst_asf_demux_aggregate_flow_return (demux); -} - static const GstQueryType * gst_asf_demux_get_src_query_types (GstPad * pad) { |