I also ran into this, and dug a little in the core file. This is the stack trace we see:
#0 0x00007f01ec5dc83b in dca_syncinfo () from /usr/lib/libdca.so.0
#1 0x00007f01ec80ab7b in gst_dtsdec_parse (bdec=0x7f01e804e320,
adapter=<optimized out>, _offset=0x7f01ed20d9fc, len=0x7f01ed20d9f8)
at gstdtsdec.c:297
#2 0x00007f01effdc0ec in gst_audio_decoder_push_buffers (dec=0x7f01e804e320,
force=0) at gstaudiodecoder.c:988
#3 0x00007f01effdc5a0 in gst_audio_decoder_chain_forward (dec=0x7f01e804e320,
buffer=0x0) at gstaudiodecoder.c:1141
#4 0x00007f01effdd35b in gst_audio_decoder_chain (pad=<optimized out>,
buffer=0x1e869f0) at gstaudiodecoder.c:1389
#5 0x00007f01ec809c97 in gst_dtsdec_chain (pad=0x7f01e803c1c0, buf=0x1e7cee0)
at gstdtsdec.c:715
#6 0x00007f01f673222a in gst_pad_chain_data_unchecked (cache=0x7f01ed20dc20,
data=0x1e7cee0, is_buffer=1, pad=0x7f01e803c1c0) at gstpad.c:4271
#7 gst_pad_push_data (pad=<optimized out>, is_buffer=1, data=0x1e7cee0,
cache=<optimized out>) at gstpad.c:4506
#8 0x00007f01f6735ae6 in gst_pad_push (pad=0x7f01e803c040, buffer=0x1e7cee0)
at gstpad.c:4730
#9 0x00007f01f31f6536 in gst_single_queue_push_one (object=0x1e7cee0,
sq=0x7f01e803eaf0, mq=0x7f01e803f050) at gstmultiqueue.c:1087
#10 gst_multi_queue_loop (pad=<optimized out>) at gstmultiqueue.c:1318
#11 0x00007f01f675bdcc in gst_task_func (task=0x1ed5610) at gsttask.c:327
#12 0x00007f01f5ff2248 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#13 0x00007f01f5ff19e5 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#14 0x00007f01f5d6fe9a in start_thread ()
from /lib/x86_64-linux-gnu/libpthread.so.0
#15 0x00007f01f5a9a4bd in clone () from /lib/x86_64-linux-gnu/libc.so.6
#16 0x0000000000000000 in ?? ()
Where $rsi is not mapped. dca_syncinfo gets $rsi from gst_dtsdec_parse(). Looking at gst_dtsdec_parse(), $rsi comes from $r12, which when we map it (manually :() to the source code, corresponds to the variable data in gst_dtsdec_parse():
if (length == 0) {
/* shift window to re-find sync */
data++;
size--;
} else if (length <= size) {
GST_LOG_OBJECT (dts, "Sync: frame size %d", length);
result = GST_FLOW_OK;
break;
} else {
GST_LOG_OBJECT (dts, "Not enough data available (needed %d had %d)",
length, size);
break;
}
}
....
Note that the loop condition does not depend on either size nor data. We only exit the loop if length is non-0. length comes from dca_syncinfo(), which looks for a certain bit pattern at the start of *data, and if it doesn't find it, it returns 0.
So if we are given bad data, that doesn't have the given bit segment dca_syncinfo() looks for, length will always be 0, we will keep looping, incrementing data and decrementing size until we fall outside of the buffer, which I think is whats happening.
This by the way is fixed upstream in gstreamer by the following commit:
I also ran into this, and dug a little in the core file. This is the stack trace we see:
#0 0x00007f01ec5dc83b in dca_syncinfo () from /usr/lib/ libdca. so.0 4e320, <optimized out>, _offset= 0x7f01ed20d9fc, len=0x7f01ed20d9f8) decoder_ push_buffers (dec=0x7f01e804 e320, .c:988 decoder_ chain_forward (dec=0x7f01e804 e320, .c:1141 decoder_ chain (pad=<optimized out>, 0x1e869f0) at gstaudiodecoder .c:1389 c1c0, buf=0x1e7cee0) chain_data_ unchecked (cache= 0x7f01ed20dc20, <optimized out>) at gstpad.c:4506 c040, buffer=0x1e7cee0) queue_push_ one (object=0x1e7cee0, 0x7f01e803eaf0, mq=0x7f01e803f050) at gstmultiqueue. c:1087 queue_loop (pad=<optimized out>) at gstmultiqueue. c:1318 64-linux- gnu/libglib- 2.0.so. 0 64-linux- gnu/libglib- 2.0.so. 0 64-linux- gnu/libpthread. so.0 64-linux- gnu/libc. so.6
#1 0x00007f01ec80ab7b in gst_dtsdec_parse (bdec=0x7f01e80
adapter=
at gstdtsdec.c:297
#2 0x00007f01effdc0ec in gst_audio_
force=0) at gstaudiodecoder
#3 0x00007f01effdc5a0 in gst_audio_
buffer=0x0) at gstaudiodecoder
#4 0x00007f01effdd35b in gst_audio_
buffer=
#5 0x00007f01ec809c97 in gst_dtsdec_chain (pad=0x7f01e803
at gstdtsdec.c:715
#6 0x00007f01f673222a in gst_pad_
data=0x1e7cee0, is_buffer=1, pad=0x7f01e803c1c0) at gstpad.c:4271
#7 gst_pad_push_data (pad=<optimized out>, is_buffer=1, data=0x1e7cee0,
cache=
#8 0x00007f01f6735ae6 in gst_pad_push (pad=0x7f01e803
at gstpad.c:4730
#9 0x00007f01f31f6536 in gst_single_
sq=
#10 gst_multi_
#11 0x00007f01f675bdcc in gst_task_func (task=0x1ed5610) at gsttask.c:327
#12 0x00007f01f5ff2248 in ?? () from /lib/x86_
#13 0x00007f01f5ff19e5 in ?? () from /lib/x86_
#14 0x00007f01f5d6fe9a in start_thread ()
from /lib/x86_
#15 0x00007f01f5a9a4bd in clone () from /lib/x86_
#16 0x0000000000000000 in ?? ()
The faulting instruction is:
0x00007f01ec 5dc820 <+0>: mov %rbx,-0x20(%rsp) 5dc825 <+5>: mov %rbp,-0x18(%rsp) 5dc82a <+10>: mov %rdi,%rbx 5dc82d <+13>: mov %r12,-0x10(%rsp) 5dc832 <+18>: mov %r13,-0x8(%rsp) 5dc837 <+23>: sub $0x38,%rsp 5dc83b <+27>: movzbl (%rsi),%eax <<<---- This one
0x00007f01ec
0x00007f01ec
0x00007f01ec
0x00007f01ec
0x00007f01ec
0x00007f01ec
Where $rsi is not mapped. dca_syncinfo gets $rsi from gst_dtsdec_parse(). Looking at gst_dtsdec_parse(), $rsi comes from $r12, which when we map it (manually :() to the source code, corresponds to the variable data in gst_dtsdec_parse():
static GstFlowReturn available (adapter);
&sample_ rate, &bit_rate, &frame_length);
gst_dtsdec_parse (GstAudioDecoder * bdec, GstAdapter * adapter,
gint * _offset, gint * len)
{
...
guint8 *data;
...
size = av = gst_adapter_
data = (guint8 *) gst_adapter_peek (adapter, av);
...
while (av >= 7) {
length = dca_syncinfo (dts->state, data, &flags,
if (length == 0) { LOG_OBJECT (dts, "Sync: frame size %d", length); LOG_OBJECT (dts, "Not enough data available (needed %d had %d)",
/* shift window to re-find sync */
data++;
size--;
} else if (length <= size) {
GST_
result = GST_FLOW_OK;
break;
} else {
GST_
length, size);
break;
}
}
....
Note that the loop condition does not depend on either size nor data. We only exit the loop if length is non-0. length comes from dca_syncinfo(), which looks for a certain bit pattern at the start of *data, and if it doesn't find it, it returns 0.
So if we are given bad data, that doesn't have the given bit segment dca_syncinfo() looks for, length will always be 0, we will keep looping, incrementing data and decrementing size until we fall outside of the buffer, which I think is whats happening.
This by the way is fixed upstream in gstreamer by the following commit:
http:// cgit.freedeskto p.org/gstreamer /gst-plugins- bad/commit/ ext/dts/ gstdtsdec. c?id=860ccd414d bb313fabf065b92 838f0f39037584b