[vlc-commits] [Git][videolan/vlc][master] 12 commits: bitmapinfoheader: explicitly use BI_RGB by default

Steve Lhomme (@robUx4) gitlab at videolan.org
Fri Sep 15 10:18:15 UTC 2023



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
066e235f by Steve Lhomme at 2023-09-15T10:02:07+00:00
bitmapinfoheader: explicitly use BI_RGB by default

BI_RGB is 0, no need to set it again to 0 later.

- - - - -
22e26729 by Steve Lhomme at 2023-09-15T10:02:07+00:00
bitmapinfoheader: map VLC_CODEC_BGRX like VLC_CODEC_BGRA

We may want to use BI_BITFIELDS with it too.

- - - - -
3f41da4a by Steve Lhomme at 2023-09-15T10:02:07+00:00
bitmpainfoheader: fix 32-bit BI_RGB mapping

With the follwing code change in mock, the planes end up matching the XRGB
order when playing the file with the Windows player. There is no mask involved
here.

* The first bar is black for 32-bit color [0xFF 0x00 0x00 0x00]
* The second bar is red for 32-bit color [0x00 0xFF 0x00 0x00]
* The third bar is green for 32-bit color [0x00 0x00 0xFF 0x00]
* The fourth bar is blue for 32-bit color [0x00 0x00 0x00 0xFF]

mock://video_track_count=1;length=6000000;video_chroma=XRGB
--sout=#transcode{vcodec=XRGB}:std{access=file,dst=xrgb.avi,mux=avi}

    unsigned lines_per_color = pic->p[0].i_visible_lines / pic->p[0].i_pixel_pitch;
    for (int bar = 0; bar < pic->p[0].i_pixel_pitch; bar++)
    {
        uint8_t colors[pic->p[0].i_pixel_pitch];
        memset(colors, 0, sizeof(colors));
        colors[bar] = 0xFF;
        for (unsigned y=bar*lines_per_color; y < (bar+1)*lines_per_color; y++)
            for (int x=0; x < pic->p[0].i_visible_pitch; x += pic->p[0].i_pixel_pitch)
            {
                memcpy(&pic->p[0].p_pixels[x + y*pic->p[0].i_pitch], colors, pic->p[0].i_pixel_pitch);
            }
    }
    memset(pic->p[0].p_pixels, pixel, block_len);

- - - - -
a8212280 by Steve Lhomme at 2023-09-15T10:02:07+00:00
bitmapinfoheader: fix mask detection to match RGB32 with BI_RGB

We know BI_RGB corresponds to XRGB, so we should match it with the
corresponding mask.

- - - - -
6bf7babd by Steve Lhomme at 2023-09-15T10:02:07+00:00
bitmapinfoheader: fix 32-bit mask usage

RGB32 with the same mask as XRGB ends up using a the wrong mask.
In both case the mask is 0xff0000/0x00ff00/0x0000ff and needs to go
through hton32.

RGB32 with default mask encoded as BI_BITFIELDS correctly play in the Windows player
after this patch.

- - - - -
050937a0 by Steve Lhomme at 2023-09-15T10:02:07+00:00
bitmapinfoheader: fix RGB16 mask comment

When patching mock with the following code and forcing BI_RGB, to not use
any mask, the Windows player render Blue, Green, Red planes in that order.
The 16-bit color values have to be written as Little-Endian (SetWLE).

    int bars = __MAX(3, pic->p[0].i_pixel_pitch);
    uint8_t colors[4];
    unsigned lines_per_color = pic->p[0].i_visible_lines / bars;
    for (int bar = 0; bar < bars; bar++)
    {
        memset(colors, 0, sizeof(colors));
        if (pic->p[0].i_pixel_pitch == 2)
        {
            if (bar == 0)
                SetWLE(colors, 0x1F << 11);
            else if (bar == 1)
                SetWLE(colors, 0x3F << 5);
            else if (bar == 2)
                SetWLE(colors, 0x1F << 0);
        }

        for (unsigned y=bar*lines_per_color; y < (bar+1)*lines_per_color; y++)
            for (int x=0; x < pic->p[0].i_visible_pitch; x += pic->p[0].i_pixel_pitch)
            {
                memcpy(&pic->p[0].p_pixels[x + y*pic->p[0].i_pitch], colors, pic->p[0].i_pixel_pitch);
            }
    }
    memset(pic->p[0].p_pixels, pixel, block_len);

