mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-07 19:22:15 +00:00
gst/avi/gstavidemux.*: Some cleanups, prepare to use GstSegment.
Original commit message from CVS: * gst/avi/gstavidemux.c: (gst_avi_demux_reset), (gst_avi_demux_index_next), (gst_avi_demux_handle_src_query), (gst_avi_demux_handle_src_event), (gst_avi_demux_parse_subindex), (gst_avi_demux_parse_stream), (gst_avi_demux_parse_index), (gst_avi_demux_stream_index), (gst_avi_demux_stream_scan), (gst_avi_demux_massage_index), (gst_avi_demux_calculate_durations_from_index), (gst_avi_demux_push_event), (gst_avi_demux_stream_header), (gst_avi_demux_handle_seek), (gst_avi_demux_process_next_entry), (gst_avi_demux_loop): * gst/avi/gstavidemux.h: Some cleanups, prepare to use GstSegment. Fix error in entry walking code. Fix VBR detection. Smarter timestamp calculation code. Uniform error/eos handling.
This commit is contained in:
parent
26c9baa830
commit
50d7e0f6bb
3 changed files with 179 additions and 145 deletions
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
||||||
|
2006-05-12 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* gst/avi/gstavidemux.c: (gst_avi_demux_reset),
|
||||||
|
(gst_avi_demux_index_next), (gst_avi_demux_handle_src_query),
|
||||||
|
(gst_avi_demux_handle_src_event), (gst_avi_demux_parse_subindex),
|
||||||
|
(gst_avi_demux_parse_stream), (gst_avi_demux_parse_index),
|
||||||
|
(gst_avi_demux_stream_index), (gst_avi_demux_stream_scan),
|
||||||
|
(gst_avi_demux_massage_index),
|
||||||
|
(gst_avi_demux_calculate_durations_from_index),
|
||||||
|
(gst_avi_demux_push_event), (gst_avi_demux_stream_header),
|
||||||
|
(gst_avi_demux_handle_seek), (gst_avi_demux_process_next_entry),
|
||||||
|
(gst_avi_demux_loop):
|
||||||
|
* gst/avi/gstavidemux.h:
|
||||||
|
Some cleanups, prepare to use GstSegment.
|
||||||
|
Fix error in entry walking code.
|
||||||
|
Fix VBR detection.
|
||||||
|
Smarter timestamp calculation code.
|
||||||
|
Uniform error/eos handling.
|
||||||
|
|
||||||
2006-05-12 Michael Smith <msmith@fluendo.com>
|
2006-05-12 Michael Smith <msmith@fluendo.com>
|
||||||
|
|
||||||
* gst/wavparse/gstwavparse.c: (gst_wavparse_fmt),
|
* gst/wavparse/gstwavparse.c: (gst_wavparse_fmt),
|
||||||
|
|
|
@ -218,25 +218,25 @@ gst_avi_demux_reset (GstAviDemux * avi)
|
||||||
gst_event_unref (avi->seek_event);
|
gst_event_unref (avi->seek_event);
|
||||||
avi->seek_event = NULL;
|
avi->seek_event = NULL;
|
||||||
|
|
||||||
avi->segment_rate = 1.0;
|
gst_segment_init (&avi->segment, GST_FORMAT_TIME);
|
||||||
avi->segment_flags = 0;
|
|
||||||
avi->segment_start = -1;
|
|
||||||
avi->segment_stop = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gst_avi_index_entry *
|
static gst_avi_index_entry *
|
||||||
gst_avi_demux_index_next (GstAviDemux * avi, gint stream_nr, gint start)
|
gst_avi_demux_index_next (GstAviDemux * avi, gint stream_nr, gint start)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
gst_avi_index_entry *entry = NULL;
|
gst_avi_index_entry *result = NULL;
|
||||||
|
|
||||||
for (i = start; i < avi->index_size; i++) {
|
for (i = start; i < avi->index_size; i++) {
|
||||||
entry = &avi->index_entries[i];
|
gst_avi_index_entry *entry = &avi->index_entries[i];
|
||||||
if (entry->stream_nr == stream_nr)
|
|
||||||
|
if (entry->stream_nr == stream_nr) {
|
||||||
|
result = entry;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gst_avi_index_entry *
|
static gst_avi_index_entry *
|
||||||
|
@ -401,23 +401,25 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
|
||||||
gint64 pos = 0;
|
gint64 pos = 0;
|
||||||
|
|
||||||
if (stream->strh->type == GST_RIFF_FCC_auds) {
|
if (stream->strh->type == GST_RIFF_FCC_auds) {
|
||||||
if (!stream->strh->samplesize) {
|
if (!stream->is_vbr) {
|
||||||
|
/* CBR */
|
||||||
pos = gst_util_uint64_scale_int ((gint64) stream->current_frame *
|
pos = gst_util_uint64_scale_int ((gint64) stream->current_frame *
|
||||||
stream->strh->scale, GST_SECOND, stream->strh->rate);
|
stream->strh->scale, GST_SECOND, stream->strh->rate);
|
||||||
} else if (stream->strf.auds->av_bps != 0) {
|
} else if (stream->strf.auds->av_bps != 0) {
|
||||||
|
/* VBR */
|
||||||
pos = gst_util_uint64_scale_int (stream->current_byte, GST_SECOND,
|
pos = gst_util_uint64_scale_int (stream->current_byte, GST_SECOND,
|
||||||
stream->strf.auds->av_bps);
|
stream->strf.auds->av_bps);
|
||||||
} else if (stream->total_frames != 0 && stream->total_bytes != 0) {
|
} else if (stream->total_frames != 0 && stream->total_bytes != 0) {
|
||||||
/* calculate timestamps based on video size */
|
/* calculate timestamps based on percentage of length */
|
||||||
guint64 xlen = demux->avih->us_frame *
|
guint64 xlen = demux->avih->us_frame *
|
||||||
demux->avih->tot_frames * GST_USECOND;
|
demux->avih->tot_frames * GST_USECOND;
|
||||||
|
|
||||||
if (!stream->strh->samplesize)
|
if (stream->is_vbr)
|
||||||
pos = gst_util_uint64_scale_int (xlen, stream->current_frame,
|
|
||||||
stream->total_frames);
|
|
||||||
else
|
|
||||||
pos = gst_util_uint64_scale_int (xlen, stream->current_byte,
|
pos = gst_util_uint64_scale_int (xlen, stream->current_byte,
|
||||||
stream->total_bytes);
|
stream->total_bytes);
|
||||||
|
else
|
||||||
|
pos = gst_util_uint64_scale_int (xlen, stream->current_frame,
|
||||||
|
stream->total_frames);
|
||||||
} else {
|
} else {
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -535,13 +537,13 @@ gst_avi_demux_handle_src_event (GstPad * pad, GstEvent * event)
|
||||||
|
|
||||||
switch (start_type) {
|
switch (start_type) {
|
||||||
case GST_SEEK_TYPE_CUR:
|
case GST_SEEK_TYPE_CUR:
|
||||||
tstart = avi->segment_start + tstart;
|
tstart = avi->segment.start + tstart;
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_TYPE_END:
|
case GST_SEEK_TYPE_END:
|
||||||
tstart = duration + tstart;
|
tstart = duration + tstart;
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_TYPE_NONE:
|
case GST_SEEK_TYPE_NONE:
|
||||||
tstart = avi->segment_start;
|
tstart = avi->segment.start;
|
||||||
update_start = FALSE;
|
update_start = FALSE;
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_TYPE_SET:
|
case GST_SEEK_TYPE_SET:
|
||||||
|
@ -551,13 +553,13 @@ gst_avi_demux_handle_src_event (GstPad * pad, GstEvent * event)
|
||||||
|
|
||||||
switch (stop_type) {
|
switch (stop_type) {
|
||||||
case GST_SEEK_TYPE_CUR:
|
case GST_SEEK_TYPE_CUR:
|
||||||
tstop = avi->segment_stop + tstop;
|
tstop = avi->segment.stop + tstop;
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_TYPE_END:
|
case GST_SEEK_TYPE_END:
|
||||||
tstop = duration + tstop;
|
tstop = duration + tstop;
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_TYPE_NONE:
|
case GST_SEEK_TYPE_NONE:
|
||||||
tstop = avi->segment_stop;
|
tstop = avi->segment.stop;
|
||||||
update_stop = FALSE;
|
update_stop = FALSE;
|
||||||
break;
|
break;
|
||||||
case GST_SEEK_TYPE_SET:
|
case GST_SEEK_TYPE_SET:
|
||||||
|
@ -566,10 +568,10 @@ gst_avi_demux_handle_src_event (GstPad * pad, GstEvent * event)
|
||||||
tstop = CLAMP (tstop, 0, duration);
|
tstop = CLAMP (tstop, 0, duration);
|
||||||
|
|
||||||
/* now store the values */
|
/* now store the values */
|
||||||
avi->segment_rate = rate;
|
avi->segment.rate = rate;
|
||||||
avi->segment_flags = flags;
|
avi->segment.flags = flags;
|
||||||
avi->segment_start = tstart;
|
avi->segment.start = tstart;
|
||||||
avi->segment_stop = tstop;
|
avi->segment.stop = tstop;
|
||||||
|
|
||||||
gst_avi_demux_handle_seek (avi, update_start || update_stop);
|
gst_avi_demux_handle_seek (avi, update_start || update_stop);
|
||||||
break;
|
break;
|
||||||
|
@ -832,7 +834,6 @@ gst_avi_demux_parse_subindex (GstElement * element,
|
||||||
gst_avi_index_entry *entries, *entry;
|
gst_avi_index_entry *entries, *entry;
|
||||||
GList *entries_list = NULL;
|
GList *entries_list = NULL;
|
||||||
GstFormat format = GST_FORMAT_TIME;
|
GstFormat format = GST_FORMAT_TIME;
|
||||||
gint64 tmp;
|
|
||||||
|
|
||||||
/* check size */
|
/* check size */
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
|
@ -862,6 +863,8 @@ gst_avi_demux_parse_subindex (GstElement * element,
|
||||||
|
|
||||||
entries = g_new (gst_avi_index_entry, num);
|
entries = g_new (gst_avi_index_entry, num);
|
||||||
for (x = 0; x < num; x++) {
|
for (x = 0; x < num; x++) {
|
||||||
|
gint64 next_ts;
|
||||||
|
|
||||||
entry = &entries[x];
|
entry = &entries[x];
|
||||||
|
|
||||||
if (GST_BUFFER_SIZE (buf) < 24 + bpe * (x + 1))
|
if (GST_BUFFER_SIZE (buf) < 24 + bpe * (x + 1))
|
||||||
|
@ -876,30 +879,26 @@ gst_avi_demux_parse_subindex (GstElement * element,
|
||||||
entry->stream_nr = stream->num;
|
entry->stream_nr = stream->num;
|
||||||
|
|
||||||
/* timestamps */
|
/* timestamps */
|
||||||
if (stream->strh->samplesize && stream->strh->type == GST_RIFF_FCC_auds) {
|
entry->ts = stream->total_time;
|
||||||
/* constant rate stream */
|
if (stream->is_vbr) {
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
/* VBR get next timestamp */
|
||||||
stream->total_bytes, &format, &tmp);
|
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
||||||
entry->ts = tmp;
|
stream->total_frames + 1, &format, &next_ts);
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
|
||||||
stream->total_bytes + entry->size, &format, &tmp);
|
|
||||||
entry->dur = tmp;
|
|
||||||
} else {
|
} else {
|
||||||
/* VBR stream */
|
/* CBR get next timestamp */
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
||||||
stream->total_frames, &format, &tmp);
|
stream->total_bytes + entry->size, &format, &next_ts);
|
||||||
entry->ts = tmp;
|
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
|
||||||
stream->total_frames + 1, &format, &tmp);
|
|
||||||
entry->dur = tmp;
|
|
||||||
}
|
}
|
||||||
entry->dur -= entry->ts;
|
/* duration is next - current */
|
||||||
|
entry->dur = next_ts - entry->ts;
|
||||||
|
|
||||||
/* stream position */
|
/* stream position */
|
||||||
entry->bytes_before = stream->total_bytes;
|
entry->bytes_before = stream->total_bytes;
|
||||||
stream->total_bytes += entry->size;
|
|
||||||
entry->frames_before = stream->total_frames;
|
entry->frames_before = stream->total_frames;
|
||||||
|
|
||||||
|
stream->total_bytes += entry->size;
|
||||||
stream->total_frames++;
|
stream->total_frames++;
|
||||||
|
stream->total_time = next_ts;
|
||||||
|
|
||||||
entries_list = g_list_prepend (entries_list, entry);
|
entries_list = g_list_prepend (entries_list, entry);
|
||||||
}
|
}
|
||||||
|
@ -1020,6 +1019,7 @@ gst_avi_demux_parse_stream (GstElement * element, GstBuffer * buf)
|
||||||
} else if (!gst_riff_parse_strh (element, sub, &stream->strh))
|
} else if (!gst_riff_parse_strh (element, sub, &stream->strh))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
|
||||||
/* read strf */
|
/* read strf */
|
||||||
if (!gst_riff_parse_chunk (element, buf, &offset, &tag, &sub) ||
|
if (!gst_riff_parse_chunk (element, buf, &offset, &tag, &sub) ||
|
||||||
tag != GST_RIFF_TAG_strf) {
|
tag != GST_RIFF_TAG_strf) {
|
||||||
|
@ -1033,14 +1033,19 @@ gst_avi_demux_parse_stream (GstElement * element, GstBuffer * buf)
|
||||||
|
|
||||||
switch (stream->strh->type) {
|
switch (stream->strh->type) {
|
||||||
case GST_RIFF_FCC_vids:
|
case GST_RIFF_FCC_vids:
|
||||||
|
stream->is_vbr = TRUE;
|
||||||
res = gst_riff_parse_strf_vids (element, sub,
|
res = gst_riff_parse_strf_vids (element, sub,
|
||||||
&stream->strf.vids, &stream->extradata);
|
&stream->strf.vids, &stream->extradata);
|
||||||
break;
|
break;
|
||||||
case GST_RIFF_FCC_auds:
|
case GST_RIFF_FCC_auds:
|
||||||
res = gst_riff_parse_strf_auds (element, sub,
|
stream->is_vbr = (stream->strh->samplesize == 0)
|
||||||
&stream->strf.auds, &stream->extradata);
|
&& stream->strh->scale > 1;
|
||||||
|
res =
|
||||||
|
gst_riff_parse_strf_auds (element, sub, &stream->strf.auds,
|
||||||
|
&stream->extradata);
|
||||||
break;
|
break;
|
||||||
case GST_RIFF_FCC_iavs:
|
case GST_RIFF_FCC_iavs:
|
||||||
|
stream->is_vbr = TRUE;
|
||||||
res = gst_riff_parse_strf_iavs (element, sub,
|
res = gst_riff_parse_strf_iavs (element, sub,
|
||||||
&stream->strf.iavs, &stream->extradata);
|
&stream->strf.iavs, &stream->extradata);
|
||||||
break;
|
break;
|
||||||
|
@ -1319,7 +1324,7 @@ gst_avi_demux_parse_index (GstElement * element,
|
||||||
gint stream_nr;
|
gint stream_nr;
|
||||||
gst_avi_index_entry *target;
|
gst_avi_index_entry *target;
|
||||||
GstFormat format;
|
GstFormat format;
|
||||||
gint64 ts;
|
gint64 next_ts;
|
||||||
|
|
||||||
_entry = &((gst_riff_index_entry *) data)[i];
|
_entry = &((gst_riff_index_entry *) data)[i];
|
||||||
entry.id = GUINT32_FROM_LE (_entry->id);
|
entry.id = GUINT32_FROM_LE (_entry->id);
|
||||||
|
@ -1354,43 +1359,41 @@ gst_avi_demux_parse_index (GstElement * element,
|
||||||
avi->index_offset = 0;
|
avi->index_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
target->bytes_before = stream->total_bytes;
|
|
||||||
target->frames_before = stream->total_frames;
|
|
||||||
|
|
||||||
format = GST_FORMAT_TIME;
|
format = GST_FORMAT_TIME;
|
||||||
if (stream->strh->type == GST_RIFF_FCC_auds) {
|
if (stream->strh->type == GST_RIFF_FCC_auds) {
|
||||||
/* all audio frames are keyframes */
|
/* all audio frames are keyframes */
|
||||||
target->flags |= GST_RIFF_IF_KEYFRAME;
|
target->flags |= GST_RIFF_IF_KEYFRAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream->strh->samplesize && stream->strh->type == GST_RIFF_FCC_auds) {
|
/* timestamps */
|
||||||
|
target->ts = stream->total_time;
|
||||||
|
if (stream->is_vbr) {
|
||||||
|
/* VBR stream next timestamp */
|
||||||
|
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
||||||
|
stream->total_frames + 1, &format, &next_ts);
|
||||||
|
} else {
|
||||||
/* constant rate stream */
|
/* constant rate stream */
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
||||||
stream->total_bytes, &format, &ts);
|
stream->total_bytes + target->size, &format, &next_ts);
|
||||||
target->ts = ts;
|
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
|
||||||
stream->total_bytes + target->size, &format, &ts);
|
|
||||||
target->dur = ts;
|
|
||||||
} else {
|
|
||||||
/* VBR stream */
|
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
|
||||||
stream->total_frames, &format, &ts);
|
|
||||||
target->ts = ts;
|
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
|
||||||
stream->total_frames + 1, &format, &ts);
|
|
||||||
target->dur = ts;
|
|
||||||
}
|
}
|
||||||
target->dur -= target->ts;
|
/* duration is next - current */
|
||||||
|
target->dur = next_ts - target->ts;
|
||||||
|
|
||||||
|
/* stream position */
|
||||||
|
target->bytes_before = stream->total_bytes;
|
||||||
|
target->frames_before = stream->total_frames;
|
||||||
|
|
||||||
stream->total_bytes += target->size;
|
stream->total_bytes += target->size;
|
||||||
|
stream->total_time = next_ts;
|
||||||
stream->total_frames++;
|
stream->total_frames++;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (avi,
|
GST_DEBUG_OBJECT (avi,
|
||||||
"Adding index entry %d (%d) flags %08x for stream %d of size %u "
|
"Adding index entry %d (%d), flags %08x, stream %d, size %u "
|
||||||
"at offset %" G_GUINT64_FORMAT " and time %" GST_TIME_FORMAT,
|
", offset %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT ", dur %"
|
||||||
|
GST_TIME_FORMAT,
|
||||||
target->index_nr, stream->total_frames - 1, target->flags,
|
target->index_nr, stream->total_frames - 1, target->flags,
|
||||||
target->stream_nr, target->size, target->offset,
|
target->stream_nr, target->size, target->offset,
|
||||||
GST_TIME_ARGS (target->ts));
|
GST_TIME_ARGS (target->ts), GST_TIME_ARGS (target->dur));
|
||||||
entries_list = g_list_prepend (entries_list, target);
|
entries_list = g_list_prepend (entries_list, target);
|
||||||
|
|
||||||
n++;
|
n++;
|
||||||
|
@ -1448,8 +1451,10 @@ gst_avi_demux_stream_index (GstAviDemux * avi,
|
||||||
avi_stream_context *stream;
|
avi_stream_context *stream;
|
||||||
|
|
||||||
stream = &avi->stream[i];
|
stream = &avi->stream[i];
|
||||||
GST_DEBUG_OBJECT (avi, "stream %u: %u frames, %" G_GINT64_FORMAT " bytes",
|
GST_DEBUG_OBJECT (avi, "stream %u: %u frames, %" G_GINT64_FORMAT " bytes, %"
|
||||||
i, stream->total_frames, stream->total_bytes);
|
GST_TIME_FORMAT " time",
|
||||||
|
i, stream->total_frames, stream->total_bytes,
|
||||||
|
GST_TIME_ARGS (stream->total_time));
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1743,17 +1748,8 @@ gst_avi_demux_stream_scan (GstAviDemux * avi,
|
||||||
entry->size = size;
|
entry->size = size;
|
||||||
|
|
||||||
/* timestamps */
|
/* timestamps */
|
||||||
if (stream->strh->samplesize && stream->strh->type == GST_RIFF_FCC_auds) {
|
format = GST_FORMAT_TIME;
|
||||||
format = GST_FORMAT_TIME;
|
if (stream->is_vbr) {
|
||||||
/* constant rate stream */
|
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
|
||||||
stream->total_bytes, &format, &tmpts);
|
|
||||||
entry->ts = tmpts;
|
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
|
||||||
stream->total_bytes + entry->size, &format, &tmpdur);
|
|
||||||
entry->dur = tmpdur;
|
|
||||||
} else {
|
|
||||||
format = GST_FORMAT_TIME;
|
|
||||||
/* VBR stream */
|
/* VBR stream */
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
||||||
stream->total_frames, &format, &tmpts);
|
stream->total_frames, &format, &tmpts);
|
||||||
|
@ -1761,6 +1757,14 @@ gst_avi_demux_stream_scan (GstAviDemux * avi,
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
||||||
stream->total_frames + 1, &format, &tmpdur);
|
stream->total_frames + 1, &format, &tmpdur);
|
||||||
entry->dur = tmpdur;
|
entry->dur = tmpdur;
|
||||||
|
} else {
|
||||||
|
/* constant rate stream */
|
||||||
|
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
||||||
|
stream->total_bytes, &format, &tmpts);
|
||||||
|
entry->ts = tmpts;
|
||||||
|
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
||||||
|
stream->total_bytes + entry->size, &format, &tmpdur);
|
||||||
|
entry->dur = tmpdur;
|
||||||
}
|
}
|
||||||
entry->dur -= entry->ts;
|
entry->dur -= entry->ts;
|
||||||
|
|
||||||
|
@ -1809,18 +1813,18 @@ gst_avi_demux_stream_scan (GstAviDemux * avi,
|
||||||
entry->size = GST_READ_UINT32_LE (&data[4]);
|
entry->size = GST_READ_UINT32_LE (&data[4]);
|
||||||
|
|
||||||
/* timestamps */
|
/* timestamps */
|
||||||
if (stream->strh->samplesize && stream->strh->type == GST_RIFF_FCC_auds) {
|
if (stream->is_vbr) {
|
||||||
/* constant rate stream */
|
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
|
||||||
stream->total_bytes, &format, &entry->ts);
|
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
|
||||||
stream->total_bytes + entry->size, &format, &entry->dur);
|
|
||||||
} else {
|
|
||||||
/* VBR stream */
|
/* VBR stream */
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
||||||
stream->total_frames, &format, &entry->ts);
|
stream->total_frames, &format, &entry->ts);
|
||||||
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_DEFAULT,
|
||||||
stream->total_frames + 1, &format, &entry->dur);
|
stream->total_frames + 1, &format, &entry->dur);
|
||||||
|
} else {
|
||||||
|
/* constant rate stream */
|
||||||
|
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
||||||
|
stream->total_bytes, &format, &entry->ts);
|
||||||
|
gst_avi_demux_src_convert (stream->pad, GST_FORMAT_BYTES,
|
||||||
|
stream->total_bytes + entry->size, &format, &entry->dur);
|
||||||
}
|
}
|
||||||
entry->dur -= entry->ts;
|
entry->dur -= entry->ts;
|
||||||
|
|
||||||
|
@ -2020,8 +2024,10 @@ gst_avi_demux_massage_index (GstAviDemux * avi,
|
||||||
g_list_free (list);
|
g_list_free (list);
|
||||||
|
|
||||||
for (i = 0; i < avi->num_streams; i++) {
|
for (i = 0; i < avi->num_streams; i++) {
|
||||||
GST_LOG_OBJECT (avi, "Stream %d, %d frames, %" G_GUINT64_FORMAT " bytes", i,
|
GST_LOG_OBJECT (avi, "Stream %d, %d frames, %" G_GUINT64_FORMAT " bytes, %"
|
||||||
avi->stream[i].total_frames, avi->stream[i].total_bytes);
|
GST_TIME_FORMAT " time", i,
|
||||||
|
avi->stream[i].total_frames, avi->stream[i].total_bytes,
|
||||||
|
GST_TIME_ARGS (avi->stream[i].total_time));
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (avi, "Index massaging done");
|
GST_LOG_OBJECT (avi, "Index massaging done");
|
||||||
|
@ -2031,37 +2037,40 @@ static void
|
||||||
gst_avi_demux_calculate_durations_from_index (GstAviDemux * avi)
|
gst_avi_demux_calculate_durations_from_index (GstAviDemux * avi)
|
||||||
{
|
{
|
||||||
gst_avi_index_entry *entry;
|
gst_avi_index_entry *entry;
|
||||||
GstClockTime end_time = GST_CLOCK_TIME_NONE;
|
GstClockTime end_time;
|
||||||
gint stream, i;
|
gint stream, i;
|
||||||
|
|
||||||
/* we assume all streams start at a timestamp of 0 for now */
|
/* we assume all streams start at a timestamp of 0 for now */
|
||||||
for (stream = 0; stream < avi->num_streams; ++stream) {
|
for (stream = 0; stream < avi->num_streams; stream++) {
|
||||||
|
end_time = GST_CLOCK_TIME_NONE;
|
||||||
i = 0;
|
i = 0;
|
||||||
while ((entry = gst_avi_demux_index_next (avi, stream, i))) {
|
while ((entry = gst_avi_demux_index_next (avi, stream, i))) {
|
||||||
end_time = entry->ts + entry->dur;
|
end_time = entry->ts + entry->dur;
|
||||||
++i;
|
i++;
|
||||||
}
|
}
|
||||||
if (GST_CLOCK_TIME_IS_VALID (end_time)) {
|
if (GST_CLOCK_TIME_IS_VALID (end_time)) {
|
||||||
avi->stream[stream].idx_duration = end_time;
|
|
||||||
GST_INFO ("Stream %d duration according to index: %" GST_TIME_FORMAT,
|
GST_INFO ("Stream %d duration according to index: %" GST_TIME_FORMAT,
|
||||||
stream, GST_TIME_ARGS (avi->stream[stream].idx_duration));
|
stream, GST_TIME_ARGS (end_time));
|
||||||
|
avi->stream[stream].idx_duration = end_time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_avi_demux_send_event (GstAviDemux * avi, GstEvent * event)
|
gst_avi_demux_push_event (GstAviDemux * avi, GstEvent * event)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
|
gboolean result = TRUE;
|
||||||
|
|
||||||
for (i = 0; i < avi->num_streams; i++) {
|
for (i = 0; i < avi->num_streams; i++) {
|
||||||
avi_stream_context *stream = &avi->stream[i];
|
avi_stream_context *stream = &avi->stream[i];
|
||||||
|
|
||||||
gst_event_ref (event);
|
gst_event_ref (event);
|
||||||
gst_pad_push_event (stream->pad, event);
|
result &= gst_pad_push_event (stream->pad, event);
|
||||||
}
|
}
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
return TRUE;
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2230,6 +2239,7 @@ done:
|
||||||
gst_avi_demux_stream_scan (avi, &index, &alloc);
|
gst_avi_demux_stream_scan (avi, &index, &alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this is a fatal error */
|
||||||
if (!index)
|
if (!index)
|
||||||
goto no_index;
|
goto no_index;
|
||||||
|
|
||||||
|
@ -2237,16 +2247,16 @@ done:
|
||||||
gst_avi_demux_calculate_durations_from_index (avi);
|
gst_avi_demux_calculate_durations_from_index (avi);
|
||||||
|
|
||||||
/* send initial discont */
|
/* send initial discont */
|
||||||
avi->segment_start = 0;
|
avi->segment.start = 0;
|
||||||
avi->segment_stop =
|
avi->segment.stop =
|
||||||
gst_util_uint64_scale_int ((gint64) avi->stream[0].strh->scale *
|
gst_util_uint64_scale_int ((gint64) avi->stream[0].strh->scale *
|
||||||
avi->stream[0].strh->length, GST_SECOND, avi->stream[0].strh->rate);
|
avi->stream[0].strh->length, GST_SECOND, avi->stream[0].strh->rate);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (avi, "segment stop %" G_GINT64_FORMAT, avi->segment_stop);
|
GST_DEBUG_OBJECT (avi, "segment stop %" G_GINT64_FORMAT, avi->segment.stop);
|
||||||
|
|
||||||
avi->seek_event = gst_event_new_new_segment
|
avi->seek_event = gst_event_new_new_segment
|
||||||
(FALSE, avi->segment_rate, GST_FORMAT_TIME,
|
(FALSE, avi->segment.rate, GST_FORMAT_TIME,
|
||||||
avi->segment_start, avi->segment_stop, avi->segment_start);
|
avi->segment.start, avi->segment.stop, avi->segment.start);
|
||||||
|
|
||||||
/* at this point we know all the streams and we can signal the no more
|
/* at this point we know all the streams and we can signal the no more
|
||||||
* pads signal */
|
* pads signal */
|
||||||
|
@ -2321,19 +2331,16 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, gboolean update)
|
||||||
{
|
{
|
||||||
GstClockTime start_time;
|
GstClockTime start_time;
|
||||||
gboolean flush, keyframe;
|
gboolean flush, keyframe;
|
||||||
guint stream;
|
|
||||||
gst_avi_index_entry *entry;
|
gst_avi_index_entry *entry;
|
||||||
|
|
||||||
/* FIXME: if we seek in an openDML file, we will have multiple
|
/* FIXME: if we seek in an openDML file, we will have multiple
|
||||||
* primary levels. Seeking in between those will cause havoc. */
|
* primary levels. Seeking in between those will cause havoc. */
|
||||||
|
|
||||||
flush = avi->segment_flags & GST_SEEK_FLAG_FLUSH;
|
flush = avi->segment.flags & GST_SEEK_FLAG_FLUSH;
|
||||||
keyframe = avi->segment_flags & GST_SEEK_FLAG_KEY_UNIT;
|
keyframe = avi->segment.flags & GST_SEEK_FLAG_KEY_UNIT;
|
||||||
|
|
||||||
if (flush) {
|
if (flush) {
|
||||||
for (stream = avi->num_streams; stream--;)
|
gst_avi_demux_push_event (avi, gst_event_new_flush_start ());
|
||||||
gst_pad_push_event (avi->stream[stream].pad,
|
|
||||||
gst_event_new_flush_start ());
|
|
||||||
gst_pad_push_event (avi->sinkpad, gst_event_new_flush_start ());
|
gst_pad_push_event (avi->sinkpad, gst_event_new_flush_start ());
|
||||||
} else
|
} else
|
||||||
gst_pad_pause_task (avi->sinkpad);
|
gst_pad_pause_task (avi->sinkpad);
|
||||||
|
@ -2342,7 +2349,7 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, gboolean update)
|
||||||
|
|
||||||
/* fill current_entry according to flags and update */
|
/* fill current_entry according to flags and update */
|
||||||
if (update) {
|
if (update) {
|
||||||
entry = gst_avi_demux_index_entry_for_time (avi, 0, avi->segment_start,
|
entry = gst_avi_demux_index_entry_for_time (avi, 0, avi->segment.start,
|
||||||
(guint32) GST_RIFF_IF_KEYFRAME);
|
(guint32) GST_RIFF_IF_KEYFRAME);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
GST_DEBUG_OBJECT (avi,
|
GST_DEBUG_OBJECT (avi,
|
||||||
|
@ -2354,30 +2361,29 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, gboolean update)
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING_OBJECT (avi,
|
GST_WARNING_OBJECT (avi,
|
||||||
"Couldn't find AviIndexEntry for time:%" GST_TIME_FORMAT,
|
"Couldn't find AviIndexEntry for time:%" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (avi->segment_start));
|
GST_TIME_ARGS (avi->segment.start));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (avi, "seek: %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT
|
GST_DEBUG_OBJECT (avi, "seek: %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT
|
||||||
" keyframe seeking:%d update:%d", GST_TIME_ARGS (avi->segment_start),
|
" keyframe seeking:%d update:%d", GST_TIME_ARGS (avi->segment.start),
|
||||||
GST_TIME_ARGS (avi->segment_stop), keyframe, update);
|
GST_TIME_ARGS (avi->segment.stop), keyframe, update);
|
||||||
|
|
||||||
if (keyframe)
|
if (keyframe)
|
||||||
start_time = avi->index_entries[avi->current_entry].ts;
|
start_time = avi->index_entries[avi->current_entry].ts;
|
||||||
else
|
else
|
||||||
start_time = avi->segment_start;
|
start_time = avi->segment.start;
|
||||||
|
|
||||||
avi->seek_event = gst_event_new_new_segment
|
avi->seek_event = gst_event_new_new_segment
|
||||||
(!update, avi->segment_rate, GST_FORMAT_TIME,
|
(!update, avi->segment.rate, GST_FORMAT_TIME,
|
||||||
start_time, avi->segment_stop, start_time);
|
start_time, avi->segment.stop, start_time);
|
||||||
|
|
||||||
if (flush) {
|
if (flush) {
|
||||||
for (stream = avi->num_streams; stream--;)
|
gst_avi_demux_push_event (avi, gst_event_new_flush_start ());
|
||||||
gst_pad_push_event (avi->stream[stream].pad, gst_event_new_flush_stop ());
|
|
||||||
gst_pad_push_event (avi->sinkpad, gst_event_new_flush_stop ());
|
gst_pad_push_event (avi->sinkpad, gst_event_new_flush_stop ());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avi->segment_flags & GST_SEEK_FLAG_SEGMENT) {
|
if (avi->segment.flags & GST_SEEK_FLAG_SEGMENT) {
|
||||||
gst_element_post_message (GST_ELEMENT (avi),
|
gst_element_post_message (GST_ELEMENT (avi),
|
||||||
gst_message_new_segment_start (GST_OBJECT (avi), GST_FORMAT_TIME,
|
gst_message_new_segment_start (GST_OBJECT (avi), GST_FORMAT_TIME,
|
||||||
start_time));
|
start_time));
|
||||||
|
@ -2481,11 +2487,11 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi)
|
||||||
|
|
||||||
if ((entry->flags & GST_RIFF_IF_KEYFRAME)
|
if ((entry->flags & GST_RIFF_IF_KEYFRAME)
|
||||||
&& GST_CLOCK_TIME_IS_VALID (entry->ts)
|
&& GST_CLOCK_TIME_IS_VALID (entry->ts)
|
||||||
&& GST_CLOCK_TIME_IS_VALID (avi->segment_stop)
|
&& GST_CLOCK_TIME_IS_VALID (avi->segment.stop)
|
||||||
&& (entry->ts > avi->segment_stop)) {
|
&& (entry->ts > avi->segment.stop)) {
|
||||||
GST_LOG_OBJECT (avi, "Found keyframe after segment,"
|
GST_LOG_OBJECT (avi, "Found keyframe after segment,"
|
||||||
" setting EOS (%" GST_TIME_FORMAT " > %" GST_TIME_FORMAT ")",
|
" setting EOS (%" GST_TIME_FORMAT " > %" GST_TIME_FORMAT ")",
|
||||||
GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (avi->segment_stop));
|
GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (avi->segment.stop));
|
||||||
goto eos;
|
goto eos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2514,6 +2520,7 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi)
|
||||||
}
|
}
|
||||||
if (!(entry->flags & GST_RIFF_IF_KEYFRAME))
|
if (!(entry->flags & GST_RIFF_IF_KEYFRAME))
|
||||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
|
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (buf) = entry->ts;
|
GST_BUFFER_TIMESTAMP (buf) = entry->ts;
|
||||||
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));
|
||||||
|
@ -2539,15 +2546,9 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
eos:
|
eos:
|
||||||
/* handle end-of-stream/segment */
|
{
|
||||||
if (avi->segment_flags & GST_SEEK_FLAG_SEGMENT)
|
return GST_FLOW_UNEXPECTED;
|
||||||
gst_element_post_message
|
}
|
||||||
(GST_ELEMENT (avi),
|
|
||||||
gst_message_new_segment_done (GST_OBJECT (avi), GST_FORMAT_TIME,
|
|
||||||
avi->segment_stop));
|
|
||||||
else
|
|
||||||
gst_avi_demux_send_event (avi, gst_event_new_eos ());
|
|
||||||
return GST_FLOW_WRONG_STATE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2644,7 +2645,7 @@ gst_avi_demux_loop (GstPad * pad)
|
||||||
break;
|
break;
|
||||||
case GST_AVI_DEMUX_MOVI:
|
case GST_AVI_DEMUX_MOVI:
|
||||||
if (avi->seek_event) {
|
if (avi->seek_event) {
|
||||||
gst_avi_demux_send_event (avi, avi->seek_event);
|
gst_avi_demux_push_event (avi, avi->seek_event);
|
||||||
avi->seek_event = NULL;
|
avi->seek_event = NULL;
|
||||||
}
|
}
|
||||||
if ((res = gst_avi_demux_stream_data (avi)) != GST_FLOW_OK) {
|
if ((res = gst_avi_demux_stream_data (avi)) != GST_FLOW_OK) {
|
||||||
|
@ -2658,24 +2659,37 @@ gst_avi_demux_loop (GstPad * pad)
|
||||||
|
|
||||||
if (gst_avi_demux_all_source_pads_unlinked (avi)) {
|
if (gst_avi_demux_all_source_pads_unlinked (avi)) {
|
||||||
GST_DEBUG_OBJECT (avi, "all source pads unlinked, pausing");
|
GST_DEBUG_OBJECT (avi, "all source pads unlinked, pausing");
|
||||||
|
res = GST_FLOW_NOT_LINKED;
|
||||||
goto pause;
|
goto pause;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pause:
|
pause:
|
||||||
GST_LOG_OBJECT (avi, "pausing task");
|
{
|
||||||
gst_pad_pause_task (avi->sinkpad);
|
GST_LOG_OBJECT (avi, "pausing task, reason %s", gst_flow_get_name (res));
|
||||||
if (GST_FLOW_IS_FATAL (res)) {
|
gst_pad_pause_task (avi->sinkpad);
|
||||||
guint stream = avi->num_streams;
|
if (GST_FLOW_IS_FATAL (res) || (res == GST_FLOW_NOT_LINKED)) {
|
||||||
|
gboolean push_eos = TRUE;
|
||||||
|
|
||||||
/* for fatal errors we post an error message */
|
if (res == GST_FLOW_UNEXPECTED) {
|
||||||
GST_ELEMENT_ERROR (avi, STREAM, FAILED,
|
/* handle end-of-stream/segment */
|
||||||
(_("Internal data stream error.")),
|
if (avi->segment.flags & GST_SEEK_FLAG_SEGMENT) {
|
||||||
("streaming stopped, reason %s", gst_flow_get_name (res)));
|
gst_element_post_message
|
||||||
while (stream--) {
|
(GST_ELEMENT (avi),
|
||||||
if (avi->stream[stream].pad)
|
gst_message_new_segment_done (GST_OBJECT (avi), GST_FORMAT_TIME,
|
||||||
gst_pad_push_event (avi->stream[stream].pad, gst_event_new_eos ());
|
avi->segment.stop));
|
||||||
|
push_eos = FALSE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* for fatal errors we post an error message */
|
||||||
|
GST_ELEMENT_ERROR (avi, STREAM, FAILED,
|
||||||
|
(_("Internal data stream error.")),
|
||||||
|
("streaming stopped, reason %s", gst_flow_get_name (res)));
|
||||||
|
}
|
||||||
|
if (push_eos) {
|
||||||
|
gst_avi_demux_push_event (avi, gst_event_new_eos ());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,10 @@ typedef struct {
|
||||||
/* stream length */
|
/* stream length */
|
||||||
guint64 total_bytes;
|
guint64 total_bytes;
|
||||||
guint32 total_frames;
|
guint32 total_frames;
|
||||||
|
guint64 total_time;
|
||||||
|
|
||||||
|
/* VBR indicator */
|
||||||
|
gboolean is_vbr;
|
||||||
|
|
||||||
/* stream length according to index */
|
/* stream length according to index */
|
||||||
GstClockTime idx_duration;
|
GstClockTime idx_duration;
|
||||||
|
@ -119,13 +123,10 @@ typedef struct _GstAviDemux {
|
||||||
/* some stream info for length */
|
/* some stream info for length */
|
||||||
gst_riff_avih *avih;
|
gst_riff_avih *avih;
|
||||||
|
|
||||||
/* seeking */
|
/* seeking in TIME */
|
||||||
gdouble segment_rate;
|
GstSegment segment;
|
||||||
GstSeekFlags segment_flags;
|
|
||||||
/* in GST_FORMAT_TIME */
|
|
||||||
gint64 segment_start;
|
|
||||||
gint64 segment_stop;
|
|
||||||
GstEvent *seek_event;
|
GstEvent *seek_event;
|
||||||
|
|
||||||
} GstAviDemux;
|
} GstAviDemux;
|
||||||
|
|
||||||
typedef struct _GstAviDemuxClass {
|
typedef struct _GstAviDemuxClass {
|
||||||
|
|
Loading…
Reference in a new issue