After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 572863 - ffmpeg requires 128bit-aligned buffers.
ffmpeg requires 128bit-aligned buffers.
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-libav
git master
Other All
: Normal critical
: 0.10.7
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2009-02-23 15:41 UTC by Miguel Angel Cabrera Moya
Modified: 2009-03-12 21:07 UTC
See Also:
GNOME target: ---
GNOME version: 2.23/2.24


Attachments
FLV with nellymoser audio that segfaults (967.10 KB, video/x-flv)
2009-02-24 09:23 UTC, Miguel Angel Cabrera Moya
  Details
Use av_malloc() to allocate memory. (846 bytes, patch)
2009-03-06 08:18 UTC, Edward Hervey
committed Details | Review
Make sure we provide 128bit-aligned buffers to ffmpeg. (5.21 KB, patch)
2009-03-08 10:37 UTC, Edward Hervey
committed Details | Review

Description Miguel Angel Cabrera Moya 2009-02-23 15:41:41 UTC
Steps to reproduce:
1. decode audio from a flash webcam


Stack trace:
  • #0 __kernel_vsyscall
  • #0 __kernel_vsyscall
  • #1 raise
    from /lib/tls/i686/cmov/libc.so.6
  • #2 abort
    from /lib/tls/i686/cmov/libc.so.6
  • #3 os::abort
    from /usr/lib/jvm/java-6-sun-1.6.0.10/jre/lib/i386/server/libjvm.so
  • #4 VMError::report_and_die
    from /usr/lib/jvm/java-6-sun-1.6.0.10/jre/lib/i386/server/libjvm.so
  • #5 JVM_handle_linux_signal
    from /usr/lib/jvm/java-6-sun-1.6.0.10/jre/lib/i386/server/libjvm.so
  • #6 signalHandler
    from /usr/lib/jvm/java-6-sun-1.6.0.10/jre/lib/i386/server/libjvm.so
  • #7 <signal handler called>
  • #8 float_to_int16_sse2
    at libavcodec/i386/dsputil_mmx.c line 2289
  • #9 decode_tag
    at libavcodec/nellymoserdec.c line 182
  • #10 avcodec_decode_audio2
  • #11 gst_ffmpegdec_audio_frame
    at gstffmpegdec.c line 1790
  • #12 gst_ffmpegdec_frame
    at gstffmpegdec.c line 1907
  • #13 gst_ffmpegdec_chain
    at gstffmpegdec.c line 2306
  • #14 gst_pad_chain_unchecked
    at gstpad.c line 3890
  • #15 gst_pad_push
    at gstpad.c line 4057
  • #16 gst_base_src_loop
    at gstbasesrc.c line 2275
  • #17 gst_task_func
    at gsttask.c line 192
  • #18 ??
    from /usr/lib/libglib-2.0.so.0
  • #19 ??
    from /usr/lib/libglib-2.0.so.0
  • #20 start_thread
    from /lib/tls/i686/cmov/libpthread.so.0
  • #21 clone
    from /lib/tls/i686/cmov/libc.so.6

Other information:
The segfault appears in 4 or 5 seconds after the receiving begins
Comment 1 Wim Taymans 2009-02-23 15:53:40 UTC
Can you make a capture of the stream? something like with:

  gst-launch udpsrc ! gdppay ! filesink location=capture.gdp

Then attach the captured file to this bug.
Comment 2 Miguel Angel Cabrera Moya 2009-02-24 09:23:31 UTC
Created attachment 129395 [details]
FLV with nellymoser audio that segfaults
Comment 3 Edward Hervey 2009-02-25 07:51:18 UTC
Works fine with current gst-ffmpeg master. Miguel, can you try with a git version ?

If not, could you specify extactly which distro and gstreamer package versions you're using ?
Comment 4 Miguel Angel Cabrera Moya 2009-02-25 10:10:33 UTC
At the moment i am very busy and cannot compile gst-ffmpeg git.