- - - - -
177bff83 by Steve Lhomme at 2023-09-15T10:02:07+00:00
bitmapinfoheader: fix RGB15 mask comment

When patching mock with the following code and forcing BI_RGB, to not use
any mask, the Windows player render Blue, Green, Red planes in that order.
The 16-bit color values have to be written as Little-Endian (SetWLE).

    int bars = __MAX(3, pic->p[0].i_pixel_pitch);
    uint8_t colors[4];
    unsigned lines_per_color = pic->p[0].i_visible_lines / bars;
    for (int bar = 0; bar < bars; bar++)
    {
        memset(colors, 0, sizeof(colors));
        if (pic->p[0].i_pixel_pitch == 2)
        {
            if (bar == 0)
                SetWLE(colors, 0x1F << 10);
            else if (bar == 1)
                SetWLE(colors, 0x1F << 5);
            else if (bar == 2)
                SetWLE(colors, 0x1F << 0);
        }

        for (unsigned y=bar*lines_per_color; y < (bar+1)*lines_per_color; y++)
            for (int x=0; x < pic->p[0].i_visible_pitch; x += pic->p[0].i_pixel_pitch)
            {
                memcpy(&pic->p[0].p_pixels[x + y*pic->p[0].i_pitch], colors, pic->p[0].i_pixel_pitch);
            }
    }
    memset(pic->p[0].p_pixels, pixel, block_len);

- - - - -
6bab8418 by Steve Lhomme at 2023-09-15T10:02:07+00:00
bitmapinfoheader: fix 15/16-bit mask usage

When using BI_BITFIELD with the data written as R5G5B5LE/B5G6R5LE the only
mask accepted by the Windows player is our default mask passed through hton32.

- - - - -
4ae5f3ed by Steve Lhomme at 2023-09-15T10:02:07+00:00
bitmapinfoheader: always apply hton32 on the RGB masks

BI_BITFIELDS can only be used with 32-bit and 16-bit RGB. So it's always
applied anyway.

- - - - -
7028356f by Steve Lhomme at 2023-09-15T10:02:07+00:00
bitmapinfoheader: fix double hton32 swap on masks

We do a first hton32 on the mask and then SetDWBE does it again.
What we really want is to store the mask as Little-Endian. This is also coherent
with the GetDWLE() used for reading the masks in ParseBitmapInfoHeader().

The corresponds to the 3 colors in extra data after the VLC_BITMAPINFOHEADER
for BI_BITFIELD [1]:

> If biCompression equals BI_BITFIELDS, the bitmap uses three DWORD color
> masks (red, green, and blue, respectively), which specify the byte layout
> of the pixels. The 1 bits in each mask indicate the bits for that color
> within the pixel.

The "bitmap" being the data after the "bitmap header".

[1] https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader

- - - - -
d50370ee by Steve Lhomme at 2023-09-15T10:02:07+00:00
vlc_es: add a function to get the mask for RGB chromas

Even if we don't keep masks internally, some system still need to
set RGB(A) masks. We can handle all our RGB chroma as we know
the proper component position.

- - - - -
2aeea3cf by Steve Lhomme at 2023-09-15T10:02:07+00:00
bitmapinfoheader: get the native endianness mask from vlc_RGBChromaToMask

- - - - -


2 changed files:

- include/vlc_es.h
- modules/demux/avi/bitmapinfoheader.h


Changes:

=====================================
include/vlc_es.h
=====================================
@@ -783,4 +783,71 @@ vlc_es_id_GetStrId(vlc_es_id_t *id);
 VLC_API enum es_format_category_e
 vlc_es_id_GetCat(vlc_es_id_t *id);
 
