mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
[MOVED FROM BAD 36/57] gst/flv/: In pull mode we create our own index before doing anything else and don't use the index provided by some fi...
Original commit message from CVS: * gst/flv/gstflvdemux.c: (gst_flv_demux_create_index), (gst_flv_demux_loop): * gst/flv/gstflvparse.c: (gst_flv_parse_tag_script), (gst_flv_parse_tag_audio), (gst_flv_parse_tag_video), (gst_flv_parse_tag_timestamp): * gst/flv/gstflvparse.h: In pull mode we create our own index before doing anything else and don't use the index provided by some files (which are more than often incorrect and cause failed seeks). For push mode we still use the index provided by the file and extend it while doing the playback.
This commit is contained in:
parent
78c8ad8cf2
commit
f945537a8a
3 changed files with 96 additions and 53 deletions
|
@ -448,6 +448,34 @@ gst_flv_demux_push_src_event (GstFLVDemux * demux, GstEvent * event)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_flv_demux_create_index (GstFLVDemux * demux)
|
||||
{
|
||||
gint64 size;
|
||||
GstFormat fmt = GST_FORMAT_BYTES;
|
||||
size_t tag_size;
|
||||
guint64 old_offset;
|
||||
GstBuffer *buffer;
|
||||
GstFlowReturn ret;
|
||||
|
||||
if (!gst_pad_query_peer_duration (demux->sinkpad, &fmt, &size) ||
|
||||
fmt != GST_FORMAT_BYTES)
|
||||
return;
|
||||
|
||||
old_offset = demux->offset;
|
||||
|
||||
while ((ret =
|
||||
gst_flv_demux_pull_range (demux, demux->sinkpad, demux->offset, 12,
|
||||
&buffer)) == GST_FLOW_OK) {
|
||||
if (gst_flv_parse_tag_timestamp (demux, GST_BUFFER_DATA (buffer),
|
||||
GST_BUFFER_SIZE (buffer), &tag_size) == GST_CLOCK_TIME_NONE)
|
||||
break;
|
||||
demux->offset += tag_size;
|
||||
}
|
||||
|
||||
demux->offset = old_offset;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_flv_demux_loop (GstPad * pad)
|
||||
{
|
||||
|
@ -467,38 +495,9 @@ gst_flv_demux_loop (GstPad * pad)
|
|||
break;
|
||||
default:
|
||||
ret = gst_flv_demux_pull_header (pad, demux);
|
||||
if (ret == GST_FLOW_OK)
|
||||
gst_flv_demux_create_index (demux);
|
||||
|
||||
/* If we parsed the header successfully try to get an
|
||||
* approximate duration by looking at the last tag's timestamp */
|
||||
if (ret == GST_FLOW_OK) {
|
||||
gint64 size;
|
||||
GstFormat fmt = GST_FORMAT_BYTES;
|
||||
|
||||
if (gst_pad_query_peer_duration (pad, &fmt, &size) &&
|
||||
fmt == GST_FORMAT_BYTES && size != -1 && size > FLV_HEADER_SIZE) {
|
||||
GstBuffer *buffer;
|
||||
|
||||
if (gst_flv_demux_pull_range (demux, pad, size - 4, 4,
|
||||
&buffer) == GST_FLOW_OK) {
|
||||
guint32 prev_tag_size =
|
||||
GST_READ_UINT32_BE (GST_BUFFER_DATA (buffer));
|
||||
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
if (size - 4 - prev_tag_size > FLV_HEADER_SIZE &&
|
||||
prev_tag_size >= 8 &&
|
||||
gst_flv_demux_pull_range (demux, pad,
|
||||
size - prev_tag_size - 4, prev_tag_size,
|
||||
&buffer) == GST_FLOW_OK) {
|
||||
demux->duration =
|
||||
gst_flv_parse_tag_timestamp (demux,
|
||||
GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
|
||||
|
||||
gst_buffer_unref (buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* pause if something went wrong */
|
||||
|
@ -527,6 +526,8 @@ gst_flv_demux_loop (GstPad * pad)
|
|||
break;
|
||||
default:
|
||||
ret = gst_flv_demux_pull_header (pad, demux);
|
||||
if (ret == GST_FLOW_OK)
|
||||
gst_flv_demux_create_index (demux);
|
||||
}
|
||||
|
||||
/* pause if something went wrong */
|
||||
|
|
|
@ -371,8 +371,9 @@ gst_flv_parse_tag_script (GstFLVDemux * demux, const guint8 * data,
|
|||
|
||||
g_free (function_name);
|
||||
|
||||
if (demux->index && demux->times && demux->filepositions) {
|
||||
/* If an index was found, insert associations */
|
||||
if (demux->index && demux->times && demux->filepositions
|
||||
&& !demux->random_access) {
|
||||
/* If an index was found and we're in push mode, insert associations */
|
||||
for (i = 0; i < MIN (demux->times->len, demux->filepositions->len); i++) {
|
||||
guint64 time, fileposition;
|
||||
|
||||
|
@ -676,17 +677,20 @@ gst_flv_parse_tag_audio (GstFLVDemux * demux, const guint8 * data,
|
|||
GST_BUFFER_OFFSET (buffer) = demux->audio_offset++;
|
||||
GST_BUFFER_OFFSET_END (buffer) = demux->audio_offset;
|
||||
|
||||
/* Only add audio frames to the index if we have no video */
|
||||
if (!demux->has_video) {
|
||||
if (demux->index) {
|
||||
GST_LOG_OBJECT (demux, "adding association %" GST_TIME_FORMAT "-> %"
|
||||
G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
|
||||
demux->cur_tag_offset);
|
||||
gst_index_add_association (demux->index, demux->index_id,
|
||||
GST_ASSOCIATION_FLAG_KEY_UNIT,
|
||||
GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer),
|
||||
GST_FORMAT_BYTES, demux->cur_tag_offset, NULL);
|
||||
}
|
||||
if (demux->duration == GST_CLOCK_TIME_NONE ||
|
||||
demux->duration < GST_BUFFER_TIMESTAMP (buffer))
|
||||
demux->duration = GST_BUFFER_TIMESTAMP (buffer);
|
||||
|
||||
/* Only add audio frames to the index if we have no video
|
||||
* and if we don't have random access */
|
||||
if (!demux->has_video && demux->index && !demux->random_access) {
|
||||
GST_LOG_OBJECT (demux, "adding association %" GST_TIME_FORMAT "-> %"
|
||||
G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
|
||||
demux->cur_tag_offset);
|
||||
gst_index_add_association (demux->index, demux->index_id,
|
||||
GST_ASSOCIATION_FLAG_KEY_UNIT,
|
||||
GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer),
|
||||
GST_FORMAT_BYTES, demux->cur_tag_offset, NULL);
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (demux->audio_need_discont)) {
|
||||
|
@ -978,9 +982,13 @@ gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
|
|||
GST_BUFFER_OFFSET (buffer) = demux->video_offset++;
|
||||
GST_BUFFER_OFFSET_END (buffer) = demux->video_offset;
|
||||
|
||||
if (demux->duration == GST_CLOCK_TIME_NONE ||
|
||||
demux->duration < GST_BUFFER_TIMESTAMP (buffer))
|
||||
demux->duration = GST_BUFFER_TIMESTAMP (buffer);
|
||||
|
||||
if (!keyframe) {
|
||||
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||
if (demux->index) {
|
||||
if (demux->index && !demux->random_access) {
|
||||
GST_LOG_OBJECT (demux, "adding association %" GST_TIME_FORMAT "-> %"
|
||||
G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
|
||||
demux->cur_tag_offset);
|
||||
|
@ -990,7 +998,7 @@ gst_flv_parse_tag_video (GstFLVDemux * demux, const guint8 * data,
|
|||
GST_FORMAT_BYTES, demux->cur_tag_offset, NULL);
|
||||
}
|
||||
} else {
|
||||
if (demux->index) {
|
||||
if (demux->index && !demux->random_access) {
|
||||
GST_LOG_OBJECT (demux, "adding association %" GST_TIME_FORMAT "-> %"
|
||||
G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
|
||||
demux->cur_tag_offset);
|
||||
|
@ -1049,20 +1057,35 @@ beach:
|
|||
|
||||
GstClockTime
|
||||
gst_flv_parse_tag_timestamp (GstFLVDemux * demux, const guint8 * data,
|
||||
size_t data_size)
|
||||
size_t data_size, size_t * tag_size)
|
||||
{
|
||||
guint32 pts = 0, pts_ext = 0;
|
||||
guint32 tag_data_size;
|
||||
guint8 type;
|
||||
gboolean keyframe = TRUE;
|
||||
GstClockTime ret;
|
||||
|
||||
if (data[0] != 9 && data[0] != 8 && data[0] != 18) {
|
||||
g_return_val_if_fail (data_size >= 12, GST_CLOCK_TIME_NONE);
|
||||
|
||||
type = data[0];
|
||||
|
||||
if (type != 9 && type != 8 && type != 18) {
|
||||
GST_WARNING_OBJECT (demux, "Unsupported tag type %u", data[0]);
|
||||
return GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
if (FLV_GET_BEUI24 (data + 1, data_size - 1) != data_size - 11) {
|
||||
GST_WARNING_OBJECT (demux, "Invalid tag");
|
||||
return GST_CLOCK_TIME_NONE;
|
||||
tag_data_size = FLV_GET_BEUI24 (data + 1, data_size - 1);
|
||||
|
||||
if (data_size >= tag_data_size + 11 + 4) {
|
||||
if (GST_READ_UINT32_BE (data + tag_data_size + 11) != tag_data_size + 11) {
|
||||
GST_WARNING_OBJECT (demux, "Invalid tag size");
|
||||
return GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (tag_size)
|
||||
*tag_size = tag_data_size + 11 + 4;
|
||||
|
||||
data += 4;
|
||||
|
||||
GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X", data[0], data[1],
|
||||
|
@ -1075,7 +1098,26 @@ gst_flv_parse_tag_timestamp (GstFLVDemux * demux, const guint8 * data,
|
|||
/* Combine them */
|
||||
pts |= pts_ext << 24;
|
||||
|
||||
return pts * GST_MSECOND;
|
||||
if (type == 9) {
|
||||
data += 7;
|
||||
|
||||
keyframe = ((data[0] >> 4) == 1);
|
||||
}
|
||||
|
||||
ret = pts * GST_MSECOND;
|
||||
|
||||
if (demux->index && (type == 9 || (type == 8 && !demux->has_video))) {
|
||||
GST_LOG_OBJECT (demux, "adding association %" GST_TIME_FORMAT "-> %"
|
||||
G_GUINT64_FORMAT, GST_TIME_ARGS (ret), demux->offset);
|
||||
gst_index_add_association (demux->index, demux->index_id,
|
||||
(keyframe) ? GST_ASSOCIATION_FLAG_KEY_UNIT : GST_ASSOCIATION_FLAG_NONE,
|
||||
GST_FORMAT_TIME, ret, GST_FORMAT_BYTES, demux->offset, NULL);
|
||||
}
|
||||
|
||||
if (demux->duration == GST_CLOCK_TIME_NONE || demux->duration < ret)
|
||||
demux->duration = ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GstFlowReturn
|
||||
|
|
|
@ -38,7 +38,7 @@ GstFlowReturn gst_flv_parse_tag_type (GstFLVDemux * demux, const guint8 * data,
|
|||
GstFlowReturn gst_flv_parse_header (GstFLVDemux * demux, const guint8 * data,
|
||||
size_t data_size);
|
||||
|
||||
GstClockTime gst_flv_parse_tag_timestamp (GstFLVDemux *demux, const guint8 *data, size_t data_size);
|
||||
GstClockTime gst_flv_parse_tag_timestamp (GstFLVDemux *demux, const guint8 *data, size_t data_size, size_t *tag_data_size);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __FLV_PARSE_H__ */
|
||||
|
|
Loading…
Reference in a new issue