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 112621 - lots of plugins get RGB caps wrong
lots of plugins get RGB caps wrong
Status: RESOLVED DUPLICATE of bug 116387
Product: GStreamer
Classification: Platform
Component: gst-plugins
git master
Other Linux
: Normal normal
: 0.6.x
Assigned To: David Schleef
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2003-05-09 08:19 UTC by David Schleef
Modified: 2004-12-22 21:47 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
proposed patch (26.27 KB, patch)
2003-05-09 08:20 UTC, David Schleef
none Details | Review

Description David Schleef 2003-05-09 08:19:26 UTC
I've noticed recently that plugins' handling of caps for RGB video
is pretty inconsistent.  I did a bunch of mucking in places that
looked like it needed work, but I'd like to see some discussion
before checking in.  It will probably break stuff.

Basically, I've changed everything so that:

  - 24 and 32 bit RGB is always big endian, with color masks
    appropriately defined (i.e., in big endian order)

  - 15 and 16 bit RGB is always host endian, except for cases
    where the video is truly byte swapped.

  - (almost) every caps definition contains all fields.
Comment 1 David Schleef 2003-05-09 08:20:14 UTC
Created attachment 16386 [details] [review]
proposed patch
Comment 2 Ronald Bultje 2003-05-09 10:14:59 UTC
I don't really see why we would want to use BIG_ENDIAN instead of
host-native endian order. I mean, basically, nothing changes in
handling anything, and we're just confusing ourselves, right? The only
advantage of your approach is that it makes it easier to understand
how the stuff is aligned in bytes, but normally, people shouldn't have
to care about that in the first place...

I'm really not trying to be a PITA, but I do prefer to use host-native
endian-order in the caps... Is there any specific case where your
approach makes an obvious difference to the current one and where it's
actually an obvious improvement?

Also, note that with your approach, casting a 32-bit RGB buffer to
guint32 and then applying the mask no longer works on little-endian
machines, for obvious reasons. This is a clear disadvantage, in my
opinion...
Comment 3 Benjamin Otte (Company) 2003-05-09 15:44:49 UTC
Could someone fill me in on how this works?

If I have a 1 pixel video buffer and I do "pixel = *((guint32) data)"
I assume I can do "redpart = pixel & gst_caps_get_int(caps,
"red_mask")" at any time with any RGB video on any machine.

Is this true or not before/after the patch?

Comment 4 David Schleef 2003-05-09 19:41:29 UTC
You can still cast a 32-bit RGB pixel to a guint32 and pull out the
color component using the color masks -- but you need to convert the
color masks to the host's byte order first.

Right now, a lot of things are using endianness==G_BYTE_ORDER, which
means that for a given subpixel arrangement in memory, the masks are
different depending on the endianness.  I think that a particular
memory arrangement should have exactly one authoritative caps, and
using G_BYTE_ORDER doesn't allow this.  Currently, few plugins get the
color masks correct for G_BYTE_ORDER on big endian machines.  Thus,
one of the primary benefits of using G_BIG_ENDIAN is that caps can be
defined without #ifdefs.

(The main advantage of using G_BIG_ENDIAN over G_LITTLE_ENDIAN is that
the masks read in memory order.)

Example code:

  endianness = gst_caps_get_int(caps,"endianness");
  red_mask = gst_caps_get_int(caps,"red_mask");
  if(endianness!=G_BYTE_ORDER)red_mask=GUINT32_SWAP_BE_LE(red_mask);
  
  pixel = *(guint32 *)data;
  red_part = pixel&red_mask;

for bpp=16, you'd use

  pixel = *(guint16 *)data;
  red_part = pixel&red_mask;

This works for any combination of host endianness and data endianness.
 I don't think that anything less addresses the problem correctly.

However, I don't think that anyone will actually use caps in this way.
 The primary use of RGB caps appears to be converting to/from a
library's #define'd format.  This mostly just means knowing how to
specify the library's format as gst caps.
Comment 5 Ronald Bultje 2003-05-09 21:48:03 UTC
Benjamin, before the patch, it works that way. Don't forget you have
to bitshift to actually get the red value, so:

guint32 red = *(guint32 *) data & redmask;
int num_shifts = 0;
while (redmask && !(redmask & 1))
  redmask >>= 1;
red >>= num_shifts;