+/**
+ * Get the native endianness mask for a RGB fourcc
+ *
+ * @note the alpha mask is 0 when the chroma doesn't contain an alpha component.
+ *
+ * @return VLC_SUCCESS if the mask values were filled
+ */
+static inline int vlc_RGBChromaToMask( vlc_fourcc_t fcc, uint32_t *rmask,
+                                       uint32_t *gmask, uint32_t *bmask,
+                                       uint32_t *amask )
+{
+    switch(fcc)
+    {
+        case VLC_CODEC_BGRA:
+            *bmask = 0xff000000;
+            *gmask = 0x00ff0000;
+            *rmask = 0x0000ff00;
+            *amask = 0x000000ff;
+            break;
+        case VLC_CODEC_BGRX:
+            *bmask = 0xff000000;
+            *gmask = 0x00ff0000;
+            *rmask = 0x0000ff00;
+            *amask = 0;
+            break;
+        case VLC_CODEC_RGBA:
+            *rmask = 0xff000000;
+            *gmask = 0x00ff0000;
+            *bmask = 0x0000ff00;
+            *amask = 0x000000ff;
+            break;
+        case VLC_CODEC_RGBX:
+            *rmask = 0xff000000;
+            *gmask = 0x00ff0000;
+            *bmask = 0x0000ff00;
+            *amask = 0;
+            break;
+        case VLC_CODEC_ABGR:
+            *amask = 0xff000000;
+            *bmask = 0x00ff0000;
+            *gmask = 0x0000ff00;
+            *rmask = 0x000000ff;
+            break;
+        case VLC_CODEC_XBGR:
+            *amask = 0;
+            *bmask = 0x00ff0000;
+            *gmask = 0x0000ff00;
+            *rmask = 0x000000ff;
+            break;
+        case VLC_CODEC_ARGB:
+            *amask = 0xff000000;
+            *rmask = 0x00ff0000;
+            *gmask = 0x0000ff00;
+            *bmask = 0x000000ff;
+            break;
+        case VLC_CODEC_XRGB:
+            *amask = 0;
+            *rmask = 0x00ff0000;
+            *gmask = 0x0000ff00;
+            *bmask = 0x000000ff;
+            break;
+        default:
+            return VLC_EINVAL;
+    }
+    return VLC_SUCCESS;
+}
+
 #endif