I am using Ubuntu 8.10 with this GStreamer versions compiled by myself:
- GStreamer (gstreamer-0.10.22)
- GStreamer plugins base (gst-plugins-base-0.10.22)
- GStreamer plugins good (gst-plugins-good-0.10.12)
- GStreamer plugins bad (gst-plugins-bad-0.10.10)
- GStreamer plugins ugly (gst-plugins-ugly-0.10.10)
- GStreamer ffmpeg (gst-ffmpeg-0.10.6)
Comment 5 Miguel Angel Cabrera Moya 2009-03-05 19:06:29 UTC
I downloaded gst-ffmpeg from git today, compiled it, and here is the backtrace:

  • #0 __kernel_vsyscall
  • #0 __kernel_vsyscall
  • #1 raise
    from /lib/tls/i686/cmov/libc.so.6
  • #2 abort
    from /lib/tls/i686/cmov/libc.so.6
  • #3 os::abort
    from /usr/lib/jvm/java-6-sun-1.6.0.10/jre/lib/i386/server/libjvm.so
  • #4 VMError::report_and_die
    from /usr/lib/jvm/java-6-sun-1.6.0.10/jre/lib/i386/server/libjvm.so
  • #5 JVM_handle_linux_signal
    from /usr/lib/jvm/java-6-sun-1.6.0.10/jre/lib/i386/server/libjvm.so
  • #6 signalHandler
    from /usr/lib/jvm/java-6-sun-1.6.0.10/jre/lib/i386/server/libjvm.so
  • #7 <signal handler called>
  • #8 float_to_int16_sse2
    at libavcodec/x86/dsputil_mmx.c line 2348
  • #9 decode_tag
    at libavcodec/nellymoserdec.c line 181
  • #10 avcodec_decode_audio2
  • #11 gst_ffmpegdec_audio_frame
    at gstffmpegdec.c line 1800
  • #12 gst_ffmpegdec_frame
    at gstffmpegdec.c line 1925
  • #13 gst_ffmpegdec_chain
    at gstffmpegdec.c line 2324
  • #14 gst_pad_chain_unchecked
  • #15 gst_pad_push
    at gstpad.c line 4057
  • #16 gst_base_src_loop
    at gstbasesrc.c line 2275
  • #17 gst_task_func
    at gsttask.c line 192
  • #18 ??
    from /usr/lib/libglib-2.0.so.0
  • #19 ??
    from /usr/lib/libglib-2.0.so.0
  • #20 start_thread
    from /lib/tls/i686/cmov/libpthread.so.0
  • #21 clone
    from /lib/tls/i686/cmov/libc.so.6

Comment 6 Michael Smith 2009-03-05 19:10:40 UTC
Reproducible (using gst-launch, rather than some weirdo java thingy). 32 bit linux here.


Program received signal SIGSEGV, Segmentation fault.

Thread 3039124368 (LWP 942)

  • #0 float_to_int16_sse2
    at libavcodec/x86/dsputil_mmx.c line 2348
  • #1 decode_tag
    at libavcodec/nellymoserdec.c line 181
  • #2 avcodec_decode_audio2
    at libavcodec/utils.c line 560
  • #3 gst_ffmpegdec_audio_frame
    at gstffmpegdec.c line 1800
  • #4 gst_ffmpegdec_frame
    at gstffmpegdec.c line 1918
  • #5 gst_ffmpegdec_chain
    at gstffmpegdec.c line 2317
  • #6 gst_pad_chain_unchecked
    at gstpad.c line 3942
  • #7 gst_pad_push
    at gstpad.c line 4109
  • #8 gst_queue_loop
    at gstqueue.c line 1042
  • #9 gst_task_func
    at gsttask.c line 192
  • #10 g_thread_pool_thread_proxy
    at /build/buildd/glib2.0-2.18.2/glib/gthreadpool.c line 265
  • #11 g_thread_create_proxy
    at /build/buildd/glib2.0-2.18.2/glib/gthread.c line 635
  • #12 start_thread
    from /lib/tls/i686/cmov/libpthread.so.0
  • #13 clone
    from /lib/tls/i686/cmov/libc.so.6

Comment 7 Michael Smith 2009-03-05 19:39:27 UTC
The buffer allocated by gstreamer (for ffmpeg to decode into) is 8-byte aligned.

