mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-21 07:46:38 +00:00
ext/wavpack/gstwavpackparse.c: Fix resyncing in push mode not stopping re-syncing at embedded zeroes; skip garbage be...
Original commit message from CVS: Based on patch by: Sebastian Dröge <slomo at circular-chaos.org> * ext/wavpack/gstwavpackparse.c: (gst_wavpack_parse_sink_event), (gst_wavpack_parse_get_upstream_length), (gst_wavpack_parse_find_marker), (gst_wavpack_parse_resync_loop), (gst_wavpack_parse_loop), (gst_wavpack_parse_resync_adapter): Fix resyncing in push mode not stopping re-syncing at embedded zeroes; skip garbage between frames in pull mode as well if necessary; use gst_pad_query_peer_duration(); push EOS and NEWSEGMENT event in right direction (#351659).
This commit is contained in:
parent
4fb8a95581
commit
609053dae0
2 changed files with 112 additions and 28 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
|||
2006-08-18 Tim-Philipp Müller <tim at centricular dot net>
|
||||
|
||||
Based on patch by: Sebastian Dröge <slomo at circular-chaos.org>
|
||||
|
||||
* ext/wavpack/gstwavpackparse.c: (gst_wavpack_parse_sink_event),
|
||||
(gst_wavpack_parse_get_upstream_length),
|
||||
(gst_wavpack_parse_find_marker), (gst_wavpack_parse_resync_loop),
|
||||
(gst_wavpack_parse_loop), (gst_wavpack_parse_resync_adapter):
|
||||
Fix resyncing in push mode not stopping re-syncing at embedded
|
||||
zeroes; skip garbage between frames in pull mode as well if
|
||||
necessary; use gst_pad_query_peer_duration(); push EOS and
|
||||
NEWSEGMENT event in right direction (#351659).
|
||||
|
||||
2006-08-16 Tim-Philipp Müller <tim at centricular dot net>
|
||||
|
||||
Patch by: Sebastian Dröge <slomo at circular-chaos.org>
|
||||
|
|
|
@ -594,7 +594,7 @@ gst_wavpack_parse_sink_event (GstPad * pad, GstEvent * event)
|
|||
if (parse->adapter) {
|
||||
gst_adapter_clear (parse->adapter);
|
||||
}
|
||||
ret = gst_pad_push_event (pad, event);
|
||||
ret = gst_pad_push_event (parse->srcpad, event);
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_NEWSEGMENT:{
|
||||
|
@ -609,7 +609,7 @@ gst_wavpack_parse_sink_event (GstPad * pad, GstEvent * event)
|
|||
* be a complete Wavpack block and we can't do anything with them */
|
||||
gst_adapter_clear (parse->adapter);
|
||||
}
|
||||
ret = gst_pad_push_event (pad, event);
|
||||
ret = gst_pad_push_event (parse->srcpad, event);
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
|
@ -678,23 +678,15 @@ gst_wavpack_parse_init (GstWavpackParse * wavpackparse,
|
|||
static gint64
|
||||
gst_wavpack_parse_get_upstream_length (GstWavpackParse * wavpackparse)
|
||||
{
|
||||
GstPad *peer;
|
||||
gint64 length = -1;
|
||||
|
||||
peer = gst_pad_get_peer (wavpackparse->sinkpad);
|
||||
if (peer) {
|
||||
GstFormat format = GST_FORMAT_BYTES;
|
||||
|
||||
if (!gst_pad_query_duration (peer, &format, &length)) {
|
||||
if (!gst_pad_query_peer_duration (wavpackparse->sinkpad, &format, &length)) {
|
||||
length = -1;
|
||||
} else {
|
||||
GST_DEBUG ("upstream length: %" G_GINT64_FORMAT, length);
|
||||
}
|
||||
gst_object_unref (peer);
|
||||
} else {
|
||||
GST_DEBUG ("no peer!");
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
@ -865,6 +857,89 @@ gst_wavpack_parse_push_buffer (GstWavpackParse * wvparse, GstBuffer * buf,
|
|||
return gst_pad_push (wvparse->srcpad, buf);
|
||||
}
|
||||
|
||||
static guint8 *
|
||||
gst_wavpack_parse_find_marker (guint8 * buf, guint size)
|
||||
{
|
||||
int i;
|
||||
guint8 *ret = NULL;
|
||||
|
||||
if (G_UNLIKELY (size < 4))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < size - 4; i++) {
|
||||
if (memcmp (buf + i, "wvpk", 4) == 0) {
|
||||
ret = buf + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_wavpack_parse_resync_loop (GstWavpackParse * parse, WavpackHeader * header)
|
||||
{
|
||||
GstFlowReturn flow_ret = GST_FLOW_UNEXPECTED;
|
||||
GstBuffer *buf = NULL;
|
||||
|
||||
/* loop until we have a frame header or reach the end of the stream */
|
||||
while (1) {
|
||||
guint8 *data, *marker;
|
||||
guint len, size;
|
||||
|
||||
if (buf) {
|
||||
gst_buffer_unref (buf);
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (parse->upstream_length == 0 ||
|
||||
parse->upstream_length <= parse->current_offset) {
|
||||
parse->upstream_length = gst_wavpack_parse_get_upstream_length (parse);
|
||||
if (parse->upstream_length == 0 ||
|
||||
parse->upstream_length <= parse->current_offset) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
len = MIN (parse->upstream_length - parse->current_offset, 2048);
|
||||
|
||||
GST_LOG_OBJECT (parse, "offset: %" G_GINT64_FORMAT, parse->current_offset);
|
||||
|
||||
buf = gst_wavpack_parse_pull_buffer (parse, parse->current_offset,
|
||||
len, &flow_ret);
|
||||
|
||||
/* whatever the problem is, there's nothing more for us to do for now */
|
||||
if (buf == NULL)
|
||||
break;
|
||||
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
size = GST_BUFFER_SIZE (buf);
|
||||
|
||||
/* not enough data for a header? */
|
||||
if (size < sizeof (WavpackHeader))
|
||||
break;
|
||||
|
||||
/* got a header right where we are at now? */
|
||||
if (gst_wavpack_read_header (header, data))
|
||||
break;
|
||||
|
||||
/* nope, let's see if we can find one */
|
||||
marker = gst_wavpack_parse_find_marker (data + 1, size - 1);
|
||||
|
||||
if (marker) {
|
||||
parse->current_offset += marker - data;
|
||||
/* do one more loop iteration to make sure we pull enough
|
||||
* data for a full header, we'll bail out then */
|
||||
} else {
|
||||
parse->current_offset += len - 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf)
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
return flow_ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wavpack_parse_loop (GstElement * element)
|
||||
{
|
||||
|
@ -873,21 +948,14 @@ gst_wavpack_parse_loop (GstElement * element)
|
|||
WavpackHeader header = { {0,}, 0, };
|
||||
GstBuffer *buf = NULL;
|
||||
|
||||
GST_LOG_OBJECT (wavpackparse, "Current offset: %" G_GINT64_FORMAT,
|
||||
wavpackparse->current_offset);
|
||||
flow_ret = gst_wavpack_parse_resync_loop (wavpackparse, &header);
|
||||
|
||||
buf = gst_wavpack_parse_pull_buffer (wavpackparse,
|
||||
wavpackparse->current_offset, sizeof (WavpackHeader), &flow_ret);
|
||||
|
||||
if (buf == NULL && flow_ret == GST_FLOW_UNEXPECTED) {
|
||||
if (flow_ret == GST_FLOW_UNEXPECTED) {
|
||||
goto eos;
|
||||
} else if (buf == NULL) {
|
||||
} else if (flow_ret != GST_FLOW_OK) {
|
||||
goto pause;
|
||||
}
|
||||
|
||||
gst_wavpack_read_header (&header, GST_BUFFER_DATA (buf));
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
GST_LOG_OBJECT (wavpackparse, "Read header at offset %" G_GINT64_FORMAT
|
||||
": chunk size = %u+8", wavpackparse->current_offset, header.ckSize);
|
||||
|
||||
|
@ -938,9 +1006,8 @@ pause:
|
|||
static gboolean
|
||||
gst_wavpack_parse_resync_adapter (GstAdapter * adapter)
|
||||
{
|
||||
const guint8 *buf;
|
||||
const guint8 *buf, *marker;
|
||||
guint avail = gst_adapter_available (adapter);
|
||||
gchar *marker;
|
||||
|
||||
if (avail < 4)
|
||||
return FALSE;
|
||||
|
@ -955,11 +1022,15 @@ gst_wavpack_parse_resync_adapter (GstAdapter * adapter)
|
|||
|
||||
/* search for the marker in the complete content of the adapter */
|
||||
buf = gst_adapter_peek (adapter, avail);
|
||||
if (buf && (marker = g_strstr_len ((gchar *) buf, avail, "wvpk"))) {
|
||||
gst_adapter_flush (adapter, marker - (gchar *) buf);
|
||||
if (buf && (marker = gst_wavpack_parse_find_marker ((guint8 *) buf, avail))) {
|
||||
gst_adapter_flush (adapter, marker - buf);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* flush everything except the last 4 bytes. they could contain
|
||||
* the start of a new marker */
|
||||
gst_adapter_flush (adapter, avail - 4);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue