mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-03 17:22:29 +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>
|
2005-09-26 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* gst/mpegaudioparse/gstmpegaudioparse.c:
|
* gst/mpegaudioparse/gstmpegaudioparse.c:
|
||||||
|
|
|
@ -311,8 +311,33 @@ gst_rmdemux_src_event (GstPad * pad, GstEvent * event)
|
||||||
GST_DEBUG ("can only seek on TIME");
|
GST_DEBUG ("can only seek on TIME");
|
||||||
goto done_unref;
|
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);
|
rmdemux->segment_play = !!(flags & GST_SEEK_FLAG_SEGMENT);
|
||||||
flush = !!(flags & GST_SEEK_FLAG_FLUSH);
|
flush = !!(flags & GST_SEEK_FLAG_FLUSH);
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
|
@ -322,7 +347,6 @@ gst_rmdemux_src_event (GstPad * pad, GstEvent * event)
|
||||||
GST_TIME_ARGS (rmdemux->segment_stop));
|
GST_TIME_ARGS (rmdemux->segment_stop));
|
||||||
|
|
||||||
/* check if we can do the seek now */
|
/* check if we can do the seek now */
|
||||||
GST_LOCK (rmdemux);
|
|
||||||
running = rmdemux->running;
|
running = rmdemux->running;
|
||||||
GST_UNLOCK (rmdemux);
|
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);
|
rmdemux->segment_stop = CLAMP (rmdemux->segment_stop, 0, rmdemux->duration);
|
||||||
|
|
||||||
/* first step is to unlock the streaming thread if it is
|
/* first step is to unlock the streaming thread if it is
|
||||||
* blocked in a chain call, we do this by starting the flush. because
|
* blocked in a chain call, we do this by starting the flush. */
|
||||||
* we cannot yet hold any streaming lock, we have to protect the chains
|
|
||||||
* with their own lock. */
|
|
||||||
if (flush) {
|
if (flush) {
|
||||||
gst_pad_push_event (rmdemux->sinkpad, gst_event_new_flush_start ());
|
gboolean res;
|
||||||
gst_rmdemux_send_event (rmdemux, gst_event_new_flush_start ());
|
|
||||||
|
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 {
|
} else {
|
||||||
gst_pad_pause_task (rmdemux->sinkpad);
|
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
|
* non flushing seeks when the element is in PAUSED this could block
|
||||||
* forever. */
|
* forever. */
|
||||||
GST_STREAM_LOCK (rmdemux->sinkpad);
|
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. */
|
* next. We can do this as we have the STREAM lock now. */
|
||||||
gst_pad_push_event (rmdemux->sinkpad, gst_event_new_flush_stop ());
|
gst_pad_push_event (rmdemux->sinkpad, gst_event_new_flush_stop ());
|
||||||
|
GST_DEBUG_OBJECT (rmdemux, "Sent flush_stop downstream");
|
||||||
|
|
||||||
/* Find the new offset */
|
/* Find the new offset */
|
||||||
/* Get the video stream */
|
/* Get the video stream */
|
||||||
|
@ -612,7 +647,7 @@ gst_rmdemux_loop (GstPad * pad)
|
||||||
{
|
{
|
||||||
GstRMDemux *rmdemux;
|
GstRMDemux *rmdemux;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
guint size;
|
guint size;
|
||||||
|
|
||||||
rmdemux = GST_RMDEMUX (GST_PAD_PARENT (pad));
|
rmdemux = GST_RMDEMUX (GST_PAD_PARENT (pad));
|
||||||
|
@ -633,6 +668,8 @@ gst_rmdemux_loop (GstPad * pad)
|
||||||
case RMDEMUX_STATE_EOS:
|
case RMDEMUX_STATE_EOS:
|
||||||
goto need_pause;
|
goto need_pause;
|
||||||
default:
|
default:
|
||||||
|
GST_LOG_OBJECT (rmdemux, "Default: requires %d bytes",
|
||||||
|
(int) rmdemux->size);
|
||||||
size = rmdemux->size;
|
size = rmdemux->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,8 +686,9 @@ gst_rmdemux_loop (GstPad * pad)
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (rmdemux,
|
GST_DEBUG_OBJECT (rmdemux,
|
||||||
"Unable to pull data at offset %p (pull_range returned %d)",
|
"Unable to pull %d bytes at offset %p (pull_range returned %d, state is %d)",
|
||||||
rmdemux->offset, ret);
|
(int) size, rmdemux->offset, ret, GST_STATE (rmdemux));
|
||||||
|
ret = GST_FLOW_ERROR;
|
||||||
goto need_pause;
|
goto need_pause;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -658,7 +696,8 @@ gst_rmdemux_loop (GstPad * pad)
|
||||||
size = GST_BUFFER_SIZE (buffer);
|
size = GST_BUFFER_SIZE (buffer);
|
||||||
|
|
||||||
/* Defer to the chain function */
|
/* 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);
|
GST_DEBUG_OBJECT (rmdemux, "Chain flow failed at %p", rmdemux->offset);
|
||||||
goto need_pause;
|
goto need_pause;
|
||||||
}
|
}
|
||||||
|
@ -698,6 +737,11 @@ need_pause:
|
||||||
{
|
{
|
||||||
GST_LOG_OBJECT (rmdemux, "pausing task");
|
GST_LOG_OBJECT (rmdemux, "pausing task");
|
||||||
gst_pad_pause_task (pad);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -968,6 +1012,7 @@ static gboolean
|
||||||
gst_rmdemux_send_event (GstRMDemux * rmdemux, GstEvent * event)
|
gst_rmdemux_send_event (GstRMDemux * rmdemux, GstEvent * event)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
gboolean ret = TRUE;
|
||||||
|
|
||||||
for (i = 0; i < rmdemux->n_streams; i++) {
|
for (i = 0; i < rmdemux->n_streams; i++) {
|
||||||
GstRMDemuxStream *stream;
|
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_DEBUG_OBJECT (rmdemux, "Pushing event to stream %d", i);
|
||||||
|
|
||||||
gst_event_ref (event);
|
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);
|
gst_event_unref (event);
|
||||||
|
|
||||||
return TRUE;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1033,6 +1080,8 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
|
||||||
gst_pad_new_from_template (gst_static_pad_template_get
|
gst_pad_new_from_template (gst_static_pad_template_get
|
||||||
(&gst_rmdemux_audiosrc_template), g_strdup_printf ("audio_%02d",
|
(&gst_rmdemux_audiosrc_template), g_strdup_printf ("audio_%02d",
|
||||||
rmdemux->n_audio_streams));
|
rmdemux->n_audio_streams));
|
||||||
|
GST_LOG_OBJECT (rmdemux, "Created audio pad \"%s\"",
|
||||||
|
gst_pad_get_name (stream->pad));
|
||||||
switch (stream->fourcc) {
|
switch (stream->fourcc) {
|
||||||
/* Older RealAudio Codecs */
|
/* Older RealAudio Codecs */
|
||||||
case GST_RM_AUD_14_4:
|
case GST_RM_AUD_14_4:
|
||||||
|
@ -1074,6 +1123,7 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
|
||||||
|
|
||||||
/* RALF is lossless */
|
/* RALF is lossless */
|
||||||
case GST_RM_AUD_RALF:
|
case GST_RM_AUD_RALF:
|
||||||
|
GST_DEBUG_OBJECT (rmdemux, "RALF");
|
||||||
stream->caps = gst_caps_new_simple ("audio/x-ralf-mpeg4-generic", NULL);
|
stream->caps = gst_caps_new_simple ("audio/x-ralf-mpeg4-generic", NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1084,7 +1134,8 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
GST_WARNING_OBJECT (rmdemux,
|
GST_WARNING_OBJECT (rmdemux,
|
||||||
"Unknown audio FOURCC code " GST_FOURCC_FORMAT, stream->fourcc);
|
"Unknown audio FOURCC code \"" GST_FOURCC_FORMAT "\"",
|
||||||
|
stream->fourcc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1116,7 +1167,7 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
|
||||||
rmdemux->n_streams++;
|
rmdemux->n_streams++;
|
||||||
GST_LOG_OBJECT (rmdemux, "n_streams is now %d", 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_DEBUG_OBJECT (rmdemux, "setting caps: %p", stream->caps);
|
||||||
|
|
||||||
gst_pad_set_caps (stream->pad, 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,
|
if (gst_pad_alloc_buffer (stream->pad, GST_BUFFER_OFFSET_NONE,
|
||||||
stream->extra_data_size, stream->caps, &buffer) != GST_FLOW_OK) {
|
stream->extra_data_size, stream->caps, &buffer) != GST_FLOW_OK) {
|
||||||
GST_WARNING_OBJECT (rmdemux, "failed to alloc src buffer for stream %d",
|
GST_WARNING_OBJECT (rmdemux, "failed to alloc extra_data src "
|
||||||
stream->id);
|
"buffer for stream %d", stream->id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1284,6 +1335,9 @@ gst_rmdemux_parse_mdpr (GstRMDemux * rmdemux, const void *data, int length)
|
||||||
stream_type = GST_RMDEMUX_STREAM_VIDEO;
|
stream_type = GST_RMDEMUX_STREAM_VIDEO;
|
||||||
} else if (strcmp (stream2_type_string, "audio/x-pn-realaudio") == 0) {
|
} else if (strcmp (stream2_type_string, "audio/x-pn-realaudio") == 0) {
|
||||||
stream_type = GST_RMDEMUX_STREAM_AUDIO;
|
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 &&
|
} else if (strcmp (stream1_type_string, "") == 0 &&
|
||||||
strcmp (stream2_type_string, "logical-fileinfo") == 0) {
|
strcmp (stream2_type_string, "logical-fileinfo") == 0) {
|
||||||
stream_type = GST_RMDEMUX_STREAM_FILEINFO;
|
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);
|
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 ((rmdemux->offset + packet_size) > stream->seek_offset) {
|
||||||
if (gst_pad_alloc_buffer (stream->pad, GST_BUFFER_OFFSET_NONE,
|
if (gst_pad_alloc_buffer (stream->pad, GST_BUFFER_OFFSET_NONE,
|
||||||
packet_size, stream->caps, &buffer) != GST_FLOW_OK) {
|
packet_size, stream->caps, &buffer) != GST_FLOW_OK) {
|
||||||
|
|
Loading…
Reference in a new issue