ffmpeg (using sse2 code) requires a 16-byte aligned buffer in this case.

It's misaligned, so you get a crash.

gstffmpeg could use a temporary, 16-byte-aligned, buffer, then copy into the actual destination GstBuffer (this requirement is documented in avcodec.h, sort of, in hand-wavey language).
Comment 8 Edward Hervey 2009-03-06 07:59:59 UTC
This would be the info from avcodec.h for avcodec_decode_audio2

 * @note You might have to align the input buffer \p buf and output buffer \p
 * samples. The alignment requirements depend on the CPU: On some CPUs it isn't
 * necessary at all, on others it won't work at all if not aligned and on others
 * it will work but it will have an impact on performance. In practice, the
 * bitstream should have 4 byte alignment at minimum and all sample data should
 * be 16 byte aligned unless the CPU doesn't need it (AltiVec and SSE do). If
 * the linesize is not a multiple of 16 then there's no sense in aligning the
 * start of the buffer to 16.
 *

Will cook up a patch for the pre-release.
Comment 9 Edward Hervey 2009-03-06 08:18:59 UTC
Created attachment 130186 [details] [review]
Use av_malloc() to allocate memory.

av_malloc() takes care or memory alignment... so let's just use it !

Will try it on a 32bit machine later on if nobody has commented on this before.
Comment 10 Tim-Philipp Müller 2009-03-06 14:43:20 UTC
Comment on attachment 130186 [details] [review]
Use av_malloc() to allocate memory.

>-  /* outgoing buffer */
>-  *outbuf = gst_buffer_new_and_alloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);

Oh wow, I would have assumed g_malloc() provides a reasonably aligned return value. Maybe we should fix gst_buffer_new_and_alloc() to do this automatically? Or provide new functions for that? (Both doesn't help us now of course)

>+  /* outgoing buffer. We use av_malloc() to have properly aligned memory. */
>+  *outbuf = gst_buffer_new ();
>+  GST_BUFFER_DATA (*outbuf) = GST_BUFFER_MALLOCDATA (*outbuf) = av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
>+  GST_BUFFER_SIZE (*outbuf) = AVCODEC_MAX_AUDIO_FRAME_SIZE;

Don't we also need an GST_BUFFER_FREE_FUNC (*outbuf) = av_free; ?

What about the input buffer? Not sure how to read the docs, but it seems like the input buffer needs to be at least 4-byte aligned?
Comment 11 Edward Hervey 2009-03-06 15:04:12 UTC
(In reply to comment #10)
> (From update of attachment 130186 [details] [review] [edit])
> >-  /* outgoing buffer */
> >-  *outbuf = gst_buffer_new_and_alloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);
> 
> Oh wow, I would have assumed g_malloc() provides a reasonably aligned return
> value.

  Nope, it only provides (arch-size) bytes alignment (i.e. on 32bit : 4 bytes, and on 64bits: 8 bytes). The ffmpeg implementation does 128bit (16bytes) alignment (by using memalign/posix_memalign).

> Maybe we should fix gst_buffer_new_and_alloc() to do this automatically?
> Or provide new functions for that? (Both doesn't help us now of course)

  Was thinking about that indeed. Considering that any sse/sse2 code (and maybe other technologies) require aligned memory... it would make much more sense.
  New functions would make more sense.

> 
> >+  /* outgoing buffer. We use av_malloc() to have properly aligned memory. */
> >+  *outbuf = gst_buffer_new ();
> >+  GST_BUFFER_DATA (*outbuf) = GST_BUFFER_MALLOCDATA (*outbuf) = av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
> >+  GST_BUFFER_SIZE (*outbuf) = AVCODEC_MAX_AUDIO_FRAME_SIZE;
> 
> Don't we also need an GST_BUFFER_FREE_FUNC (*outbuf) = av_free; ?

  We could for safety, although it will not be doing anything fancy (apart from calling free) if we have CONFIG_MEMALIGN_HACK deactivated (which is the case in our supported builds).

> 
> What about the input buffer? Not sure how to read the docs, but it seems like
> the input buffer needs to be at least 4-byte aligned?
> 
  Indeed. I guess we could check if the input buffer is 32bit aligned, and if not, create a temporary buffer with av_malloc(), pass that to the decoding function, and then free it.

  Will create an updated patch for this and test it.
Comment 12 Edward Hervey 2009-03-06 16:41:47 UTC
commit 98167578c45b91b5b73f4e1165fb68d03b10ed92
Author: Edward Hervey <bilboed@bilboed.com>
Date:   Fri Mar 6 17:37:51 2009 +0100

    ffmpegdec: Make sure we provide 16 byte aligned data to ffmpeg. Fixes #572863
    
    We simply allocate the memory using ffmpeg's av_malloc which provides us
    with properly memalign'ed data.
    This avoids write-outside-of-bounds when sse/altivec code is being used.

diff --git a/ext/ffmpeg/gstffmpegdec.c b/ext/ffmpeg/gstffmpegdec.c
index aeec910..019140c 100644
--- a/ext/ffmpeg/gstffmpegdec.c
+++ b/ext/ffmpeg/gstffmpegdec.c
@@ -1794,8 +1794,12 @@ gst_ffmpegdec_audio_frame (GstFFMpegDec * ffmpegdec,
       GST_TIME_ARGS (in_timestamp), GST_TIME_ARGS (in_duration),
       GST_TIME_ARGS (ffmpegdec->next_ts));
 
-  /* outgoing buffer */
-  *outbuf = gst_buffer_new_and_alloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);
+  /* outgoing buffer. We use av_malloc() to have properly aligned memory. */
+  *outbuf = gst_buffer_new ();
+  GST_BUFFER_DATA (*outbuf) = GST_BUFFER_MALLOCDATA (*outbuf) =
+      av_malloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);
+  GST_BUFFER_SIZE (*outbuf) = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+  GST_BUFFER_FREE_FUNC (*outbuf) = av_free;
 
   len = avcodec_decode_audio2 (ffmpegdec->context,
       (int16_t *) GST_BUFFER_DATA (*outbuf), &have_data, data, size);
