[vlc-commits] demux: avi: split BIH handling

Francois Cartegnie git at videolan.org
Tue Aug 14 15:56:11 CEST 2018


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon Aug 13 11:44:05 2018 +0200| [042dc8aca36f16881c398537a2b18ad1ccf03fbc] | committer: Francois Cartegnie

demux: avi: split BIH handling

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=042dc8aca36f16881c398537a2b18ad1ccf03fbc
---

 modules/demux/Makefile.am            |   3 +-
 modules/demux/avi/avi.c              | 171 +++++--------------------------
 modules/demux/avi/bitmapinfoheader.h | 191 +++++++++++++++++++++++++++++++++++
 3 files changed, 217 insertions(+), 148 deletions(-)

diff --git a/modules/demux/Makefile.am b/modules/demux/Makefile.am
index 83534711b9..70923d8945 100644
--- a/modules/demux/Makefile.am
+++ b/modules/demux/Makefile.am
@@ -128,7 +128,8 @@ libasf_plugin_la_SOURCES = demux/asf/asf.c demux/asf/libasf.c demux/asf/libasf.h
                            demux/asf/libasf_guid.h
 demux_LTLIBRARIES += libasf_plugin.la
 
-libavi_plugin_la_SOURCES = demux/avi/avi.c demux/avi/libavi.c demux/avi/libavi.h
+libavi_plugin_la_SOURCES = demux/avi/avi.c demux/avi/libavi.c demux/avi/libavi.h \
+                           demux/avi/bitmapinfoheader.h
 demux_LTLIBRARIES += libavi_plugin.la
 
 libcaf_plugin_la_SOURCES = demux/caf.c
diff --git a/modules/demux/avi/avi.c b/modules/demux/avi/avi.c
index 068c2d30b9..da79217528 100644
--- a/modules/demux/avi/avi.c
+++ b/modules/demux/avi/avi.c
@@ -45,6 +45,7 @@
 
 #include "libavi.h"
 #include "../rawdv.h"
+#include "bitmapinfoheader.h"
 
 /*****************************************************************************
  * Module descriptor
@@ -146,8 +147,7 @@ typedef struct
     unsigned int    i_scale;
     unsigned int    i_samplesize;
 
-    unsigned int    i_width_bytes;
-    bool            b_flipped;
+    struct bitmapinfoheader_properties bihprops;
 
     es_format_t     fmt;
     es_out_id_t     *p_es;
@@ -274,30 +274,6 @@ static void Close ( vlc_object_t * p_this )
     free( p_sys );
 }
 
-static void Set_BMP_RGB_Masks( es_format_t *fmt )
-{
-    switch( fmt->i_codec )
-    {
-        case VLC_CODEC_RGB32:
-            fmt->video.i_bmask = 0xff000000;
-            fmt->video.i_gmask = 0x00ff0000;
-            fmt->video.i_rmask = 0x0000ff00;
-            break;
-        case VLC_CODEC_RGB24: /* BGR (see biBitCount) */
-            fmt->video.i_bmask = 0x00ff0000;
-            fmt->video.i_gmask = 0x0000ff00;
-            fmt->video.i_rmask = 0x000000ff;
-            break;
-        case VLC_CODEC_RGB15:
-            fmt->video.i_rmask = 0x7c00;
-            fmt->video.i_gmask = 0x03e0;
-            fmt->video.i_bmask = 0x001f;
-            break;
-        default:
-            break;
-    }
-}
-
 /*****************************************************************************
  * Open: check file and initializes AVI structures
  *****************************************************************************/
@@ -605,124 +581,25 @@ static int Open( vlc_object_t * p_this )
                 es_format_Init( &tk->fmt, VIDEO_ES,
                         AVI_FourccGetCodec( VIDEO_ES, p_vids->p_bih->biCompression ) );
 
