GNOME Bugzilla – Bug 736965
matroskademux: Output raw video in unaligned buffers causing crashing in ORC video conversion code
Last modified: 2015-08-31 11:41:49 UTC
Given the following pair of pipelines: gst-launch-1.0 videotestsrc ! video/x-raw,framerate=25/1,width=1280,height=720,format=AYUV ! matroskamux ! shmsink socket-path=/tmp/foo gst-launch-1.0 shmsrc socket-path=/tmp/foo ! matroskademux ! videoconvert ! video/x-raw,format=YUY2 ! fakesink The latter causes a segfault in the orc-generated code in videoconvert:
+ Trace 234110
Thread 3 (Thread 0x7f13201fb700 (LWP 11294))
Removing either the shm transport, the muxing, or the orc-accelerated converting (ORC_CODE=backup) makes the segfault disappear. Could this be a problem with orc working on unaligned buffers in the shm segment due to the tiny metadata buffers matroskamux injects?
In 1.2 it cleanly fail with this error: ERROR: from element /GstPipeline:pipeline0/GstShmSink:shmsink0: Shared memory area is too small Additional debug info: Shared memory area of size 262144 is smaller thanbuffer of size 368640 And fixing the size makes GstVideoFrame fails t map buffer, invalid size. Deep down, I think matroska might not be setting raw buffers information correctly, or is missing some required VideoMeta maybe.
Seems to be a problem with matroskademux not creating aligned video buffers if it is pushed a whole frame in a single buffer. Tested using the following setup: Create a test file: gst-launch-1.0 videotestsrc num-buffers=100 ! video/x-raw,format=I420 ! matroskamux ! filesink location=foo.mkv With a small blocksize matroskademux creates perfectly sized and aligned buffers and everything is fine: GST_DEBUG="GST_MEMORY:LOG" gst-launch-1.0 pushfilesrc real-filesrc::blocksize=4096 real-filesrc::location=foo.mkv ! matroskademux ! videoconvert ! video/x-raw,format=UYVY ! fakesink gstmemory.c:137:gst_memory_init: new memory 0x13ff640, maxsize:115208 offset:0 size:115208 With a blocksize large enough to capture an entire frame, matroskademux creates buffers using unaligned child memory and videoconvert crashes: GST_DEBUG="GST_MEMORY:LOG" gst-launch-1.0 pushfilesrc real-filesrc::blocksize=256000 real-filesrc::location=foo.mkv ! matroskademux ! videoconvert ! video/x-raw,format=UYVY ! fakesink gstmemory.c:137:gst_memory_init: new memory 0x7fd5ac0061c0, maxsize:256007 offset:437 size:115200
If the video frame size is small enough, even the default blocksize causes problems: gst-launch-1.0 videotestsrc num-buffers=100 ! video/x-raw,format=I420,width=32,height=24 ! matroskamux ! filesink location=foo.mkv GST_DEBUG="GST_MEMORY:LOG" gst-launch-1.0 filesrc location=foo.mkv ! matroskademux ! videoconvert ! video/x-raw,format=UYVY ! fakesink
So I guess the thing to do here would be to teach the video converters to copy into an aligned buffer if necessary?
Any comment? I know there has already been a lot of change to the video converting code in the 1.5 cycle.
The pipeline from comment 2 and 3 don't crash here anymore, but this latter one does: gst-launch-1.0 videotestsrc num-buffers=100 ! video/x-raw,format=AYUV,width=32,height=24 ! matroskamux ! filesink location=foo.mkv GST_DEBUG="GST_MEMORY:LOG" gst-launch-1.0 filesrc location=foo.mkv ! matroskademux ! videoconvert ! video/x-raw,format=YUY2 ! fakesink
Since 1.5.90 I'm seeing this with pipes and big frames, too. gst-launch-1.0 -q videotestsrc ! video/x-raw,format=I420,width=1920,height=1080 ! matroskamux streamable=1 ! fdsink fd=1 | gst-launch-1.0 fdsrc fd=0 ! matroskademux ! videoscale ! video/x-raw,width=960,height=540 ! fakesink
It seems I've found a workaround: diff --git i/gst/matroska/matroska-demux.c w/gst/matroska/matroska-demux.c index 1d84abc..01a65ff 100644 --- i/gst/matroska/matroska-demux.c +++ w/gst/matroska/matroska-demux.c @@ -5012,6 +5012,7 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext * videocontext->pixel_height); caps = gst_video_info_to_caps (&info); *codec_name = gst_pb_utils_get_codec_description (caps); + context->alignment = 32; } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP)) { caps = gst_caps_new_simple ("video/x-divx", "divxversion", G_TYPE_INT, 4, NULL);
So the problem here looks like matroskademux never made the alignment correct before, and older videoconvert was just more forgiving :)
Jan, can you confirm that the problem is that matroskademux (in 1.4 and 1.5) outputs improperly aligned buffers and that the only problem is that in 1.5 the video converter code is a bit more picky about that?
I think it's definitely matroskademux which now outputs more unaligned buffers. Even with context->alignment = 8 it doesn't crash, and I see: matroska-demux.c:3143:gst_matroska_demux_align_buffer:<matroskademux0> We want output aligned on 8, reallocated
I think it's reasonable to enforce 32 byte alignment for the raw video formats in matroskademux. Should check if the same is also needed in qtdemux and avidemux, they also support raw video. Jan, can you attach a proper patch for matroskademux and shortly check those other demuxers? Thanks!
Created attachment 310344 [details] [review] [PATCH] matroskademux: Align raw video frames to 32 bytes Patch for the change above. qtdemux and avidemux just take the buffers from a GstAdapter (in push mode) or pull a range (in pull mode) without checking aligment.
Ok, so avidemux and qtdemux are equally broken then just that nobody noticed yet. Want to provide patches? :)
So far I've been unable to get them to crash.
We should do the other ones after 1.6 then, they're not regressions either as far as we know, are they?