mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-22 14:06:23 +00:00
gst/realmedia/rmdemux.c: Real demuxer fixes. Make it more bulletproof against bad data, identify a few more stream ty...
Original commit message from CVS: * gst/realmedia/rmdemux.c: (gst_rmdemux_src_event), (gst_rmdemux_perform_seek), (gst_rmdemux_loop), (gst_rmdemux_send_event), (gst_rmdemux_add_stream), (gst_rmdemux_parse_mdpr), (gst_rmdemux_parse_packet): Real demuxer fixes. Make it more bulletproof against bad data, identify a few more stream types. Fix seeking so that it works (at least with the seek example program; it still fails with totem).
This commit is contained in:
parent
b293389291
commit
3dc55cb75e
2 changed files with 90 additions and 19 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
2005-09-29 Michael Smith <msmith@fluendo.com>
|
||||
|
||||
* gst/realmedia/rmdemux.c: (gst_rmdemux_src_event),
|
||||
(gst_rmdemux_perform_seek), (gst_rmdemux_loop),
|
||||
(gst_rmdemux_send_event), (gst_rmdemux_add_stream),
|
||||
(gst_rmdemux_parse_mdpr), (gst_rmdemux_parse_packet):
|
||||
Real demuxer fixes. Make it more bulletproof against bad data,
|
||||
identify a few more stream types.
|
||||
Fix seeking so that it works (at least with the seek example program;
|
||||
it still fails with totem).
|
||||
|
||||
2005-09-26 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* gst/mpegaudioparse/gstmpegaudioparse.c:
|
||||
|
|
|
@ -311,8 +311,33 @@ gst_rmdemux_src_event (GstPad * pad, GstEvent * event)
|
|||
GST_DEBUG ("can only seek on TIME");
|
||||
goto done_unref;
|
||||
}
|
||||
rmdemux->segment_start = cur;
|
||||
rmdemux->segment_stop = stop;
|
||||
|
||||
GST_LOCK (rmdemux);
|
||||
|
||||
if (cur_type == GST_SEEK_TYPE_SET)
|
||||
rmdemux->segment_start = cur;
|
||||
else if (cur_type == GST_SEEK_TYPE_CUR)
|
||||
rmdemux->segment_start += cur;
|
||||
else if (cur_type == GST_SEEK_TYPE_END)
|
||||
rmdemux->segment_start = rmdemux->duration + cur;
|
||||
|
||||
if (stop_type == GST_SEEK_TYPE_SET)
|
||||
rmdemux->segment_stop = stop;
|
||||
else if (cur_type == GST_SEEK_TYPE_CUR)
|
||||
rmdemux->segment_stop += cur;
|
||||
else if (cur_type == GST_SEEK_TYPE_END)
|
||||
rmdemux->segment_stop = rmdemux->duration + cur;
|
||||
|
||||
/* Now do a sanity-check */
|
||||
if (rmdemux->segment_stop < rmdemux->segment_start) {
|
||||
GST_UNLOCK (rmdemux);
|
||||
ret = FALSE;
|
||||
GST_DEBUG_OBJECT (rmdemux, "Seek had stop " G_GUINT64_FORMAT " < start "
|
||||
G_GUINT64_FORMAT ", cannot perform seek",
|
||||
rmdemux->segment_stop, rmdemux->segment_start);
|
||||
goto done_unref;
|
||||
}
|
||||
|
||||
rmdemux->segment_play = !!(flags & GST_SEEK_FLAG_SEGMENT);
|
||||
flush = !!(flags & GST_SEEK_FLAG_FLUSH);
|
||||
gst_event_unref (event);
|
||||
|
@ -322,7 +347,6 @@ gst_rmdemux_src_event (GstPad * pad, GstEvent * event)
|
|||
GST_TIME_ARGS (rmdemux->segment_stop));
|
||||
|
||||
/* check if we can do the seek now */
|
||||
GST_LOCK (rmdemux);
|
||||
running = rmdemux->running;
|
||||
GST_UNLOCK (rmdemux);
|
||||
|
||||
|
@ -360,12 +384,21 @@ gst_rmdemux_perform_seek (GstRMDemux * rmdemux, gboolean flush)
|
|||
rmdemux->segment_stop = CLAMP (rmdemux->segment_stop, 0, rmdemux->duration);
|
||||
|
||||
/* first step is to unlock the streaming thread if it is
|
||||
* blocked in a chain call, we do this by starting the flush. because
|
||||
* we cannot yet hold any streaming lock, we have to protect the chains
|
||||
* with their own lock. */
|
||||
* blocked in a chain call, we do this by starting the flush. */
|
||||
if (flush) {
|
||||
gst_pad_push_event (rmdemux->sinkpad, gst_event_new_flush_start ());
|
||||
gst_rmdemux_send_event (rmdemux, gst_event_new_flush_start ());
|
||||
gboolean res;
|
||||
|
||||
GST_DEBUG_OBJECT (rmdemux, "About to send flush_start events");
|
||||
res = gst_pad_push_event (rmdemux->sinkpad, gst_event_new_flush_start ());
|
||||
if (!res) {
|
||||
GST_WARNING_OBJECT (rmdemux, "Failed to push event upstream!");
|
||||
}
|
||||
|
||||
res = gst_rmdemux_send_event (rmdemux, gst_event_new_flush_start ());
|
||||
if (!res) {
|
||||
GST_WARNING_OBJECT (rmdemux, "Failed to push event downstream!");
|
||||
}
|
||||
GST_DEBUG_OBJECT (rmdemux, "Sent flush_start events");
|
||||
} else {
|
||||
gst_pad_pause_task (rmdemux->sinkpad);
|
||||
}
|
||||
|
@ -374,10 +407,12 @@ gst_rmdemux_perform_seek (GstRMDemux * rmdemux, gboolean flush)
|
|||
* non flushing seeks when the element is in PAUSED this could block
|
||||
* forever. */
|
||||
GST_STREAM_LOCK (rmdemux->sinkpad);
|
||||
GST_DEBUG_OBJECT (rmdemux, "Taken stream lock on sinkpad!");
|
||||
|
||||
/* we need to stop flushing on the srcpad as we're going to use it
|
||||
/* we need to stop flushing on the sinkpad as we're going to use it
|
||||
* next. We can do this as we have the STREAM lock now. */
|
||||
gst_pad_push_event (rmdemux->sinkpad, gst_event_new_flush_stop ());
|
||||
GST_DEBUG_OBJECT (rmdemux, "Sent flush_stop downstream");
|
||||
|
||||
/* Find the new offset */
|
||||
/* Get the video stream */
|
||||
|
@ -612,7 +647,7 @@ gst_rmdemux_loop (GstPad * pad)
|
|||
{
|
||||
GstRMDemux *rmdemux;
|
||||
GstBuffer *buffer;
|
||||
GstFlowReturn ret;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
guint size;
|
||||
|
||||
rmdemux = GST_RMDEMUX (GST_PAD_PARENT (pad));
|
||||
|
@ -633,6 +668,8 @@ gst_rmdemux_loop (GstPad * pad)
|
|||
case RMDEMUX_STATE_EOS:
|
||||
goto need_pause;
|
||||
default:
|
||||
GST_LOG_OBJECT (rmdemux, "Default: requires %d bytes",
|
||||
(int) rmdemux->size);
|
||||
size = rmdemux->size;
|
||||
}
|
||||
|
||||
|
@ -649,8 +686,9 @@ gst_rmdemux_loop (GstPad * pad)
|
|||
return;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (rmdemux,
|
||||
"Unable to pull data at offset %p (pull_range returned %d)",
|
||||
rmdemux->offset, ret);
|
||||
"Unable to pull %d bytes at offset %p (pull_range returned %d, state is %d)",
|
||||
(int) size, rmdemux->offset, ret, GST_STATE (rmdemux));
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto need_pause;
|
||||
}
|
||||
}
|
||||
|
@ -658,7 +696,8 @@ gst_rmdemux_loop (GstPad * pad)
|
|||
size = GST_BUFFER_SIZE (buffer);
|
||||
|
||||
/* Defer to the chain function */
|
||||
if (gst_rmdemux_chain (pad, buffer) != GST_FLOW_OK) {
|
||||
ret = gst_rmdemux_chain (pad, buffer);
|
||||
if (ret != GST_FLOW_OK) {
|
||||
GST_DEBUG_OBJECT (rmdemux, "Chain flow failed at %p", rmdemux->offset);
|
||||
goto need_pause;
|
||||
}
|
||||
|
@ -698,6 +737,11 @@ need_pause:
|
|||
{
|
||||
GST_LOG_OBJECT (rmdemux, "pausing task");
|
||||
gst_pad_pause_task (pad);
|
||||
if (GST_FLOW_IS_FATAL (ret)) {
|
||||
gst_rmdemux_send_event (rmdemux, gst_event_new_eos ());
|
||||
GST_ELEMENT_ERROR (rmdemux, STREAM, STOPPED, (NULL),
|
||||
("stream stopped, reason %d", ret));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -968,6 +1012,7 @@ static gboolean
|
|||
gst_rmdemux_send_event (GstRMDemux * rmdemux, GstEvent * event)
|
||||
{
|
||||
int i;
|
||||
gboolean ret = TRUE;
|
||||
|
||||
for (i = 0; i < rmdemux->n_streams; i++) {
|
||||
GstRMDemuxStream *stream;
|
||||
|
@ -977,11 +1022,13 @@ gst_rmdemux_send_event (GstRMDemux * rmdemux, GstEvent * event)
|
|||
GST_DEBUG_OBJECT (rmdemux, "Pushing event to stream %d", i);
|
||||
|
||||
gst_event_ref (event);
|
||||
gst_pad_push_event (stream->pad, event);
|
||||
ret = gst_pad_push_event (stream->pad, event);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
gst_event_unref (event);
|
||||
|
||||
return TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1033,6 +1080,8 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
|
|||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&gst_rmdemux_audiosrc_template), g_strdup_printf ("audio_%02d",
|
||||
rmdemux->n_audio_streams));
|
||||
GST_LOG_OBJECT (rmdemux, "Created audio pad \"%s\"",
|
||||
gst_pad_get_name (stream->pad));
|
||||
switch (stream->fourcc) {
|
||||
/* Older RealAudio Codecs */
|
||||
case GST_RM_AUD_14_4:
|
||||
|
@ -1074,6 +1123,7 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
|
|||
|
||||
/* RALF is lossless */
|
||||
case GST_RM_AUD_RALF:
|
||||
GST_DEBUG_OBJECT (rmdemux, "RALF");
|
||||
stream->caps = gst_caps_new_simple ("audio/x-ralf-mpeg4-generic", NULL);
|
||||
break;
|
||||
|
||||
|
@ -1084,7 +1134,8 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
|
|||
|
||||
default:
|
||||
GST_WARNING_OBJECT (rmdemux,
|
||||
"Unknown audio FOURCC code " GST_FOURCC_FORMAT, stream->fourcc);
|
||||
"Unknown audio FOURCC code \"" GST_FOURCC_FORMAT "\"",
|
||||
stream->fourcc);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1116,7 +1167,7 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
|
|||
rmdemux->n_streams++;
|
||||
GST_LOG_OBJECT (rmdemux, "n_streams is now %d", rmdemux->n_streams);
|
||||
|
||||
if (stream->pad) {
|
||||
if (stream->pad && stream->caps) {
|
||||
GST_DEBUG_OBJECT (rmdemux, "setting caps: %p", stream->caps);
|
||||
|
||||
gst_pad_set_caps (stream->pad, stream->caps);
|
||||
|
@ -1145,8 +1196,8 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
|
|||
|
||||
if (gst_pad_alloc_buffer (stream->pad, GST_BUFFER_OFFSET_NONE,
|
||||
stream->extra_data_size, stream->caps, &buffer) != GST_FLOW_OK) {
|
||||
GST_WARNING_OBJECT (rmdemux, "failed to alloc src buffer for stream %d",
|
||||
stream->id);
|
||||
GST_WARNING_OBJECT (rmdemux, "failed to alloc extra_data src "
|
||||
"buffer for stream %d", stream->id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1284,6 +1335,9 @@ gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, const void *data, int length)
|
|||
stream_type = GST_RMDEMUX_STREAM_VIDEO;
|
||||
} else if (strcmp (stream2_type_string, "audio/x-pn-realaudio") == 0) {
|
||||
stream_type = GST_RMDEMUX_STREAM_AUDIO;
|
||||
} else if (strcmp (stream2_type_string, "audio/x-ralf-mpeg4-generic") == 0) {
|
||||
/* Another audio type found in the real testsuite */
|
||||
stream_type = GST_RMDEMUX_STREAM_AUDIO;
|
||||
} else if (strcmp (stream1_type_string, "") == 0 &&
|
||||
strcmp (stream2_type_string, "logical-fileinfo") == 0) {
|
||||
stream_type = GST_RMDEMUX_STREAM_FILEINFO;
|
||||
|
@ -1490,6 +1544,12 @@ gst_rmdemux_parse_packet (GstRMDemux * rmdemux, const void *data,
|
|||
|
||||
stream = gst_rmdemux_get_stream_by_id (rmdemux, id);
|
||||
|
||||
if (!stream) {
|
||||
GST_WARNING_OBJECT (rmdemux, "No stream for stream id %d in parsing "
|
||||
"data packet", id);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((rmdemux->offset + packet_size) > stream->seek_offset) {
|
||||
if (gst_pad_alloc_buffer (stream->pad, GST_BUFFER_OFFSET_NONE,
|
||||
packet_size, stream->caps, &buffer) != GST_FLOW_OK) {
|
||||
|
|
Loading…
Reference in a new issue