Comment 13 Sjoerd Simons 2009-03-07 18:06:52 UTC
Unfortunately that only fixes the audio case. I can reproduce the same issue on my 32 powerpc with just using ffdec_mpeg4. A quick hack to alloc_output_buffer reallocate its own buffer with av_malloc when gst_pad_alloc_buffer_and_set_caps returns a buffer not aligned to 16 bytes fixes the issue... But that doesn't seem like the proper way of fixing it
Comment 14 Edward Hervey 2009-03-08 10:02:14 UTC
Alas... doing what you suggest is indeed the proper fix.

If the downstream element properly allocates 128bit-aligned then you won't see a difference.

Changing title of the bug according, will cook up a patch.
Comment 15 Edward Hervey 2009-03-08 10:37:58 UTC
Created attachment 130269 [details] [review]
Make sure we provide 128bit-aligned buffers to ffmpeg.

    Make sure we provide ffmpeg with 128bit-aligned data.
    
    Add a new function new_aligned_buffer() which creates a GstBuffer of
    the requested size/caps, with the memory being allocated/freed by ffmpeg's
    av_malloc/av_free which guarantees properly aligned memory.
    Added a can_allocate_aligned internal property which we use to figure out
    whether downstream can provide us with 128bit aligned buffers.
Comment 16 Sjoerd Simons 2009-03-08 11:00:59 UTC
(In reply to comment #15)
> Created an attachment (id=130269) [edit]
> Make sure we provide 128bit-aligned buffers to ffmpeg.

That fixes the issue on my ppc indeed, thanks
Comment 17 Stefan Sauer (gstreamer, gtkdoc dev) 2009-03-08 21:17:41 UTC
I have actually a fixme for memalign() in my local code for quite some time, but wonder how portable this is. On macOS its probably fine. Anyone know the story on windows.
128bit aligned would help e.g. with DSP based environments too. Too bad that there is no guarrantee for that because of subbuffers :/
Comment 18 Edward Hervey 2009-03-12 21:07:44 UTC
Forgot to close bug again after committing patch.