=====================================
modules/demux/avi/bitmapinfoheader.h
=====================================
@@ -44,18 +44,18 @@ static const struct
     vlc_fourcc_t codec;
     uint32_t i_rmask, i_gmask, i_bmask;
 } bitmap_rgb_masks[] = {
-    { VLC_CODEC_RGB15,      0x7c00, /* R5G5B5 */
+    { VLC_CODEC_RGB15,      0x7c00, /* FIXME it should be B5G5R5LE */
                             0x03e0,
                             0x001f, },
-    { VLC_CODEC_RGB16,      0xf800, /* R5G6B5 */
+    { VLC_CODEC_RGB16,      0xf800, /* FIXME it should be B5G6R5LE */
                             0x07e0,
                             0x001f, },
     { VLC_CODEC_RGB24,      0x000000ff, /* BGR (see biBitCount) */
                             0x0000ff00,
                             0x00ff0000, },
-    { VLC_CODEC_RGB32,      0x0000ff00, /* This is in BGR0 format */
-                            0x00ff0000,
-                            0xff000000U, },
+    { VLC_CODEC_RGB32,      0x00ff0000, /* This is in XRGB format */
+                            0x0000ff00,
+                            0x000000ff, },
 };
 
 static inline void SetBitmapRGBMasks( vlc_fourcc_t i_fourcc, video_format_t *fmt )
@@ -252,23 +252,23 @@ static inline VLC_BITMAPINFOHEADER * CreateBitmapInfoHeader( const es_format_t *
                                                              size_t *pi_total )
 {
     uint16_t biBitCount = 0;
-    uint32_t biCompression = 0;
+    uint32_t biCompression = BI_RGB;
     bool b_has_alpha = false;
     switch( fmt->i_codec )
     {
-        case VLC_CODEC_BGRX:
+        case VLC_CODEC_XRGB:
             biBitCount = 32;
-            biCompression = BI_RGB;
             break;
+        case VLC_CODEC_BGRX:
         case VLC_CODEC_XBGR:
-        case VLC_CODEC_XRGB:
         case VLC_CODEC_RGBX:
             biBitCount = 32;
             biCompression = BI_BITFIELDS;
             break;
         case VLC_CODEC_RGB32:
             biBitCount = 32;
-            biCompression = MatchBitmapRGBMasks( fmt ) ? BI_RGB : BI_BITFIELDS;
+            if ( !MatchBitmapRGBMasks( fmt ) )
+                biCompression = BI_BITFIELDS;
             break;
         case VLC_CODEC_BGRA:
         case VLC_CODEC_RGBA:
@@ -280,7 +280,6 @@ static inline VLC_BITMAPINFOHEADER * CreateBitmapInfoHeader( const es_format_t *
             break;
         case VLC_CODEC_RGB24:
             biBitCount = 24;
-            biCompression = BI_RGB;
             break;
         case VLC_CODEC_RGB16:
         case VLC_CODEC_RGB15:
@@ -290,7 +289,6 @@ static inline VLC_BITMAPINFOHEADER * CreateBitmapInfoHeader( const es_format_t *
         case VLC_CODEC_RGBP:
         case VLC_CODEC_GREY:
             biBitCount = 8;
-            biCompression = BI_RGB;
             break;
         case VLC_CODEC_MP4V:
             biCompression = VLC_FOURCC( 'X', 'V', 'I', 'D' );
@@ -320,44 +318,21 @@ static inline VLC_BITMAPINFOHEADER * CreateBitmapInfoHeader( const es_format_t *
     p_bih->biClrUsed = 0;
     if( biCompression == BI_BITFIELDS )
     {
-        uint32_t i_rmask,i_gmask,i_bmask;
-        switch( fmt->i_codec )
+        uint32_t i_rmask,i_gmask,i_bmask, i_amask;
+        int ret = vlc_RGBChromaToMask( fmt->i_codec, &i_rmask, &i_gmask,
+                                       &i_bmask, &i_amask );
+        if (ret != VLC_SUCCESS)
         {
-            case VLC_CODEC_ABGR:
-            case VLC_CODEC_XBGR:
-                i_rmask = hton32(0x000000ff);
-                i_gmask = hton32(0x0000ff00);
-                i_bmask = hton32(0x00ff0000);
-                break;
-            case VLC_CODEC_ARGB:
-            case VLC_CODEC_XRGB:
-                i_rmask = hton32(0x00ff0000);
-                i_gmask = hton32(0x0000ff00);
-                i_bmask = hton32(0x000000ff);
-                break;
-            case VLC_CODEC_RGBA:
-            case VLC_CODEC_RGBX:
-                i_rmask = hton32(0xff000000);
-                i_gmask = hton32(0x00ff0000);
-                i_bmask = hton32(0x0000ff00);
-                break;
-            case VLC_CODEC_BGRA:
-                i_rmask = hton32(0x0000ff00);
-                i_gmask = hton32(0x00ff0000);
-                i_bmask = hton32(0xff000000);
-                break;
-            default:
-                i_rmask = fmt->video.i_rmask;
-                i_gmask = fmt->video.i_gmask;
-                i_bmask = fmt->video.i_bmask;
-                break;
+            i_rmask = fmt->video.i_rmask;
+            i_gmask = fmt->video.i_gmask;
+            i_bmask = fmt->video.i_bmask;
         }
-        SetDWBE( &p_bmiColors[0], i_rmask );
-        SetDWBE( &p_bmiColors[4], i_gmask );
-        SetDWBE( &p_bmiColors[8], i_bmask );
+        SetDWLE( &p_bmiColors[0], i_rmask );
+        SetDWLE( &p_bmiColors[4], i_gmask );
+        SetDWLE( &p_bmiColors[8], i_bmask );
         if( b_has_alpha )
         {
-            SetDWBE( &p_bmiColors[12], ~(i_rmask | i_gmask | i_bmask) );
+            SetDWLE( &p_bmiColors[12], i_amask );
         }
     }
     else if( fmt->i_codec == VLC_CODEC_RGBP )



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b1e4b572ce1b405d889c53c56ae0e2e73cc1b526...2aeea3cf00f727e8494d54e8803093f9ec10b7e8

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b1e4b572ce1b405d889c53c56ae0e2e73cc1b526...2aeea3cf00f727e8494d54e8803093f9ec10b7e8
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list