-                /* Extradata is the remainder of the chunk less the BIH */
-                const uint8_t *p_bihextra = (const uint8_t *) &p_vids->p_bih[1];
-                size_t i_bihextra;
-                if( p_vids->i_chunk_size <= INT_MAX - sizeof(VLC_BITMAPINFOHEADER) )
-                    i_bihextra = p_vids->i_chunk_size - sizeof(VLC_BITMAPINFOHEADER);
-                else
-                    i_bihextra = 0;
-
-                if( p_vids->p_bih->biCompression == BI_RGB ||
-                    p_vids->p_bih->biCompression == BI_BITFIELDS )
+                if( ParseBitmapInfoHeader( p_vids->p_bih, p_vids->i_chunk_size, &tk->fmt,
+                                           &tk->bihprops ) != VLC_SUCCESS )
                 {
-                    switch( p_vids->p_bih->biBitCount )
-                    {
-                        case 32:
-                            tk->fmt.i_codec = VLC_CODEC_RGB32;
-                            Set_BMP_RGB_Masks( &tk->fmt );
-                            break;
-                        case 24:
-                            tk->fmt.i_codec = VLC_CODEC_RGB24; /* BGR (see biBitCount) */
-                            Set_BMP_RGB_Masks( &tk->fmt );
-                            break;
-                        case 16: /* Yes it is RV15 */
-                        case 15: /* RGB (B least 5 bits) */
-                            tk->fmt.i_codec = VLC_CODEC_RGB15;
-                            Set_BMP_RGB_Masks( &tk->fmt );
-                            break;
-                        case 9: /* <- TODO check that */
-                            tk->fmt.i_codec = VLC_CODEC_I410;
-                            break;
-                        case 8:
-                            if ( p_vids->p_bih->biClrUsed )
-                                tk->fmt.i_codec = VLC_CODEC_RGBP;
-                            else
-                                tk->fmt.i_codec = VLC_CODEC_GREY;
-                            break;
-                        default:
-                            if( p_vids->p_bih->biClrUsed < 8 )
-                                tk->fmt.i_codec = VLC_CODEC_RGBP;
-                            break;
-                    }
-
-                    if( p_vids->p_bih->biCompression == BI_BITFIELDS ) /* Only 16 & 32 */
-                    {
-                        if( i_bihextra >= 3 * sizeof(uint32_t) )
-                        {
-                            tk->fmt.video.i_rmask = GetDWLE( &p_bihextra[0] );
-                            tk->fmt.video.i_gmask = GetDWLE( &p_bihextra[4] );
-                            tk->fmt.video.i_bmask = GetDWLE( &p_bihextra[8] );
-                            if( i_bihextra >= 4 * sizeof(uint32_t) ) /* Alpha channel ? */
-                            {
-                                uint32_t i_alpha = GetDWLE( &p_bihextra[8] );
-                                if( tk->fmt.i_codec == VLC_CODEC_RGB32 && i_alpha == 0xFF )
-                                    tk->fmt.i_codec = VLC_CODEC_BGRA;
-                            }
-                        }
-                    }
-                    else if( tk->fmt.i_codec == VLC_CODEC_RGBP )
-                    {
-                        /* The palette should not be included in biSize, but come
-                         * directly after BITMAPINFORHEADER in the BITMAPINFO structure */
-                        tk->fmt.video.p_palette = malloc( sizeof(video_palette_t) );
-                        if ( tk->fmt.video.p_palette )
-                        {
-                            tk->fmt.video.p_palette->i_entries = __MIN(i_bihextra/4, 256);
-                            for( int k = 0; k < tk->fmt.video.p_palette->i_entries; k++ )
-                            {
-                                for( int j = 0; j < 4; j++ )
-                                    tk->fmt.video.p_palette->palette[k][j] = p_bihextra[4*k+j];
-                            }
-                        }
-                    }
-
-                    tk->i_width_bytes = p_vids->p_bih->biWidth * (p_vids->p_bih->biBitCount >> 3);
-                    /* RGB DIB are coded from bottom to top */
-                    if ( p_vids->p_bih->biHeight < INT32_MAX ) tk->b_flipped = true;
+                    es_format_Clean( &tk->fmt );
+                    free( tk );
+                    goto error;
                 }
