[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