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
This commit is contained in:
Stefan Kost 2006-11-24 07:46:54 +00:00
parent 466a76bd9d
commit 90431d788e
2 changed files with 189 additions and 75 deletions

View file

@ -1,3 +1,21 @@
2006-11-24 Stefan Kost <ensonic@users.sf.net>
* 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 <edward@fluendo.com> 2006-11-22 Edward Hervey <edward@fluendo.com>
* po/.cvsignore: * po/.cvsignore:

View file

@ -289,6 +289,17 @@ gst_avi_demux_index_next (GstAviDemux * avi, gint stream_nr, gint start)
return result; 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 * static gst_avi_index_entry *
gst_avi_demux_index_entry_for_time (GstAviDemux * avi, gst_avi_demux_index_entry_for_time (GstAviDemux * avi,
gint stream_nr, guint64 time, guint32 flags) 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; gst_avi_index_entry *entry = NULL, *last_entry = NULL;
gint i; 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); stream_nr, GST_TIME_ARGS (time), flags);
i = -1; i = -1;
do { do {
/* get next entry for given stream */
entry = gst_avi_demux_index_next (avi, stream_nr, i + 1); entry = gst_avi_demux_index_next (avi, stream_nr, i + 1);
if (!entry) if (!entry)
break; break;
i = entry->index_nr; i = entry->index_nr;
if (entry->ts <= time && (entry->flags & flags) == flags)
last_entry = entry;
GST_LOG_OBJECT (avi, GST_LOG_OBJECT (avi,
"looking at entry %d / ts:%" GST_TIME_FORMAT " / dur:%" GST_TIME_FORMAT "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), " flags:%d", i, GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (entry->dur),
entry->flags); entry->flags);
if (entry->ts <= time &&
(entry->flags & flags) == flags && stream_nr == entry->stream_nr)
last_entry = entry;
} while (entry->ts < time); } while (entry->ts < time);
return last_entry; return last_entry;
@ -377,9 +388,8 @@ gst_avi_demux_src_convert (GstPad * pad,
case GST_FORMAT_TIME: case GST_FORMAT_TIME:
switch (*dest_format) { switch (*dest_format) {
case GST_FORMAT_BYTES: case GST_FORMAT_BYTES:
*dest_value = *dest_value = gst_util_uint64_scale (src_value,
gst_util_uint64_scale_int (src_value, stream->strf.auds->av_bps, (guint64) stream->strf.auds->av_bps, GST_SECOND);
GST_SECOND);
break; break;
case GST_FORMAT_DEFAULT: case GST_FORMAT_DEFAULT:
*dest_value = gst_util_uint64_scale (src_value, stream->strh->rate, *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) { switch (*dest_format) {
case GST_FORMAT_TIME: case GST_FORMAT_TIME:
if (stream->strf.auds->av_bps != 0) { if (stream->strf.auds->av_bps != 0) {
*dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND, *dest_value = gst_util_uint64_scale (src_value, GST_SECOND,
stream->strf.auds->av_bps); (guint64) stream->strf.auds->av_bps);
} else } else
res = FALSE; res = FALSE;
break; break;
@ -407,9 +417,8 @@ gst_avi_demux_src_convert (GstPad * pad,
case GST_FORMAT_DEFAULT: case GST_FORMAT_DEFAULT:
switch (*dest_format) { switch (*dest_format) {
case GST_FORMAT_TIME: case GST_FORMAT_TIME:
*dest_value = *dest_value = gst_util_uint64_scale (src_value,
gst_util_uint64_scale (src_value, stream->strh->scale * GST_SECOND, (guint64) stream->strh->rate);
stream->strh->scale * GST_SECOND, stream->strh->rate);
break; break;
default: default:
res = FALSE; res = FALSE;
@ -444,7 +453,7 @@ static gboolean
gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query) gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
{ {
gboolean res = TRUE; 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); 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:{ case GST_QUERY_POSITION:{
gint64 pos = 0; 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->strh->type == GST_RIFF_FCC_auds) {
if (stream->is_vbr) { if (stream->is_vbr) {
/* VBR */ /* VBR */
pos = gst_util_uint64_scale_int ((gint64) stream->current_frame * pos = gst_util_uint64_scale ((gint64) stream->current_frame *
stream->strh->scale, GST_SECOND, stream->strh->rate); stream->strh->scale, GST_SECOND, (guint64) stream->strh->rate);
GST_DEBUG_OBJECT (demux, "VBR convert frame %u, time %" GST_DEBUG_OBJECT (avi, "VBR convert frame %u, time %"
GST_TIME_FORMAT, stream->current_frame, GST_TIME_ARGS (pos)); GST_TIME_FORMAT, stream->current_frame, GST_TIME_ARGS (pos));
} else if (stream->strf.auds->av_bps != 0) { } else if (stream->strf.auds->av_bps != 0) {
/* CBR */ /* CBR */
pos = gst_util_uint64_scale_int (stream->current_byte, GST_SECOND, pos = gst_util_uint64_scale (stream->current_byte, GST_SECOND,
stream->strf.auds->av_bps); (guint64) stream->strf.auds->av_bps);
GST_DEBUG_OBJECT (demux, GST_DEBUG_OBJECT (avi,
"CBR convert bytes %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT, "CBR convert bytes %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT,
stream->current_byte, GST_TIME_ARGS (pos)); stream->current_byte, GST_TIME_ARGS (pos));
} else if (stream->total_frames != 0 && stream->total_bytes != 0) { } else if (stream->total_frames != 0 && stream->total_bytes != 0) {
/* calculate timestamps based on percentage of length */ /* calculate timestamps based on percentage of length */
guint64 xlen = demux->avih->us_frame * guint64 xlen = avi->avih->us_frame *
demux->avih->tot_frames * GST_USECOND; avi->avih->tot_frames * GST_USECOND;
if (stream->is_vbr) { if (stream->is_vbr) {
pos = gst_util_uint64_scale (xlen, stream->current_frame, pos = gst_util_uint64_scale (xlen, stream->current_frame,
stream->total_frames); 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)); GST_TIME_FORMAT, stream->current_frame, GST_TIME_ARGS (pos));
} else { } else {
pos = gst_util_uint64_scale (xlen, stream->current_byte, pos = gst_util_uint64_scale (xlen, stream->current_byte,
stream->total_bytes); 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, ", time %" GST_TIME_FORMAT, stream->current_byte,
GST_TIME_ARGS (pos)); GST_TIME_ARGS (pos));
} }
@ -492,11 +504,10 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
} }
} else { } else {
if (stream->strh->rate != 0) { if (stream->strh->rate != 0) {
pos = pos = gst_util_uint64_scale ((guint64) stream->current_frame *
gst_util_uint64_scale_int ((guint64) stream->current_frame * stream->strh->scale, GST_SECOND, (guint64) stream->strh->rate);
stream->strh->scale, GST_SECOND, stream->strh->rate);
} else { } else {
pos = stream->current_frame * demux->avih->us_frame * GST_USECOND; pos = stream->current_frame * avi->avih->us_frame * GST_USECOND;
} }
} }
if (res) { if (res) {
@ -607,6 +618,7 @@ static gboolean
gst_avi_demux_peek_chunk (GstAviDemux * avi, guint32 * tag, guint32 * size) gst_avi_demux_peek_chunk (GstAviDemux * avi, guint32 * tag, guint32 * size)
{ {
guint32 peek_size = 0; guint32 peek_size = 0;
gint available;
if (!gst_avi_demux_peek_chunk_info (avi, tag, size)) { if (!gst_avi_demux_peek_chunk_info (avi, tag, size)) {
return FALSE; return FALSE;
@ -617,11 +629,13 @@ gst_avi_demux_peek_chunk (GstAviDemux * avi, guint32 * tag, guint32 * size)
*size, GST_FOURCC_ARGS (*tag)); *size, GST_FOURCC_ARGS (*tag));
return FALSE; 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; 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; return TRUE;
} else { } else {
return FALSE; return FALSE;
@ -868,7 +882,7 @@ too_small:
/* /*
* gst_avi_demux_parse_subindex: * gst_avi_demux_parse_subindex:
* @element: caller element (used for errors/debug). * @avi: Avi object
* @buf: input data to use for parsing. * @buf: input data to use for parsing.
* @stream: stream context. * @stream: stream context.
* @entries_list: a list (returned by the function) containing all the * @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. * throw an error, caller should bail out asap.
*/ */
static gboolean 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) GstBuffer * buf, avi_stream_context * stream, GList ** _entries_list)
{ {
guint8 *data = GST_BUFFER_DATA (buf); guint8 *data = GST_BUFFER_DATA (buf);
@ -913,7 +927,7 @@ gst_avi_demux_parse_subindex (GstElement * element,
bpe = (data[2] & 0x01) ? 12 : 8; bpe = (data[2] & 0x01) ? 12 : 8;
if (GST_READ_UINT16_LE (data) != bpe / 4 || if (GST_READ_UINT16_LE (data) != bpe / 4 ||
(data[2] & 0xfe) != 0x0 || data[3] != 0x1) { (data[2] & 0xfe) != 0x0 || data[3] != 0x1) {
GST_WARNING_OBJECT (element, GST_WARNING_OBJECT (avi,
"Superindex for stream %d has unexpected " "Superindex for stream %d has unexpected "
"size_entry %d (bytes) or flags 0x%02x/0x%02x", "size_entry %d (bytes) or flags 0x%02x/0x%02x",
stream->num, GST_READ_UINT16_LE (data), data[2], data[3]); 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); 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); gst_buffer_unref (buf);
@ -984,7 +998,7 @@ gst_avi_demux_parse_subindex (GstElement * element,
/* ERRORS */ /* ERRORS */
too_small: too_small:
{ {
GST_ERROR_OBJECT (element, GST_ERROR_OBJECT (avi,
"Not enough data to parse subindex (%d available, 24 needed)", size); "Not enough data to parse subindex (%d available, 24 needed)", size);
if (buf) if (buf)
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -992,7 +1006,7 @@ too_small:
} }
not_implemented: not_implemented:
{ {
GST_ELEMENT_ERROR (element, STREAM, NOT_IMPLEMENTED, (NULL), GST_ELEMENT_ERROR (avi, STREAM, NOT_IMPLEMENTED, (NULL),
("Subindex-is-data is not implemented")); ("Subindex-is-data is not implemented"));
gst_buffer_unref (buf); gst_buffer_unref (buf);
return FALSE; return FALSE;
@ -1012,7 +1026,7 @@ gst_avi_demux_read_subindexes_push (GstAviDemux * avi,
GstBuffer *buf = NULL; GstBuffer *buf = NULL;
gint i, n; 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); avi->num_streams);
for (n = 0; n < avi->num_streams; n++) { 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_DATA (buf) = gst_adapter_take (avi->adapter, size);
GST_BUFFER_SIZE (buf) = 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; continue;
if (list) { if (list) {
GST_DEBUG_OBJECT (avi, " adding %d entries", g_list_length (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; continue;
} }
if (!gst_avi_demux_parse_subindex (GST_ELEMENT (avi), buf, stream, &list)) if (!gst_avi_demux_parse_subindex (avi, buf, stream, &list))
continue; continue;
if (list) { if (list) {
GST_DEBUG_OBJECT (avi, " adding %5d entries, total %2d %5d", 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; 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 */ /* set proper settings and add it */
if (stream->pad) if (stream->pad)
gst_object_unref (stream->pad); gst_object_unref (stream->pad);
@ -1509,6 +1527,7 @@ gst_avi_demux_parse_index (GstAviDemux * avi,
avi->index_offset = pos_before + 8; avi->index_offset = pos_before + 8;
else else
avi->index_offset = 0; avi->index_offset = 0;
GST_DEBUG ("index_offset = %" G_GUINT64_FORMAT, avi->index_offset);
} }
format = GST_FORMAT_TIME; format = GST_FORMAT_TIME;
@ -1571,31 +1590,51 @@ static void
gst_avi_demux_stream_index (GstAviDemux * avi, gst_avi_demux_stream_index (GstAviDemux * avi,
GList ** index, GList ** alloc_list) GList ** index, GList ** alloc_list)
{ {
GstFlowReturn res;
guint64 offset = avi->offset; guint64 offset = avi->offset;
GstBuffer *buf; GstBuffer *buf;
guint32 tag; guint32 tag;
guint size;
gint i; gint i;
GST_DEBUG ("Demux stream index"); GST_DEBUG ("demux stream index at offset %" G_GUINT64_FORMAT, offset);
*alloc_list = NULL; *alloc_list = NULL;
*index = NULL; *index = NULL;
/* get chunk information */ /* get chunk information */
if (gst_pad_pull_range (avi->sinkpad, offset, 8, &buf) != GST_FLOW_OK) res = gst_pad_pull_range (avi->sinkpad, offset, 8, &buf);
return; if (res != GST_FLOW_OK)
goto pull_failed;
else if (GST_BUFFER_SIZE (buf) < 8) else if (GST_BUFFER_SIZE (buf) < 8)
goto too_small; 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_buffer_unref (buf);
GST_DEBUG ("index found at offset %" G_GUINT64_FORMAT, offset);
/* read chunk, advance offset */ /* read chunk, advance offset */
if (gst_riff_read_chunk (GST_ELEMENT_CAST (avi), if (gst_riff_read_chunk (GST_ELEMENT_CAST (avi),
avi->sinkpad, &offset, &tag, &buf) != GST_FLOW_OK) avi->sinkpad, &offset, &tag, &buf) != GST_FLOW_OK)
return; return;
else if (tag != GST_RIFF_TAG_idx1)
goto no_index;
gst_avi_demux_parse_index (avi, buf, index); gst_avi_demux_parse_index (avi, buf, index);
if (*index) if (*index)
@ -1612,6 +1651,12 @@ gst_avi_demux_stream_index (GstAviDemux * avi,
return; return;
/* ERRORS */ /* ERRORS */
pull_failed:
{
GST_DEBUG_OBJECT (avi,
"pull range failed: pos=%" G_GUINT64_FORMAT " size=8", offset);
return;
}
too_small: too_small:
{ {
GST_DEBUG_OBJECT (avi, "Buffer is too small"); GST_DEBUG_OBJECT (avi, "Buffer is too small");
@ -1621,7 +1666,7 @@ too_small:
no_index: no_index:
{ {
GST_WARNING_OBJECT (avi, 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_FOURCC_ARGS (tag));
gst_buffer_unref (buf); gst_buffer_unref (buf);
return; return;
@ -1834,7 +1879,7 @@ gst_avi_demux_next_data_buffer (GstAviDemux * avi, guint64 * offset,
if (res != GST_FLOW_OK) if (res != GST_FLOW_OK)
break; break;
if (*tag == GST_RIFF_TAG_LIST) if (*tag == GST_RIFF_TAG_LIST)
off += 12; off += 8 + 4; /* skip tag + size + subtag */
else { else {
*offset = off + 8; *offset = off + 8;
*size = _size; *size = _size;
@ -2059,7 +2104,7 @@ gst_avi_demux_massage_index (GstAviDemux * avi,
guint32 init_frames; guint32 init_frames;
GstFormat fmt = GST_FORMAT_TIME; GstFormat fmt = GST_FORMAT_TIME;
#endif #endif
gint64 delay = 0; gint64 delay = G_GINT64_CONSTANT (0);
GST_LOG_OBJECT (avi, "Starting index massage"); GST_LOG_OBJECT (avi, "Starting index massage");
@ -2177,24 +2222,35 @@ gst_avi_demux_massage_index (GstAviDemux * avi,
/* re-order for time */ /* re-order for time */
list = g_list_sort (list, (GCompareFunc) sort); list = g_list_sort (list, (GCompareFunc) sort);
GST_LOG_OBJECT (avi, "Filling in index array");
avi->index_size = g_list_length (list); 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); avi->index_entries = g_new (gst_avi_index_entry, avi->index_size);
entry = (gst_avi_index_entry *) (list->data); if (list) {
delay = entry->ts; entry = (gst_avi_index_entry *) (list->data);
delay = entry->ts;
}
GST_DEBUG ("Fixing time offset : %" GST_TIME_FORMAT, GST_TIME_ARGS (delay)); GST_DEBUG ("Fixing time offset : %" GST_TIME_FORMAT, GST_TIME_ARGS (delay));
for (i = 0, one = list; one != NULL; one = one->next, i++) { for (i = 0, one = list; one != NULL; one = one->next, i++) {
entry = one->data; entry = one->data;
entry->ts -= delay; entry->ts -= delay;
memcpy (&avi->index_entries[i], entry, sizeof (gst_avi_index_entry)); memcpy (&avi->index_entries[i], entry, sizeof (gst_avi_index_entry));
avi->index_entries[i].index_nr = i; avi->index_entries[i].index_nr = i;
GST_DEBUG ("Sorted index entry %3d for stream %d of size %6u" GST_DEBUG ("Sorted index entry %3d for stream %d of size %6u"
" at offset %7" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT " at offset %7" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT
" dur %" GST_TIME_FORMAT, " dur %" GST_TIME_FORMAT,
avi->index_entries[i].index_nr, entry->stream_nr, entry->size, avi->index_entries[i].index_nr, entry->stream_nr, entry->size,
entry->offset, GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (entry->dur)); 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"); GST_LOG_OBJECT (avi, "Freeing original index list");
@ -2227,11 +2283,14 @@ gst_avi_demux_calculate_durations_from_index (GstAviDemux * avi)
/* get header duration */ /* get header duration */
hduration = gst_util_uint64_scale ((guint64) strh->length * 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, GST_INFO ("Stream %d duration according to header: %" GST_TIME_FORMAT,
stream, GST_TIME_ARGS (hduration)); stream, GST_TIME_ARGS (hduration));
if (hduration == 0)
hduration = GST_CLOCK_TIME_NONE;
/* set duration for the stream */ /* set duration for the stream */
streamc->hdr_duration = hduration; streamc->hdr_duration = hduration;
@ -2260,6 +2319,21 @@ gst_avi_demux_calculate_durations_from_index (GstAviDemux * avi)
total = duration; 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. */ /* and set the total duration in the segment. */
GST_INFO ("Setting total duration to: %" GST_TIME_FORMAT, GST_INFO ("Setting total duration to: %" GST_TIME_FORMAT,
GST_TIME_ARGS (total)); GST_TIME_ARGS (total));
@ -2638,8 +2712,8 @@ gst_avi_demux_stream_header_pull (GstAviDemux * avi)
} }
default: default:
GST_WARNING_OBJECT (avi, GST_WARNING_OBJECT (avi,
"Unknown off %d tag %" GST_FOURCC_FORMAT " in AVI header", "Unknown tag %" GST_FOURCC_FORMAT " in AVI header at off %d",
offset, GST_FOURCC_ARGS (tag)); GST_FOURCC_ARGS (tag), offset);
/* fall-through */ /* fall-through */
case GST_RIFF_TAG_JUNK: case GST_RIFF_TAG_JUNK:
next: next:
@ -2722,6 +2796,7 @@ skipping_done:
/* create or read stream index (for seeking) */ /* create or read stream index (for seeking) */
if (avi->stream[0].indexes != NULL) { 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); gst_avi_demux_read_subindexes_pull (avi, &index, &alloc);
} }
if (!index) { if (!index) {
@ -2838,7 +2913,7 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
old_entry = avi->current_entry; old_entry = avi->current_entry;
/* get the entry for the requested position, which is always in last_stop. /* 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 * 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, * well. FIXME, this code assumes the main stream with keyframes is stream 0,
* which is mostly correct... */ * which is mostly correct... */
@ -2850,6 +2925,7 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
" / duration:%" GST_TIME_FORMAT "]", entry->index_nr, " / duration:%" GST_TIME_FORMAT "]", entry->index_nr,
entry->stream_nr, GST_TIME_ARGS (entry->ts), entry->stream_nr, GST_TIME_ARGS (entry->ts),
GST_TIME_ARGS (entry->dur)); GST_TIME_ARGS (entry->dur));
avi->current_entry = entry->index_nr; avi->current_entry = entry->index_nr;
} else { } else {
GST_WARNING_OBJECT (avi, GST_WARNING_OBJECT (avi,
@ -2919,21 +2995,25 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event)
format = fmt; format = fmt;
} }
/* FIXME: can we do anything with rate!=1.0 */
} else { } else {
GST_DEBUG_OBJECT (avi, "doing seek without event"); GST_DEBUG_OBJECT (avi, "doing seek without event");
flags = 0; flags = 0;
rate = 1.0;
} }
/* save flush flag */ /* save flush flag */
flush = flags & GST_SEEK_FLAG_FLUSH; flush = flags & GST_SEEK_FLAG_FLUSH;
if (flush) { if (flush) {
GstEvent *event = gst_event_new_flush_start ();
/* for a flushing seek, we send a flush_start on all pads. This will /* 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 * eventually stop streaming with a WRONG_STATE. We can thus eventually
* take the STREAM_LOCK. */ * take the STREAM_LOCK. */
GST_DEBUG_OBJECT (avi, "sending flush start"); GST_DEBUG_OBJECT (avi, "sending flush start");
gst_avi_demux_push_event (avi, gst_event_new_flush_start ()); gst_avi_demux_push_event (avi, gst_event_ref (event));
gst_pad_push_event (avi->sinkpad, gst_event_new_flush_start ()); gst_pad_push_event (avi->sinkpad, event);
} else { } else {
/* a non-flushing seek, we PAUSE the task so that we can take the /* a non-flushing seek, we PAUSE the task so that we can take the
* STREAM_LOCK */ * STREAM_LOCK */
@ -2942,6 +3022,7 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event)
} }
/* wait for streaming to stop */ /* wait for streaming to stop */
GST_DEBUG_OBJECT (avi, "wait for streaming to stop");
GST_PAD_STREAM_LOCK (avi->sinkpad); GST_PAD_STREAM_LOCK (avi->sinkpad);
/* copy segment, we need this because we still need the old /* 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 static GstFlowReturn
gst_avi_demux_process_next_entry (GstAviDemux * avi) gst_avi_demux_process_next_entry (GstAviDemux * avi)
@ -3144,6 +3225,10 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi)
goto next; 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 */ /* pull in the data */
res = gst_pad_pull_range (avi->sinkpad, entry->offset + res = gst_pad_pull_range (avi->sinkpad, entry->offset +
avi->index_offset, entry->size, &buf); 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_DURATION (buf) = entry->dur;
gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad)); 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_TIME_FORMAT " on pad %s",
GST_BUFFER_SIZE (buf), GST_TIME_ARGS (entry->ts), GST_BUFFER_SIZE (buf), GST_TIME_ARGS (entry->ts),
GST_PAD_NAME (stream->pad)); GST_PAD_NAME (stream->pad));
@ -3242,6 +3327,7 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
guint32 size = 0; guint32 size = 0;
gint stream_nr = 0; gint stream_nr = 0;
GstFlowReturn res = GST_FLOW_OK; GstFlowReturn res = GST_FLOW_OK;
GstFormat format = GST_FORMAT_TIME;
/* if we have a avi->index_entries[], we don't want to read /* if we have a avi->index_entries[], we don't want to read
* the stream linearly, but seek to the next ts/index_entry. */ * the stream linearly, but seek to the next ts/index_entry. */
@ -3306,12 +3392,11 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
/* recoverable */ /* recoverable */
GST_WARNING ("Invalid stream ID %d (%" GST_FOURCC_FORMAT ")", GST_WARNING ("Invalid stream ID %d (%" GST_FOURCC_FORMAT ")",
stream_nr, GST_FOURCC_ARGS (tag)); stream_nr, GST_FOURCC_ARGS (tag));
avi->offset += 8 + ((size + 1) & ~1);
gst_adapter_flush (avi->adapter, 8 + ((size + 1) & ~1)); gst_adapter_flush (avi->adapter, 8 + ((size + 1) & ~1));
} else { } else {
avi_stream_context *stream; avi_stream_context *stream;
GstClockTime next_ts = 0; GstClockTime next_ts = 0;
GstFormat format;
GstBuffer *buf; GstBuffer *buf;
gst_adapter_flush (avi->adapter, 8); gst_adapter_flush (avi->adapter, 8);
@ -3324,8 +3409,9 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
/* get time of this buffer */ /* get time of this buffer */
stream = &avi->stream[stream_nr]; stream = &avi->stream[stream_nr];
format = GST_FORMAT_TIME;
gst_pad_query_position (stream->pad, &format, (gint64 *) & next_ts); gst_pad_query_position (stream->pad, &format, (gint64 *) & next_ts);
if (format != GST_FORMAT_TIME)
goto wrong_format;
/* set delay (if any) /* set delay (if any)
if (stream->strh->init_frames == stream->current_frame && if (stream->strh->init_frames == stream->current_frame &&
@ -3336,12 +3422,6 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
stream->current_frame++; stream->current_frame++;
stream->current_byte += size; stream->current_byte += size;
/* should we skip this buffer? */
/*
if (stream->skip) {
stream->skip--;
gst_buffer_unref (buf);
} else { */
if (!stream->pad) { if (!stream->pad) {
GST_WARNING ("No pad."); GST_WARNING ("No pad.");
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -3353,8 +3433,11 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
buf = gst_avi_demux_invert (stream, buf); buf = gst_avi_demux_invert (stream, buf);
} }
GST_BUFFER_TIMESTAMP (buf) = next_ts;
gst_pad_query_position (stream->pad, &format, (gint64 *) & dur_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_DURATION (buf) = dur_ts - next_ts;
gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad)); gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad));
GST_DEBUG_OBJECT (avi, GST_DEBUG_OBJECT (avi,
@ -3376,11 +3459,20 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
return res; return res;
} }
} }
/*} */
} }
} }
done:
return res; 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 static void
gst_avi_demux_loop (GstPad * pad) 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)); GstAviDemux *avi = GST_AVI_DEMUX (GST_PAD_PARENT (pad));
switch (avi->state) { switch (avi->state) {
@ -3449,10 +3541,14 @@ gst_avi_demux_loop (GstPad * pad)
GST_DEBUG_OBJECT (avi, "state: %d res:%s", avi->state, GST_DEBUG_OBJECT (avi, "state: %d res:%s", avi->state,
gst_flow_get_name (res)); gst_flow_get_name (res));
/* Get Aggregated flow return */ /* if a pad is in e.g. WRONG_STATE, we want to pause to unlock the STREAM_LOCK */
if ((res != GST_FLOW_OK) if ((res == GST_FLOW_WRONG_STATE) || ((res != GST_FLOW_OK)
&& ((res = gst_avi_demux_aggregated_flow (avi)) != 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; goto pause;
}
return; return;