would give you the actual bytevalue of red.

Dave, you're saying a lot of plugins currently have to use #ifdefs to
convert masks depending on byte order. That sounds weird, it'd mean
that the libs we depend on don't actually make proper use of RGB data
depending on endianness, which seems more like an issue with them than
with us, unless this is for a specific purpose. I don't see this
happening a lot, actually.
Comment 6 David Schleef 2003-05-09 22:36:31 UTC
24-bit and 32-bit RGB formats are typically byte-oriented, not
word-oriented.  There is no inherint endianness in the data as there
is with 16-bit or 15-bit, there is merely arrangement.

The reason there aren't many #ifdefs currently is because nothing
really works on big-endian machines.
Comment 7 David Schleef 2003-05-09 22:51:59 UTC
> Benjamin, before the patch, it works that way.

Only on little endian machines.

Here's a concrete example of the problem.  Swfdec creates 24 bit RGB
images where the ((guint8 *)data)[0] is red, [1] is green, [2] is
blue, [3] is red, etc., independent of host endianness.  To describe
this using G_BYTE_ORDER, we need:

#ifdef G_BYTE_ORDER == G_BIG_ENDIAN
  c = GST_CAPS_NEW (
    "swfdec_videosrc",
    "video/raw",
      "format",         GST_PROPS_FOURCC (GST_MAKE_FOURCC
('R','G','B',' ')),
      "bpp",            GST_PROPS_INT (24),
      "depth",          GST_PROPS_INT (24),
      "endianness",     GST_PROPS_INT (G_BYTE_ORDER),
      "red_mask",       GST_PROPS_INT (0xff0000),
      "green_mask",     GST_PROPS_INT (0x00ff00),
      "blue_mask",      GST_PROPS_INT (0x0000ff)
  );
#else
  c = GST_CAPS_NEW (
    "swfdec_videosrc",
    "video/raw",
      "format",         GST_PROPS_FOURCC (GST_MAKE_FOURCC
('R','G','B',' ')),
      "bpp",            GST_PROPS_INT (24),
      "depth",          GST_PROPS_INT (24),
      "endianness",     GST_PROPS_INT (G_BYTE_ORDER),
      "red_mask",       GST_PROPS_INT (0x0000ff),
      "green_mask",     GST_PROPS_INT (0x00ff00),
      "blue_mask",      GST_PROPS_INT (0xff0000)
  );
#endif

Arguably, one can make this cleaner, although not smaller.  However,
one must use #ifdefs for GST_PAD_TEMPLATE_FACTORY().

Comment 8 Ronald Bultje 2003-05-10 08:57:02 UTC
But this will go for most file-source/file-sink elements. I'm assuming
that swf inherently always uses big-endian inside? Similarly, AVI
always contains little endian data. So RGB32 data in an AVI file would
always look like BGRA:

((guint8 *) data)[0] = b;
((guint8 *) data)[1] = g;
((guint8 *) data)[2] = r;
((guint8 *) data)[3] = a;

Most files/streams simply have an internally defined, fixed, byte
order. This is simply a portability feature of these files. So
file/stream elements, in the old case, would always need #ifdefs. In
the new case, they wouldn't.

Device elements, on the other hand, will always wan the native byte
order, e.g. for sending stuff to the sound card, xvideo,
reading/writing v4l, etc. This is because the byte order here always
depends on the host system. In the old case, we didn't need #ifdefs
all around, you simply describe (RGB32 as example)
red_mask=0x00ff0000, blue_mask=0x0000ff00, green_mask=0x000000ff and
endianness is G_BYTE_ORDER. In the new case, we get exactly the
problem that file elements have in the old case: we'll need #ifdefs,
and the caps you described above will be exactly what's needed here, now.

For encoders/decoders/filters, I'm not sure what applies most. This
basically depends on whether the underlying lib/backend reads data as
bytes or as guint32's. I'm guessing some libs do the one, other libs
do the other so I can't say much here.

So my conclusion is that for some elements, fixed byte order is easier
in describing their caps, while for others, native byte order is
easier. It doesn't make any difference, really...
Comment 9 Ronald Bultje 2003-06-30 21:48:59 UTC
I'll take this patch with me in the caps remake.

(I still don't like it, but that's beyond the point ;) )

*** This bug has been marked as a duplicate of 116387 ***