-                else /* Compressed codecs */
-                {
-                    tk->fmt.i_codec = p_vids->p_bih->biCompression;
-                    if( tk->fmt.i_codec == VLC_CODEC_MP4V &&
-                        !strncasecmp( (char*)&p_strh->i_handler, "XVID", 4 ) )
-                    {
-                        tk->fmt.i_codec           =
-                        tk->fmt.i_original_fourcc = VLC_FOURCC( 'X', 'V', 'I', 'D' );
-                    }
 
-                    /* Cop extradata if any */
-                    if( i_bihextra > 0 )
-                    {
-                        tk->fmt.p_extra = malloc( i_bihextra );
-                        if( unlikely(tk->fmt.p_extra == NULL) )
-                        {
-                            es_format_Clean( &tk->fmt );
-                            free( tk );
-                            goto error;
-                        }
-                        tk->fmt.i_extra = i_bihextra;
-                        memcpy( tk->fmt.p_extra, p_bihextra, i_bihextra );
-                    }
-
-                    /* Shitty files storing chroma in biCompression */
-                    Set_BMP_RGB_Masks( &tk->fmt );
+                if( tk->fmt.i_codec == VLC_CODEC_MP4V &&
+                    !strncasecmp( (char*)&p_strh->i_handler, "XVID", 4 ) )
+                {
+                    tk->fmt.i_codec           =
+                    tk->fmt.i_original_fourcc = VLC_FOURCC( 'X', 'V', 'I', 'D' );
                 }
-                tk->i_samplesize = 0;
 
-                tk->fmt.video.i_visible_width =
-                tk->fmt.video.i_width  = p_vids->p_bih->biWidth;
-                tk->fmt.video.i_visible_height =
-                tk->fmt.video.i_height = p_vids->p_bih->biHeight;
-                tk->fmt.video.i_bits_per_pixel = p_vids->p_bih->biBitCount;
+                tk->i_samplesize = 0;
                 tk->fmt.video.i_frame_rate = tk->i_rate;
                 tk->fmt.video.i_frame_rate_base = tk->i_scale;
 
-                 /* Uncompresse Bitmap or YUV, YUV being always topdown */
-                if ( tk->fmt.video.i_height > INT32_MAX )
-                    tk->fmt.video.i_height =
-                        (unsigned int)(-(int)p_vids->p_bih->biHeight);
-
                 avi_chunk_vprp_t *p_vprp = AVI_ChunkFind( p_strl, AVIFOURCC_vprp, 0, false );
                 if( p_vprp )
                 {
@@ -950,9 +827,9 @@ static block_t * ReadFrame( demux_t *p_demux, const avi_track_t *tk,
     p_frame->p_buffer += i_header;
     p_frame->i_buffer -= i_header;
 
-    const unsigned int i_stride_bytes = ((( (tk->i_width_bytes << 3) + 31) & ~31) >> 3);
+    const unsigned int i_stride_bytes = ((( (tk->bihprops.i_stride << 3) + 31) & ~31) >> 3);
 
-    if ( !tk->i_width_bytes || !i_stride_bytes )
+    if ( !tk->bihprops.i_stride || !i_stride_bytes )
         return p_frame;
 
     if( p_frame->i_buffer < i_stride_bytes )
@@ -961,20 +838,20 @@ static block_t * ReadFrame( demux_t *p_demux, const avi_track_t *tk,
         return p_frame;
     }
 
-    if( !tk->b_flipped )
+    if( !tk->bihprops.b_flipped )
     {
         const uint8_t *p_src = p_frame->p_buffer + i_stride_bytes;
         const uint8_t *p_end = p_frame->p_buffer + p_frame->i_buffer;
-        uint8_t *p_dst = p_frame->p_buffer + tk->i_width_bytes;
+        uint8_t *p_dst = p_frame->p_buffer + tk->bihprops.i_stride;
 
-        p_frame->i_buffer = tk->i_width_bytes;
+        p_frame->i_buffer = tk->bihprops.i_stride;
 
         while ( p_src + i_stride_bytes <= p_end )
         {
-            memmove( p_dst, p_src, tk->i_width_bytes );
+            memmove( p_dst, p_src, tk->bihprops.i_stride );
             p_src += i_stride_bytes;
-            p_dst += tk->i_width_bytes;
-            p_frame->i_buffer += tk->i_width_bytes;
+            p_dst += tk->bihprops.i_stride;
+            p_frame->i_buffer += tk->bihprops.i_stride;
         }
     }
     else
@@ -995,9 +872,9 @@ static block_t * ReadFrame( demux_t *p_demux, const avi_track_t *tk,
         while ( i_lines-- > 0 )
         {
             p_src -= i_stride_bytes;
-            memcpy( p_dst, p_src, tk->i_width_bytes );
-            p_dst += tk->i_width_bytes;
-            p_flippedframe->i_buffer += tk->i_width_bytes;
+            memcpy( p_dst, p_src, tk->bihprops.i_stride );
+            p_dst += tk->bihprops.i_stride;
+            p_flippedframe->i_buffer += tk->bihprops.i_stride;
         }
 
         block_Release( p_frame );
diff --git a/modules/demux/avi/bitmapinfoheader.h b/modules/demux/avi/bitmapinfoheader.h
new file mode 100644
index 0000000000..2c43fac043
--- /dev/null
+++ b/modules/demux/avi/bitmapinfoheader.h
@@ -0,0 +1,191 @@
+/*****************************************************************************
+ * bitmapinfoheader.h : BITMAPINFOHEADER handling
+ *****************************************************************************
+ * Copyright (C) 2001-2009 VLC authors and VideoLAN
+ *               2018      VideoLabs, VLC authors and VideoLAN
+ *
+ * Authors: Laurent Aimar <fenrir at via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#include <vlc_common.h>
+#include <vlc_es.h>
+#include <vlc_codecs.h>
+#include <limits.h>
+
+/* biCompression / Others are FourCC */
+#define BI_RGB              0x0000
+#define BI_RLE8             0x0001
+#define BI_RLE4             0x0002
+#define BI_BITFIELDS        0x0003
+#define BI_JPEG             0x0004
+#define BI_PNG              0x0005
+#define BI_CMYK             0x000B
+#define BI_CMYKRLE8         0x000C
+#define BI_CMYKRLE4         0x000D
+
+static inline void SetBitmapRGBMasks( vlc_fourcc_t i_fourcc, es_format_t *fmt )
+{
+    switch( i_fourcc )
+    {
+        case VLC_CODEC_RGB15:
+            fmt->video.i_rmask = 0x7c00;
+            fmt->video.i_gmask = 0x03e0;
+            fmt->video.i_bmask = 0x001f;
+            break;
+        case VLC_CODEC_RGB16:
+            fmt->video.i_rmask = 0xf800;
+            fmt->video.i_gmask = 0x07e0;
+            fmt->video.i_bmask = 0x001f;
+            break;
+        case VLC_CODEC_RGB24: /* BGR (see biBitCount) */
+            fmt->video.i_bmask = 0x00ff0000;
+            fmt->video.i_gmask = 0x0000ff00;
+            fmt->video.i_rmask = 0x000000ff;
+            break;
+        case VLC_CODEC_RGB32: /* This is in BGRx format */
+        case VLC_CODEC_RGBA:
+            fmt->video.i_bmask = 0xff000000;
+            fmt->video.i_gmask = 0x00ff0000;
+            fmt->video.i_rmask = 0x0000ff00;
+            break;
+        default:
+            return;
+    }
+    fmt->video.i_chroma = i_fourcc;
+    video_format_FixRgb( &fmt->video );
+}
+
+struct bitmapinfoheader_properties
+{
+    bool b_flipped;
+    unsigned i_stride;
+};
+
+static inline int ParseBitmapInfoHeader( VLC_BITMAPINFOHEADER *p_bih, size_t i_bih,
+                                         es_format_t *fmt,
+                                         struct bitmapinfoheader_properties *p_props )
+{
+    /* Extradata is the remainder of the chunk less the BIH */
+    const uint8_t *p_bihextra = (const uint8_t *) &p_bih[1];
+    size_t i_bihextra;
+    if( i_bih <= INT_MAX - sizeof(VLC_BITMAPINFOHEADER) )
+        i_bihextra = i_bih - sizeof(VLC_BITMAPINFOHEADER);
+    else
+        i_bihextra = 0;
+
+    if( p_bih->biCompression == BI_RGB ||
+        p_bih->biCompression == BI_BITFIELDS )
+    {
+        switch( p_bih->biBitCount )
+        {
+            case 32:
+                fmt->i_codec = VLC_CODEC_RGB32;
+                SetBitmapRGBMasks( fmt->i_codec, fmt );
+                break;
+            case 24:
+                fmt->i_codec = VLC_CODEC_RGB24; /* BGR (see biBitCount) */
+                SetBitmapRGBMasks( fmt->i_codec, fmt );
+                break;
+            case 16:
+                fmt->i_codec = VLC_CODEC_RGB16; /* RGB (5,6,5 bits) */
+                SetBitmapRGBMasks( fmt->i_codec, fmt );
+                break;
+            case 15: /* RGB (B least 5 bits) */
+                fmt->i_codec = VLC_CODEC_RGB15;
+                SetBitmapRGBMasks( fmt->i_codec, fmt );
+                break;
+            case 9: /* <- TODO check that */
+                fmt->i_codec = VLC_CODEC_I410;
+                break;
+            case 8:
+                if ( p_bih->biClrUsed )
+                    fmt->i_codec = VLC_CODEC_RGBP;
+                else
+                    fmt->i_codec = VLC_CODEC_GREY;
+                break;
+            default:
+                if( p_bih->biClrUsed < 8 )
+                    fmt->i_codec = VLC_CODEC_RGBP;
+                break;
+        }
+
+        if( p_bih->biCompression == BI_BITFIELDS ) /* Only 16 & 32 */
+        {
+            if( i_bihextra >= 3 * sizeof(uint32_t) )
+            {
+                fmt->video.i_rmask = GetDWLE( &p_bihextra[0] );
+                fmt->video.i_gmask = GetDWLE( &p_bihextra[4] );
+                fmt->video.i_bmask = GetDWLE( &p_bihextra[8] );
+                if( i_bihextra >= 4 * sizeof(uint32_t) ) /* Alpha channel ? */
+                {
+                    uint32_t i_alpha = GetDWLE( &p_bihextra[8] );
+                    if( fmt->i_codec == VLC_CODEC_RGB32 && i_alpha == 0xFF )
+                        fmt->i_codec = VLC_CODEC_BGRA;
+                }
+            }
+            SetBitmapRGBMasks( fmt->i_codec, fmt ); /* override default masks shifts */
+        }
+        else if( fmt->i_codec == VLC_CODEC_RGBP )
+        {
+            /* The palette should not be included in biSize, but come
+             * directly after BITMAPINFORHEADER in the BITMAPINFO structure */
+            fmt->video.p_palette = malloc( sizeof(video_palette_t) );
+            if ( fmt->video.p_palette )
+            {
+                fmt->video.p_palette->i_entries = __MIN(i_bihextra/4, 256);
+                for( int k = 0; k < fmt->video.p_palette->i_entries; k++ )
+                {
+                    for( int j = 0; j < 4; j++ )
+                        fmt->video.p_palette->palette[k][j] = p_bihextra[4*k+j];
+                }
+            }
+        }
+
+        p_props->i_stride = p_bih->biWidth * (p_bih->biBitCount >> 3);
+        /* RGB DIB are coded from bottom to top */
+        if ( p_bih->biHeight < INT32_MAX ) p_props->b_flipped = true;
+    }
+    else /* Compressed codecs */
+    {
+        fmt->i_codec = p_bih->biCompression;
+
+        /* Copy extradata if any */
+        if( i_bihextra > 0 )
+        {
+            fmt->p_extra = malloc( i_bihextra );
+            if( unlikely(fmt->p_extra == NULL) )
+                return VLC_ENOMEM;
+            fmt->i_extra = i_bihextra;
+            memcpy( fmt->p_extra, p_bihextra, i_bihextra );
+        }
+
+        /* Shitty VLC muxed files storing chroma in biCompression */
+        SetBitmapRGBMasks( fmt->i_codec, fmt );
+    }
+
+    fmt->video.i_visible_width =
+    fmt->video.i_width  = p_bih->biWidth;
+    fmt->video.i_visible_height =
+    fmt->video.i_height = p_bih->biHeight;
+    fmt->video.i_bits_per_pixel = p_bih->biBitCount;
+
+    /* Uncompressed Bitmap or YUV, YUV being always topdown */
+    if ( fmt->video.i_height > INT32_MAX )
+        fmt->video.i_height =
+            (unsigned int)(-(int)p_bih->biHeight);
+
+    return VLC_SUCCESS;
+}



More information about the vlc-commits mailing list