From 90431d788ecfa895049790133f60dd62648eab79 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Fri, 24 Nov 2006 07:46:54 +0000 Subject: [PATCH] gst/avi/gstavidemux.c: remove dead code, tweak debugs statements, add comments, use _uint64_scale instead _uint64_sca... Original commit message from CVS: * gst/avi/gstavidemux.c: (gst_avi_demux_index_entry_for_time), (gst_avi_demux_src_convert), (gst_avi_demux_handle_src_query), (gst_avi_demux_peek_chunk), (gst_avi_demux_parse_subindex), (gst_avi_demux_read_subindexes_push), (gst_avi_demux_read_subindexes_pull), (gst_avi_demux_parse_stream), (gst_avi_demux_parse_index), (gst_avi_demux_stream_index), (gst_avi_demux_sync), (gst_avi_demux_next_data_buffer), (gst_avi_demux_massage_index), (gst_avi_demux_calculate_durations_from_index), (gst_avi_demux_stream_header_pull), (gst_avi_demux_do_seek), (gst_avi_demux_handle_seek), (gst_avi_demux_process_next_entry), (gst_avi_demux_stream_data), (gst_avi_demux_loop): remove dead code, tweak debugs statements, add comments, use _uint64_scale instead _uint64_scale_int when using guint64 values, small optimizations, reflow some error handling --- ChangeLog | 18 ++++ gst/avi/gstavidemux.c | 246 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 189 insertions(+), 75 deletions(-) diff --git a/ChangeLog b/ChangeLog index d04cb64..10097b4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2006-11-24 Stefan Kost + + * gst/avi/gstavidemux.c: (gst_avi_demux_index_entry_for_time), + (gst_avi_demux_src_convert), (gst_avi_demux_handle_src_query), + (gst_avi_demux_peek_chunk), (gst_avi_demux_parse_subindex), + (gst_avi_demux_read_subindexes_push), + (gst_avi_demux_read_subindexes_pull), (gst_avi_demux_parse_stream), + (gst_avi_demux_parse_index), (gst_avi_demux_stream_index), + (gst_avi_demux_sync), (gst_avi_demux_next_data_buffer), + (gst_avi_demux_massage_index), + (gst_avi_demux_calculate_durations_from_index), + (gst_avi_demux_stream_header_pull), (gst_avi_demux_do_seek), + (gst_avi_demux_handle_seek), (gst_avi_demux_process_next_entry), + (gst_avi_demux_stream_data), (gst_avi_demux_loop): + remove dead code, tweak debugs statements, add comments, use + _uint64_scale instead _uint64_scale_int when using guint64 values, + small optimizations, reflow some error handling + 2006-11-22 Edward Hervey * po/.cvsignore: diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c index 76469e5..100272f 100644 --- a/gst/avi/gstavidemux.c +++ b/gst/avi/gstavidemux.c @@ -289,6 +289,17 @@ gst_avi_demux_index_next (GstAviDemux * avi, gint stream_nr, gint start) return result; } +/* + * gst_avi_index_entry: + * @avi: Avi object + * @stream_nr: stream number + * @time: seek time position + * @flags: index entry flags to match + * + * Finds the index entry which time is less or equal than the requested time. + * + * Returns: the found index entry or %NULL + */ static gst_avi_index_entry * gst_avi_demux_index_entry_for_time (GstAviDemux * avi, gint stream_nr, guint64 time, guint32 flags) @@ -296,24 +307,24 @@ gst_avi_demux_index_entry_for_time (GstAviDemux * avi, gst_avi_index_entry *entry = NULL, *last_entry = NULL; gint i; - GST_LOG_OBJECT (avi, "stream_nr:%d , time:%" GST_TIME_FORMAT " flags:%d", + GST_LOG_OBJECT (avi, "stream_nr:%d , time:%" GST_TIME_FORMAT " flags:%x", stream_nr, GST_TIME_ARGS (time), flags); i = -1; do { + /* get next entry for given stream */ entry = gst_avi_demux_index_next (avi, stream_nr, i + 1); if (!entry) break; i = entry->index_nr; + if (entry->ts <= time && (entry->flags & flags) == flags) + last_entry = entry; GST_LOG_OBJECT (avi, "looking at entry %d / ts:%" GST_TIME_FORMAT " / dur:%" GST_TIME_FORMAT " flags:%d", i, GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (entry->dur), entry->flags); - if (entry->ts <= time && - (entry->flags & flags) == flags && stream_nr == entry->stream_nr) - last_entry = entry; } while (entry->ts < time); return last_entry; @@ -377,9 +388,8 @@ gst_avi_demux_src_convert (GstPad * pad, case GST_FORMAT_TIME: switch (*dest_format) { case GST_FORMAT_BYTES: - *dest_value = - gst_util_uint64_scale_int (src_value, stream->strf.auds->av_bps, - GST_SECOND); + *dest_value = gst_util_uint64_scale (src_value, + (guint64) stream->strf.auds->av_bps, GST_SECOND); break; case GST_FORMAT_DEFAULT: *dest_value = gst_util_uint64_scale (src_value, stream->strh->rate, @@ -394,8 +404,8 @@ gst_avi_demux_src_convert (GstPad * pad, switch (*dest_format) { case GST_FORMAT_TIME: if (stream->strf.auds->av_bps != 0) { - *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND, - stream->strf.auds->av_bps); + *dest_value = gst_util_uint64_scale (src_value, GST_SECOND, + (guint64) stream->strf.auds->av_bps); } else res = FALSE; break; @@ -407,9 +417,8 @@ gst_avi_demux_src_convert (GstPad * pad, case GST_FORMAT_DEFAULT: switch (*dest_format) { case GST_FORMAT_TIME: - *dest_value = - gst_util_uint64_scale (src_value, - stream->strh->scale * GST_SECOND, stream->strh->rate); + *dest_value = gst_util_uint64_scale (src_value, + stream->strh->scale * GST_SECOND, (guint64) stream->strh->rate); break; default: res = FALSE; @@ -444,7 +453,7 @@ static gboolean gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query) { gboolean res = TRUE; - GstAviDemux *demux = GST_AVI_DEMUX (GST_PAD_PARENT (pad)); + GstAviDemux *avi = GST_AVI_DEMUX (GST_PAD_PARENT (pad)); avi_stream_context *stream = gst_pad_get_element_private (pad); @@ -455,34 +464,37 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query) case GST_QUERY_POSITION:{ gint64 pos = 0; + GST_DEBUG ("pos query for stream %d: frames %d, bytes %" G_GUINT64_FORMAT, + stream->num, stream->current_frame, stream->current_byte); + if (stream->strh->type == GST_RIFF_FCC_auds) { if (stream->is_vbr) { /* VBR */ - pos = gst_util_uint64_scale_int ((gint64) stream->current_frame * - stream->strh->scale, GST_SECOND, stream->strh->rate); - GST_DEBUG_OBJECT (demux, "VBR convert frame %u, time %" + pos = gst_util_uint64_scale ((gint64) stream->current_frame * + stream->strh->scale, GST_SECOND, (guint64) stream->strh->rate); + GST_DEBUG_OBJECT (avi, "VBR convert frame %u, time %" GST_TIME_FORMAT, stream->current_frame, GST_TIME_ARGS (pos)); } else if (stream->strf.auds->av_bps != 0) { /* CBR */ - pos = gst_util_uint64_scale_int (stream->current_byte, GST_SECOND, - stream->strf.auds->av_bps); - GST_DEBUG_OBJECT (demux, + pos = gst_util_uint64_scale (stream->current_byte, GST_SECOND, + (guint64) stream->strf.auds->av_bps); + GST_DEBUG_OBJECT (avi, "CBR convert bytes %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT, stream->current_byte, GST_TIME_ARGS (pos)); } else if (stream->total_frames != 0 && stream->total_bytes != 0) { /* calculate timestamps based on percentage of length */ - guint64 xlen = demux->avih->us_frame * - demux->avih->tot_frames * GST_USECOND; + guint64 xlen = avi->avih->us_frame * + avi->avih->tot_frames * GST_USECOND; if (stream->is_vbr) { pos = gst_util_uint64_scale (xlen, stream->current_frame, stream->total_frames); - GST_DEBUG_OBJECT (demux, "VBR perc convert frame %u, time %" + GST_DEBUG_OBJECT (avi, "VBR perc convert frame %u, time %" GST_TIME_FORMAT, stream->current_frame, GST_TIME_ARGS (pos)); } else { pos = gst_util_uint64_scale (xlen, stream->current_byte, stream->total_bytes); - GST_DEBUG_OBJECT (demux, "CBR perc convert bytes %" G_GUINT64_FORMAT + GST_DEBUG_OBJECT (avi, "CBR perc convert bytes %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT, stream->current_byte, GST_TIME_ARGS (pos)); } @@ -492,11 +504,10 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query) } } else { if (stream->strh->rate != 0) { - pos = - gst_util_uint64_scale_int ((guint64) stream->current_frame * - stream->strh->scale, GST_SECOND, stream->strh->rate); + pos = gst_util_uint64_scale ((guint64) stream->current_frame * + stream->strh->scale, GST_SECOND, (guint64) stream->strh->rate); } else { - pos = stream->current_frame * demux->avih->us_frame * GST_USECOND; + pos = stream->current_frame * avi->avih->us_frame * GST_USECOND; } } if (res) { @@ -607,6 +618,7 @@ static gboolean gst_avi_demux_peek_chunk (GstAviDemux * avi, guint32 * tag, guint32 * size) { guint32 peek_size = 0; + gint available; if (!gst_avi_demux_peek_chunk_info (avi, tag, size)) { return FALSE; @@ -617,11 +629,13 @@ gst_avi_demux_peek_chunk (GstAviDemux * avi, guint32 * tag, guint32 * size) *size, GST_FOURCC_ARGS (*tag)); return FALSE; } - GST_DEBUG ("Need to peek chunk of %d bytes to read chunk %" GST_FOURCC_FORMAT, - *size, GST_FOURCC_ARGS (*tag)); peek_size = (*size + 1) & ~1; + available = gst_adapter_available (avi->adapter); - if (gst_adapter_available (avi->adapter) >= (8 + peek_size)) { + GST_DEBUG ("Need to peek chunk of %d bytes to read chunk %" GST_FOURCC_FORMAT + ", %d bytes available", *size, GST_FOURCC_ARGS (*tag), available); + + if (available >= (8 + peek_size)) { return TRUE; } else { return FALSE; @@ -868,7 +882,7 @@ too_small: /* * gst_avi_demux_parse_subindex: - * @element: caller element (used for errors/debug). + * @avi: Avi object * @buf: input data to use for parsing. * @stream: stream context. * @entries_list: a list (returned by the function) containing all the @@ -884,7 +898,7 @@ too_small: * throw an error, caller should bail out asap. */ static gboolean -gst_avi_demux_parse_subindex (GstElement * element, +gst_avi_demux_parse_subindex (GstAviDemux * avi, GstBuffer * buf, avi_stream_context * stream, GList ** _entries_list) { guint8 *data = GST_BUFFER_DATA (buf); @@ -913,7 +927,7 @@ gst_avi_demux_parse_subindex (GstElement * element, bpe = (data[2] & 0x01) ? 12 : 8; if (GST_READ_UINT16_LE (data) != bpe / 4 || (data[2] & 0xfe) != 0x0 || data[3] != 0x1) { - GST_WARNING_OBJECT (element, + GST_WARNING_OBJECT (avi, "Superindex for stream %d has unexpected " "size_entry %d (bytes) or flags 0x%02x/0x%02x", stream->num, GST_READ_UINT16_LE (data), data[2], data[3]); @@ -969,7 +983,7 @@ gst_avi_demux_parse_subindex (GstElement * element, entries_list = g_list_prepend (entries_list, entry); } - GST_LOG_OBJECT (element, "Read %d index entries", x); + GST_LOG_OBJECT (avi, "Read %d index entries", x); gst_buffer_unref (buf); @@ -984,7 +998,7 @@ gst_avi_demux_parse_subindex (GstElement * element, /* ERRORS */ too_small: { - GST_ERROR_OBJECT (element, + GST_ERROR_OBJECT (avi, "Not enough data to parse subindex (%d available, 24 needed)", size); if (buf) gst_buffer_unref (buf); @@ -992,7 +1006,7 @@ too_small: } not_implemented: { - GST_ELEMENT_ERROR (element, STREAM, NOT_IMPLEMENTED, (NULL), + GST_ELEMENT_ERROR (avi, STREAM, NOT_IMPLEMENTED, (NULL), ("Subindex-is-data is not implemented")); gst_buffer_unref (buf); return FALSE; @@ -1012,7 +1026,7 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi, GstBuffer *buf = NULL; gint i, n; - GST_DEBUG_OBJECT (avi, "gst_avi_demux_read_subindexes_pull for %d streams", + GST_DEBUG_OBJECT (avi, "gst_avi_demux_read_subindexes_push for %d streams", avi->num_streams); for (n = 0; n < avi->num_streams; n++) { @@ -1034,7 +1048,7 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi, GST_BUFFER_DATA (buf) = gst_adapter_take (avi->adapter, size); GST_BUFFER_SIZE (buf) = size; - if (!gst_avi_demux_parse_subindex (GST_ELEMENT (avi), buf, stream, &list)) + if (!gst_avi_demux_parse_subindex (avi, buf, stream, &list)) continue; if (list) { GST_DEBUG_OBJECT (avi, " adding %d entries", g_list_length (list)); @@ -1080,7 +1094,7 @@ gst_avi_demux_read_subindexes_pull (GstAviDemux * avi, continue; } - if (!gst_avi_demux_parse_subindex (GST_ELEMENT (avi), buf, stream, &list)) + if (!gst_avi_demux_parse_subindex (avi, buf, stream, &list)) continue; if (list) { GST_DEBUG_OBJECT (avi, " adding %5d entries, total %2d %5d", @@ -1290,6 +1304,10 @@ gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf) goto fail; } + GST_DEBUG_OBJECT (element, "codec-name=%s", + (codec_name ? codec_name : "NULL")); + GST_DEBUG_OBJECT (element, "caps=%" GST_PTR_FORMAT, caps); + /* set proper settings and add it */ if (stream->pad) gst_object_unref (stream->pad); @@ -1509,6 +1527,7 @@ gst_avi_demux_parse_index (GstAviDemux * avi, avi->index_offset = pos_before + 8; else avi->index_offset = 0; + GST_DEBUG ("index_offset = %" G_GUINT64_FORMAT, avi->index_offset); } format = GST_FORMAT_TIME; @@ -1571,31 +1590,51 @@ static void gst_avi_demux_stream_index (GstAviDemux * avi, GList ** index, GList ** alloc_list) { + GstFlowReturn res; guint64 offset = avi->offset; GstBuffer *buf; guint32 tag; + guint size; gint i; - GST_DEBUG ("Demux stream index"); + GST_DEBUG ("demux stream index at offset %" G_GUINT64_FORMAT, offset); *alloc_list = NULL; *index = NULL; /* get chunk information */ - if (gst_pad_pull_range (avi->sinkpad, offset, 8, &buf) != GST_FLOW_OK) - return; + res = gst_pad_pull_range (avi->sinkpad, offset, 8, &buf); + if (res != GST_FLOW_OK) + goto pull_failed; else if (GST_BUFFER_SIZE (buf) < 8) goto too_small; - offset += 8 + GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4); + /* check tag first before blindy trying to read 'size' bytes */ + tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf)); + size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4); + if (tag == GST_RIFF_TAG_LIST) { + GST_WARNING_OBJECT (avi, "skip LIST chunk"); + offset += 8 + ((size + 1) & ~1); + res = gst_pad_pull_range (avi->sinkpad, offset, 8, &buf); + if (res != GST_FLOW_OK) + goto pull_failed; + else if (GST_BUFFER_SIZE (buf) < 8) + goto too_small; + tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf)); + size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4); + } + + if (tag != GST_RIFF_TAG_idx1) + goto no_index; + gst_buffer_unref (buf); + GST_DEBUG ("index found at offset %" G_GUINT64_FORMAT, offset); + /* read chunk, advance offset */ if (gst_riff_read_chunk (GST_ELEMENT_CAST (avi), avi->sinkpad, &offset, &tag, &buf) != GST_FLOW_OK) return; - else if (tag != GST_RIFF_TAG_idx1) - goto no_index; gst_avi_demux_parse_index (avi, buf, index); if (*index) @@ -1612,6 +1651,12 @@ gst_avi_demux_stream_index (GstAviDemux * avi, return; /* ERRORS */ +pull_failed: + { + GST_DEBUG_OBJECT (avi, + "pull range failed: pos=%" G_GUINT64_FORMAT " size=8", offset); + return; + } too_small: { GST_DEBUG_OBJECT (avi, "Buffer is too small"); @@ -1621,7 +1666,7 @@ too_small: no_index: { GST_WARNING_OBJECT (avi, - "No index data after movi chunk, but %" GST_FOURCC_FORMAT, + "No index data (idx1) after movi chunk, but %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)); gst_buffer_unref (buf); return; @@ -1834,7 +1879,7 @@ gst_avi_demux_next_data_buffer (GstAviDemux * avi, guint64 * offset, if (res != GST_FLOW_OK) break; if (*tag == GST_RIFF_TAG_LIST) - off += 12; + off += 8 + 4; /* skip tag + size + subtag */ else { *offset = off + 8; *size = _size; @@ -2059,7 +2104,7 @@ gst_avi_demux_massage_index (GstAviDemux * avi, guint32 init_frames; GstFormat fmt = GST_FORMAT_TIME; #endif - gint64 delay = 0; + gint64 delay = G_GINT64_CONSTANT (0); GST_LOG_OBJECT (avi, "Starting index massage"); @@ -2177,24 +2222,35 @@ gst_avi_demux_massage_index (GstAviDemux * avi, /* re-order for time */ list = g_list_sort (list, (GCompareFunc) sort); - GST_LOG_OBJECT (avi, "Filling in index array"); - avi->index_size = g_list_length (list); + GST_LOG_OBJECT (avi, "Filling in index array, nr_entries = %d", + avi->index_size); + avi->index_entries = g_new (gst_avi_index_entry, avi->index_size); - entry = (gst_avi_index_entry *) (list->data); - delay = entry->ts; + if (list) { + entry = (gst_avi_index_entry *) (list->data); + delay = entry->ts; + } + GST_DEBUG ("Fixing time offset : %" GST_TIME_FORMAT, GST_TIME_ARGS (delay)); for (i = 0, one = list; one != NULL; one = one->next, i++) { entry = one->data; entry->ts -= delay; memcpy (&avi->index_entries[i], entry, sizeof (gst_avi_index_entry)); avi->index_entries[i].index_nr = i; + GST_DEBUG ("Sorted index entry %3d for stream %d of size %6u" " at offset %7" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT " dur %" GST_TIME_FORMAT, avi->index_entries[i].index_nr, entry->stream_nr, entry->size, entry->offset, GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (entry->dur)); } + if (delay) { + for (i = 0; i < avi->num_streams; i++) { + stream = &avi->stream[i]; + stream->idx_duration -= delay; + } + } GST_LOG_OBJECT (avi, "Freeing original index list"); @@ -2227,11 +2283,14 @@ gst_avi_demux_calculate_durations_from_index (GstAviDemux * avi) /* get header duration */ hduration = gst_util_uint64_scale ((guint64) strh->length * - strh->scale, GST_SECOND, strh->rate); + strh->scale, GST_SECOND, (guint64) strh->rate); GST_INFO ("Stream %d duration according to header: %" GST_TIME_FORMAT, stream, GST_TIME_ARGS (hduration)); + if (hduration == 0) + hduration = GST_CLOCK_TIME_NONE; + /* set duration for the stream */ streamc->hdr_duration = hduration; @@ -2260,6 +2319,21 @@ gst_avi_demux_calculate_durations_from_index (GstAviDemux * avi) total = duration; } + if (GST_CLOCK_TIME_IS_VALID (total) && (total > 0)) { + /* now update the duration for those streams where we had none */ + for (stream = 0; stream < avi->num_streams; stream++) { + avi_stream_context *streamc = &avi->stream[stream]; + + if (!GST_CLOCK_TIME_IS_VALID (streamc->duration) + || streamc->duration == 0) { + streamc->duration = total; + + GST_INFO ("Stream %d duration according to total: %" GST_TIME_FORMAT, + stream, GST_TIME_ARGS (total)); + } + } + } + /* and set the total duration in the segment. */ GST_INFO ("Setting total duration to: %" GST_TIME_FORMAT, GST_TIME_ARGS (total)); @@ -2638,8 +2712,8 @@ gst_avi_demux_stream_header_pull (GstAviDemux * avi) } default: GST_WARNING_OBJECT (avi, - "Unknown off %d tag %" GST_FOURCC_FORMAT " in AVI header", - offset, GST_FOURCC_ARGS (tag)); + "Unknown tag %" GST_FOURCC_FORMAT " in AVI header at off %d", + GST_FOURCC_ARGS (tag), offset); /* fall-through */ case GST_RIFF_TAG_JUNK: next: @@ -2722,6 +2796,7 @@ skipping_done: /* create or read stream index (for seeking) */ if (avi->stream[0].indexes != NULL) { + /* we read a super index already (gst_avi_demux_parse_superindex() ) */ gst_avi_demux_read_subindexes_pull (avi, &index, &alloc); } if (!index) { @@ -2838,7 +2913,7 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment) old_entry = avi->current_entry; /* get the entry for the requested position, which is always in last_stop. - * we search the index intry for stream 0, since all entries are sorted by + * we search the index entry for stream 0, since all entries are sorted by * time and stream we automagically are positioned for the other streams as * well. FIXME, this code assumes the main stream with keyframes is stream 0, * which is mostly correct... */ @@ -2850,6 +2925,7 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment) " / duration:%" GST_TIME_FORMAT "]", entry->index_nr, entry->stream_nr, GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (entry->dur)); + avi->current_entry = entry->index_nr; } else { GST_WARNING_OBJECT (avi, @@ -2919,21 +2995,25 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event) format = fmt; } + /* FIXME: can we do anything with rate!=1.0 */ } else { GST_DEBUG_OBJECT (avi, "doing seek without event"); flags = 0; + rate = 1.0; } /* save flush flag */ flush = flags & GST_SEEK_FLAG_FLUSH; if (flush) { + GstEvent *event = gst_event_new_flush_start (); + /* for a flushing seek, we send a flush_start on all pads. This will * eventually stop streaming with a WRONG_STATE. We can thus eventually * take the STREAM_LOCK. */ GST_DEBUG_OBJECT (avi, "sending flush start"); - gst_avi_demux_push_event (avi, gst_event_new_flush_start ()); - gst_pad_push_event (avi->sinkpad, gst_event_new_flush_start ()); + gst_avi_demux_push_event (avi, gst_event_ref (event)); + gst_pad_push_event (avi->sinkpad, event); } else { /* a non-flushing seek, we PAUSE the task so that we can take the * STREAM_LOCK */ @@ -2942,6 +3022,7 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event) } /* wait for streaming to stop */ + GST_DEBUG_OBJECT (avi, "wait for streaming to stop"); GST_PAD_STREAM_LOCK (avi->sinkpad); /* copy segment, we need this because we still need the old @@ -3100,7 +3181,7 @@ gst_avi_demux_aggregated_flow (GstAviDemux * avi) } /* - * Read data from index + * Read data from one index entry */ static GstFlowReturn gst_avi_demux_process_next_entry (GstAviDemux * avi) @@ -3144,6 +3225,10 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi) goto next; } + GST_LOG ("reading buffer (size=%d) from stream %d at current pos %" + G_GUINT64_FORMAT " (%llx)", entry->size, entry->stream_nr, + avi->index_offset + entry->offset, avi->index_offset + entry->offset); + /* pull in the data */ res = gst_pad_pull_range (avi->sinkpad, entry->offset + avi->index_offset, entry->size, &buf); @@ -3166,7 +3251,7 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi) GST_BUFFER_DURATION (buf) = entry->dur; gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad)); - GST_DEBUG_OBJECT (avi, "Processing buffer of size %d and time %" + GST_DEBUG_OBJECT (avi, "Pushing buffer of size %d and time %" GST_TIME_FORMAT " on pad %s", GST_BUFFER_SIZE (buf), GST_TIME_ARGS (entry->ts), GST_PAD_NAME (stream->pad)); @@ -3242,6 +3327,7 @@ gst_avi_demux_stream_data (GstAviDemux * avi) guint32 size = 0; gint stream_nr = 0; GstFlowReturn res = GST_FLOW_OK; + GstFormat format = GST_FORMAT_TIME; /* if we have a avi->index_entries[], we don't want to read * the stream linearly, but seek to the next ts/index_entry. */ @@ -3306,12 +3392,11 @@ gst_avi_demux_stream_data (GstAviDemux * avi) /* recoverable */ GST_WARNING ("Invalid stream ID %d (%" GST_FOURCC_FORMAT ")", stream_nr, GST_FOURCC_ARGS (tag)); - + avi->offset += 8 + ((size + 1) & ~1); gst_adapter_flush (avi->adapter, 8 + ((size + 1) & ~1)); } else { avi_stream_context *stream; GstClockTime next_ts = 0; - GstFormat format; GstBuffer *buf; gst_adapter_flush (avi->adapter, 8); @@ -3324,8 +3409,9 @@ gst_avi_demux_stream_data (GstAviDemux * avi) /* get time of this buffer */ stream = &avi->stream[stream_nr]; - format = GST_FORMAT_TIME; gst_pad_query_position (stream->pad, &format, (gint64 *) & next_ts); + if (format != GST_FORMAT_TIME) + goto wrong_format; /* set delay (if any) if (stream->strh->init_frames == stream->current_frame && @@ -3336,12 +3422,6 @@ gst_avi_demux_stream_data (GstAviDemux * avi) stream->current_frame++; stream->current_byte += size; - /* should we skip this buffer? */ - /* - if (stream->skip) { - stream->skip--; - gst_buffer_unref (buf); - } else { */ if (!stream->pad) { GST_WARNING ("No pad."); gst_buffer_unref (buf); @@ -3353,8 +3433,11 @@ gst_avi_demux_stream_data (GstAviDemux * avi) buf = gst_avi_demux_invert (stream, buf); } - GST_BUFFER_TIMESTAMP (buf) = next_ts; gst_pad_query_position (stream->pad, &format, (gint64 *) & dur_ts); + if (format != GST_FORMAT_TIME) + goto wrong_format; + + GST_BUFFER_TIMESTAMP (buf) = next_ts; GST_BUFFER_DURATION (buf) = dur_ts - next_ts; gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad)); GST_DEBUG_OBJECT (avi, @@ -3376,11 +3459,20 @@ gst_avi_demux_stream_data (GstAviDemux * avi) return res; } } - /*} */ } } +done: return res; + + /* ERRORS */ +wrong_format: + { + GST_DEBUG_OBJECT (avi, "format %s != GST_FORMAT_TIME", + gst_format_get_name (format)); + res = GST_FLOW_ERROR; + goto done; + } } /* @@ -3413,7 +3505,7 @@ push_tag_lists (GstAviDemux * avi) static void gst_avi_demux_loop (GstPad * pad) { - GstFlowReturn res = GST_FLOW_OK; + GstFlowReturn res = GST_FLOW_OK, agg_res = GST_FLOW_OK; GstAviDemux *avi = GST_AVI_DEMUX (GST_PAD_PARENT (pad)); switch (avi->state) { @@ -3449,10 +3541,14 @@ gst_avi_demux_loop (GstPad * pad) GST_DEBUG_OBJECT (avi, "state: %d res:%s", avi->state, gst_flow_get_name (res)); - /* Get Aggregated flow return */ - if ((res != GST_FLOW_OK) - && ((res = gst_avi_demux_aggregated_flow (avi)) != GST_FLOW_OK)) + /* if a pad is in e.g. WRONG_STATE, we want to pause to unlock the STREAM_LOCK */ + if ((res == GST_FLOW_WRONG_STATE) || ((res != GST_FLOW_OK) + && ((agg_res = gst_avi_demux_aggregated_flow (avi)) != GST_FLOW_OK))) { + GST_WARNING ("stream_movi flow: %s / %s", gst_flow_get_name (res), + gst_flow_get_name (agg_res)); + res = agg_res; goto pause; + } return; -- 2.7.4