mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-31 19:42:26 +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
8938587f17
commit
611b2dd11b
1 changed files with 99 additions and 28 deletions
|
@ -594,7 +594,7 @@ gst_wavpack_parse_sink_event (GstPad * pad, GstEvent * event)
|
||||||
if (parse->adapter) {
|
if (parse->adapter) {
|
||||||
gst_adapter_clear (parse->adapter);
|
gst_adapter_clear (parse->adapter);
|
||||||
}
|
}
|
||||||
ret = gst_pad_push_event (pad, event);
|
ret = gst_pad_push_event (parse->srcpad, event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GST_EVENT_NEWSEGMENT:{
|
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 */
|
* be a complete Wavpack block and we can't do anything with them */
|
||||||
gst_adapter_clear (parse->adapter);
|
gst_adapter_clear (parse->adapter);
|
||||||
}
|
}
|
||||||
ret = gst_pad_push_event (pad, event);
|
ret = gst_pad_push_event (parse->srcpad, event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:{
|
default:{
|
||||||
|
@ -678,23 +678,15 @@ gst_wavpack_parse_init (GstWavpackParse * wavpackparse,
|
||||||
static gint64
|
static gint64
|
||||||
gst_wavpack_parse_get_upstream_length (GstWavpackParse * wavpackparse)
|
gst_wavpack_parse_get_upstream_length (GstWavpackParse * wavpackparse)
|
||||||
{
|
{
|
||||||
GstPad *peer;
|
|
||||||
gint64 length = -1;
|
gint64 length = -1;
|
||||||
|
|
||||||
peer = gst_pad_get_peer (wavpackparse->sinkpad);
|
GstFormat format = GST_FORMAT_BYTES;
|
||||||
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;
|
length = -1;
|
||||||
} else {
|
|
||||||
GST_DEBUG ("upstream length: %" G_GINT64_FORMAT, length);
|
|
||||||
}
|
|
||||||
gst_object_unref (peer);
|
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG ("no peer!");
|
GST_DEBUG ("upstream length: %" G_GINT64_FORMAT, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,6 +857,89 @@ gst_wavpack_parse_push_buffer (GstWavpackParse * wvparse, GstBuffer * buf,
|
||||||
return gst_pad_push (wvparse->srcpad, 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
|
static void
|
||||||
gst_wavpack_parse_loop (GstElement * element)
|
gst_wavpack_parse_loop (GstElement * element)
|
||||||
{
|
{
|
||||||
|
@ -873,21 +948,14 @@ gst_wavpack_parse_loop (GstElement * element)
|
||||||
WavpackHeader header = { {0,}, 0, };
|
WavpackHeader header = { {0,}, 0, };
|
||||||
GstBuffer *buf = NULL;
|
GstBuffer *buf = NULL;
|
||||||
|
|
||||||
GST_LOG_OBJECT (wavpackparse, "Current offset: %" G_GINT64_FORMAT,
|
flow_ret = gst_wavpack_parse_resync_loop (wavpackparse, &header);
|
||||||
wavpackparse->current_offset);
|
|
||||||
|
|
||||||
buf = gst_wavpack_parse_pull_buffer (wavpackparse,
|
if (flow_ret == GST_FLOW_UNEXPECTED) {
|
||||||
wavpackparse->current_offset, sizeof (WavpackHeader), &flow_ret);
|
|
||||||
|
|
||||||
if (buf == NULL && flow_ret == GST_FLOW_UNEXPECTED) {
|
|
||||||
goto eos;
|
goto eos;
|
||||||
} else if (buf == NULL) {
|
} else if (flow_ret != GST_FLOW_OK) {
|
||||||
goto pause;
|
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
|
GST_LOG_OBJECT (wavpackparse, "Read header at offset %" G_GINT64_FORMAT
|
||||||
": chunk size = %u+8", wavpackparse->current_offset, header.ckSize);
|
": chunk size = %u+8", wavpackparse->current_offset, header.ckSize);
|
||||||
|
|
||||||
|
@ -938,9 +1006,8 @@ pause:
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_wavpack_parse_resync_adapter (GstAdapter * adapter)
|
gst_wavpack_parse_resync_adapter (GstAdapter * adapter)
|
||||||
{
|
{
|
||||||
const guint8 *buf;
|
const guint8 *buf, *marker;
|
||||||
guint avail = gst_adapter_available (adapter);
|
guint avail = gst_adapter_available (adapter);
|
||||||
gchar *marker;
|
|
||||||
|
|
||||||
if (avail < 4)
|
if (avail < 4)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -955,11 +1022,15 @@ gst_wavpack_parse_resync_adapter (GstAdapter * adapter)
|
||||||
|
|
||||||
/* search for the marker in the complete content of the adapter */
|
/* search for the marker in the complete content of the adapter */
|
||||||
buf = gst_adapter_peek (adapter, avail);
|
buf = gst_adapter_peek (adapter, avail);
|
||||||
if (buf && (marker = g_strstr_len ((gchar *) buf, avail, "wvpk"))) {
|
if (buf && (marker = gst_wavpack_parse_find_marker ((guint8 *) buf, avail))) {
|
||||||
gst_adapter_flush (adapter, marker - (gchar *) buf);
|
gst_adapter_flush (adapter, marker - buf);
|
||||||
return TRUE;
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue