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 577346 - [xvimagesink] Playback failure with certain XVImage sizes
[xvimagesink] Playback failure with certain XVImage sizes
Status: RESOLVED NOTGNOME
Product: GStreamer
Classification: Platform
Component: gst-plugins-base
0.10.16
Other All
: Normal normal
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2009-03-30 19:32 UTC by Steve Magoun
Modified: 2009-04-27 18:07 UTC
See Also:
GNOME target: ---
GNOME version: 2.21/2.22


Attachments
Log with GST_DEBUG=xvimagesink:5 (161.73 KB, text/plain)
2009-03-30 19:38 UTC, Steve Magoun
  Details
Patch against xvimagesink.c blob 818ffd2b1ef62713f79f093b8d2746a1203c70a9 (4.73 KB, patch)
2009-03-30 20:09 UTC, Steve Magoun
none Details | Review
Log with GST_DEBUG=xvimagesink:5, using the patch to xvimagesink.c (161.73 KB, text/plain)
2009-03-30 20:11 UTC, Steve Magoun
  Details

Description Steve Magoun 2009-03-30 19:32:54 UTC
Please describe the problem:
For some content with dimensions that aren't a multiple of 2px/4px (e.g. 190x240), incorrect behavior in xvimagesink prevents the content from playing; the user is presented with the error "Failed to create output buffer of X x Y". The content plays properly if Xv output is disabled. It is not a hardware limitation - the same content plays properly with Xv using other media players like mplayer.

The problem seems to be that xvimagesink assumes that XvShmCreateImage will return a surface with dimensions that have been silently adjusted by the video driver. xvimagesink compares the size of the XvImage returned by XvShmCreateImage with an expected size it computes, and throws the error if the two size values differ.

This is an invalid assumption for drivers that don't adjust the size of the surface (Intel's 'Poulsbo' driver - xf86-video-psb is one such example). The Xv doc here http://www.x.org/docs/Xv/video says "[w]idth and height may be enlarged in some YUV formats", but there's no indication that such enlargement is a requirement.

Instead of assuming the video driver will adjust the image size, xvimagesink should perform the adjustment itself.

Steps to reproduce:
1. Download + unzip sample_mpeg4.mp4 from http://support.apple.com/kb/HT1425
2. gst-launch-0.10 ! filesrc location=~/sample_mpeg4.mp4 ! decodebin ! ffmpegcolorspace ! xvimagesink


Actual results:
Error message: "Xserver allocated buffer size did not match input buffer"; content does not play

Expected results:
Content plays in a new window

Does this happen every time?
Yes

Other information:
Might be the underlying problem in bug 552796

My OS is Ubuntu 8.04.2
Comment 1 Steve Magoun 2009-03-30 19:38:40 UTC
Created attachment 131720 [details]
Log with GST_DEBUG=xvimagesink:5

Note the 'unexpected XShm image size (got 68400, expected 69120)'.
Comment 2 Steve Magoun 2009-03-30 20:09:44 UTC
Created attachment 131724 [details] [review]
Patch against xvimagesink.c blob 818ffd2b1ef62713f79f093b8d2746a1203c70a9

I use a variant of this patch against gstreamer 0.10.18. I forward-ported the patch to the current head, though I haven't compiled/tested it there (sorry! Don't have an appropriate dev environment set up right now).

It's not especially clear from this version of the patch, but the intent is to move the "calculate the expected size.  This is only for sanity checking..." block before the call to XvShmCreateImage. I calculate a rounded_width/rounded_height value in that block, then pass the rounded values to XvShmCreateImage. Passing the rounded_width/rounded_height values to XvShmCreateImage fixes the problem in my testing.
Comment 3 Steve Magoun 2009-03-30 20:11:17 UTC
Created attachment 131726 [details]
Log with GST_DEBUG=xvimagesink:5, using the patch to xvimagesink.c
Comment 4 Steve Magoun 2009-04-24 22:07:21 UTC
Turns out that while it makes the sample_mpeg4.mp4 movie play correctly, my patch doesn't fix the case in which GST_ROUND_UP_4(xvimage->width) and GST_ROUND_UP_8(xvimage->width) return different values.

I'm probably misunderstanding something in gstreamer, but there seems to be a fundamental problem in this case:

Suppose we have a 426x240 image in I420 (a real example - I ran into this with Totem's visualizer plugin on a system w/ a 576px tall screen).

XvShmCreateImage takes width, height, and format as input. If the X driver always returns an image that's exactly the requested size, xvimage->data_size will be 426px * 240px * 1.5bytes/px = 153360bytes.

However, gstreamer expects a shared image with size = 154560 (gst_xvimagesink_show_frame gets handed a GstBuffer with size = 154560, and the 'sanity check' code in gst_xvimagesink_xvimage_new also expects an image w/ size 154560).

Therefore XvShmCreateImage needs to return an image where xvimage->data_size = 154560 in order to appease the sanity checks in gst_xvimagesink_xvimage_new,  gst_xvimagesink_show_frame, and gst-xvimagesink_buffer_alloc.

If XvShmCreateImage does exactly what's requested, though, it's not possible to create the proper surface:
154560 / 1.5 / 240 = 429.333....


The calculation for 154560 is as follows:
GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + GST_ROUND_UP_2 (height) * GST_ROUND_UP_8 (width) /2 = size

428 * 240 + 240 * 432 / 2 = 154560
Comment 5 David Schleef 2009-04-27 02:16:27 UTC
xvimagesink is pretty heavily tested over the years with lots of video cards, X servers, and OS's, for various odd video sizes.  I fixed a whole slew of drivers that were doing things wrong several years ago, but am unable to keep track of everything on a continuing basis.  There are *lots* of assumptions and knowledge about video cards that really isn't documented anywhere, especially not in the XVideo spec.

Unless someone has recently broken the xvimagesink code without me noticing, xvimagesink is likely correct, and the driver is broken.

A brief check shows me that 190x240 and 426x240 (as well as 425x240 and 427x240) work with the drivers I have immediately available.
Comment 6 Julien MOUTTE 2009-04-27 18:07:57 UTC
In GStreamer there's an assumption that says that I420 video frames have a specific stride.

Y, U and V planes strides (size of a line in bytes) have to be a multiple of 4 which gives :

Y stride = roundup_4 (width)
U stride = V stride = roundup_8 (width) / 2

The XV drivers are supposed to do that too. In your case it seems like the Poulsbo driver does not do that and that's why it breaks.

Fixing the check in xvimagesink is not going to fix the problem as GStreamer is going to generate frames with a different strides and the Poulsbo driver is going to choke on them.

The correct fix for this is to add the stride in the caps for every video buffer so that the video sink can check if strides match or convert if they don't (that's on the TODO list).

A fix to the poulsbo driver is probably the less intrusive thing to do. Fixing XVimagesink to convert strides is a possible hack as well adding a function that will memcpy the GStreamer frames to an XV image when width is not a multiple of 8.