X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fcodec%2Fcinepak.c;h=b7642ec24911bb3240bfc7db3d6aa194f99b9c93;hb=4e9597b800d1140dfab1cf33c3df8c608d58878f;hp=cedf7bb1f591b69d3a8bd49699997c185436c2a5;hpb=61f6d450b1863de272a471d34d35af8d031390da;p=vlc diff --git a/modules/codec/cinepak.c b/modules/codec/cinepak.c index cedf7bb1f5..b7642ec249 100644 --- a/modules/codec/cinepak.c +++ b/modules/codec/cinepak.c @@ -1,8 +1,8 @@ /***************************************************************************** * cinepak.c: cinepak video decoder ***************************************************************************** - * Copyright (C) 1999-2001 VideoLAN - * $Id: cinepak.c,v 1.4 2003/11/22 23:39:14 fenrir Exp $ + * Copyright (C) 1999-2001 the VideoLAN team + * $Id$ * * Authors: Laurent Aimar * @@ -18,31 +18,54 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Preamble *****************************************************************************/ -#include -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ +static int OpenDecoder ( vlc_object_t * ); +static void CloseDecoder( vlc_object_t * ); + +vlc_module_begin(); + set_description( N_("Cinepak video decoder") ); + set_capability( "decoder", 50 ); + set_category( CAT_INPUT ); + set_subcategory( SUBCAT_INPUT_VCODEC ); + set_callbacks( OpenDecoder, CloseDecoder ); +vlc_module_end(); + + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ #define CINEPAK_MAXSTRIP 32 -typedef struct cinepak_codebook_s +typedef struct { uint8_t i_y[4]; uint8_t i_u, i_v; } cinepak_codebook_t; -typedef struct cinepak_context_s +typedef struct { int b_grayscale; /* force to grayscale */ - int i_width; - int i_height; + unsigned int i_width; + unsigned int i_height; int i_stride_x; int i_stride_y; @@ -66,26 +89,12 @@ struct decoder_sys_t /* * Cinepak properties */ - cinepak_context_t *p_context; + cinepak_context_t context; }; -/***************************************************************************** - * Local prototypes - *****************************************************************************/ -static int OpenDecoder( vlc_object_t * ); -static void CloseDecoder( vlc_object_t * ); static picture_t *DecodeBlock ( decoder_t *, block_t ** ); -static int cinepak_decode_frame( cinepak_context_t *, int, uint8_t * ); - -/***************************************************************************** - * Module descriptor - *****************************************************************************/ -vlc_module_begin(); - set_description( _("Cinepak video decoder") ); - set_capability( "decoder", 70 ); - set_callbacks( OpenDecoder, CloseDecoder ); -vlc_module_end(); +static int cinepak_decode_frame( cinepak_context_t *, size_t, uint8_t * ); /***************************************************************************** * OpenDecoder: probe the decoder and return score @@ -99,33 +108,20 @@ static int OpenDecoder( vlc_object_t *p_this ) decoder_sys_t *p_sys; vlc_value_t val; - switch( p_dec->fmt_in.i_codec ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC('c','v','i','d') && + p_dec->fmt_in.i_codec != VLC_FOURCC('C','V','I','D') ) { - case VLC_FOURCC('c','v','i','d'): - case VLC_FOURCC('C','V','I','D'): - break; - - default: - return VLC_EGENERIC; - } - - /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = p_sys = - (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) - { - msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } - if( !(p_sys->p_context = malloc( sizeof( cinepak_context_t ) ) ) ) - { - msg_Err( p_dec, "out of memory" ); - } - memset( p_sys->p_context, 0, sizeof( cinepak_context_t ) ); + /* Allocate the memory needed to store the decoder's structure */ + if( ( p_dec->p_sys = p_sys = malloc(sizeof(decoder_sys_t)) ) == NULL ) + return VLC_ENOMEM; + memset( &p_sys->context, 0, sizeof( cinepak_context_t ) ); var_Create( p_dec, "grayscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_dec, "grayscale", &val ); - p_sys->p_context->b_grayscale = val.b_bool; + p_sys->context.b_grayscale = val.b_bool; p_dec->pf_decode_video = DecodeBlock; @@ -147,57 +143,55 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) picture_t *p_pic; block_t *p_block; - if( !pp_block || !*pp_block ) return NULL; - + if( !pp_block || !*pp_block ) + { + return NULL; + } p_block = *pp_block; + *pp_block = NULL; - i_status = cinepak_decode_frame( p_sys->p_context, p_block->i_buffer, + i_status = cinepak_decode_frame( &p_sys->context, p_block->i_buffer, p_block->p_buffer ); if( i_status < 0 ) { - msg_Warn( p_dec, "cannot decode one frame (%d bytes)", + msg_Warn( p_dec, "cannot decode one frame (%zu bytes)", p_block->i_buffer ); block_Release( p_block ); return NULL; } - p_dec->fmt_out.video.i_width = p_sys->p_context->i_width; - p_dec->fmt_out.video.i_height = p_sys->p_context->i_height; - p_dec->fmt_out.video.i_aspect = p_sys->p_context->i_width - * VOUT_ASPECT_FACTOR / p_sys->p_context->i_height; + p_dec->fmt_out.video.i_width = p_sys->context.i_width; + p_dec->fmt_out.video.i_height = p_sys->context.i_height; + p_dec->fmt_out.video.i_aspect = p_sys->context.i_width + * VOUT_ASPECT_FACTOR / p_sys->context.i_height; p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0'); /* Get a new picture */ - p_pic = p_dec->pf_vout_buffer_new( p_dec ); - - if( p_pic == NULL ) - { - block_Release( p_block ); - return NULL; - } - - for( i_plane = 0; i_plane < 3; i_plane++ ) + if( ( p_pic = p_dec->pf_vout_buffer_new( p_dec ) ) ) { - int i_line, i_lines; + for( i_plane = 0; i_plane < 3; i_plane++ ) + { + int i_line, i_lines; - p_dst = p_pic->p[i_plane].p_pixels; - p_src = p_sys->p_context->p_pix[i_plane]; + p_dst = p_pic->p[i_plane].p_pixels; + p_src = p_sys->context.p_pix[i_plane]; - i_lines = __MIN( p_sys->p_context->i_lines[i_plane], - p_pic->p[i_plane].i_lines ); - for( i_line = 0; i_line < i_lines; i_line++ ) - { - memcpy( p_dst, p_src, - __MIN( p_pic->p[i_plane].i_pitch, - p_sys->p_context->i_stride[i_plane] ) ); - p_dst += p_pic->p[i_plane].i_pitch; - p_src += p_sys->p_context->i_stride[i_plane]; + i_lines = __MIN( p_sys->context.i_lines[i_plane], + p_pic->p[i_plane].i_visible_lines ); + for( i_line = 0; i_line < i_lines; i_line++ ) + { + memcpy( p_dst, p_src, + __MIN( p_pic->p[i_plane].i_pitch, + p_sys->context.i_stride[i_plane] ) ); + p_dst += p_pic->p[i_plane].i_pitch; + p_src += p_sys->context.i_stride[i_plane]; + } } + + p_pic->date = p_block->i_pts ? p_block->i_pts : p_block->i_dts; } - p_pic->date = p_block->i_pts; block_Release( p_block ); - return p_pic; } @@ -206,18 +200,14 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) *****************************************************************************/ static void CloseDecoder( vlc_object_t *p_this ) { - decoder_t *p_dec = (decoder_t *)p_this; + decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys = p_dec->p_sys; int i; msg_Dbg( p_dec, "cinepak decoder stopped" ); for( i = 0; i < 3; i++ ) - { - if( p_sys->p_context->p_pix[i] ) free( p_sys->p_context->p_pix[i] ); - } - - free( p_sys->p_context ); + free( p_sys->context.p_pix[i] ); free( p_sys ); } @@ -235,9 +225,6 @@ static void CloseDecoder( vlc_object_t *p_this ) #define GET4BYTES( p ) \ GetDWBE( p ); p+= 4; -#define FREE( p ) \ - if( p ) free( p ) - static void cinepak_LoadCodebook( cinepak_codebook_t *p_codebook, uint8_t *p_data, int b_grayscale ) { @@ -287,11 +274,21 @@ static void cinepak_LoadCodebook( cinepak_codebook_t *p_codebook, static void cinepak_Getv4( cinepak_context_t *p_context, int i_strip, int i_x, int i_y, - int i_x2, int i_y2, uint8_t *p_data ) + uint8_t *p_data ) { uint8_t i_index[4]; int i,j; + size_t y_max = p_context->i_stride[0] * ( i_y + 5 ) + i_x + 5; + size_t u_max = p_context->i_stride[1] * ( ( i_y/2 ) + 2 ) + 2 + ( i_x / 2 ); + size_t v_max = p_context->i_stride[2] * ( ( i_y/2 ) + 2 ) + 2 + ( i_x / 2 ); + size_t y_siz = p_context->i_stride[0] * p_context->i_lines[0]; + size_t u_siz = p_context->i_stride[1] * p_context->i_lines[1]; + size_t v_siz = p_context->i_stride[2] * p_context->i_lines[2]; + /* boundary check */ + if( y_max >= y_siz || u_max >= u_siz || v_max >= v_siz ) + return; + uint8_t *p_dst_y, *p_dst_u, *p_dst_v; #define PIX_SET_Y( x, y, v ) \ p_dst_y[(x) + (y)* p_context->i_stride[0]] = (v); @@ -334,11 +331,21 @@ static void cinepak_Getv4( cinepak_context_t *p_context, static void cinepak_Getv1( cinepak_context_t *p_context, int i_strip, int i_x, int i_y, - int i_x2, int i_y2, uint8_t *p_data ) + uint8_t *p_data ) { uint8_t i_index; int i,j; + size_t y_max = p_context->i_stride[0] * ( i_y + 5 ) + i_x + 5; + size_t u_max = p_context->i_stride[1] * ( ( i_y/2 ) + 2 ) + 2 + ( i_x / 2 ); + size_t v_max = p_context->i_stride[2] * ( ( i_y/2 ) + 2 ) + 2 + ( i_x / 2 ); + size_t y_siz = p_context->i_stride[0] * p_context->i_lines[0]; + size_t u_siz = p_context->i_stride[1] * p_context->i_lines[1]; + size_t v_siz = p_context->i_stride[2] * p_context->i_lines[2]; + /* boundary check */ + if( y_max >= y_siz || u_max >= u_siz || v_max >= v_siz ) + return; + uint8_t *p_dst_y, *p_dst_u, *p_dst_v; #define PIX_SET_Y( x, y, v ) \ p_dst_y[(x) + (y)* p_context->i_stride[0]] = (v); @@ -381,14 +388,14 @@ static void cinepak_Getv1( cinepak_context_t *p_context, * The function that decode one frame *****************************************************************************/ static int cinepak_decode_frame( cinepak_context_t *p_context, - int i_length, uint8_t *p_data ) + size_t i_length, uint8_t *p_data ) { int i_strip; - int i_frame_flags; - int i_frame_size; - int i_width, i_height; - int i_frame_strips; + int8_t i_frame_flags; + uint32_t i_frame_size; + uint16_t i_width, i_height; + uint16_t i_frame_strips; int i_index; int i_strip_x1 =0, i_strip_y1=0; int i_strip_x2 =0, i_strip_y2=0; @@ -406,7 +413,8 @@ static int cinepak_decode_frame( cinepak_context_t *p_context, i_height = GET2BYTES( p_data ); i_frame_strips = GET2BYTES( p_data ); - if( !i_frame_size || !i_width || !i_height ) + if( !i_frame_size || !i_width || !i_height || + i_width > 0xffff-3 || i_height > 0xffff-3) { /* Broken header */ return( -1 ); @@ -419,7 +427,7 @@ static int cinepak_decode_frame( cinepak_context_t *p_context, int i; for( i = 0; i < 3; i++ ) { - FREE( p_context->p_pix[i] ); + free( p_context->p_pix[i] ); } p_context->i_width = i_width; @@ -437,6 +445,8 @@ static int cinepak_decode_frame( cinepak_context_t *p_context, { p_context->p_pix[i] = malloc( p_context->i_stride[i] * p_context->i_lines[i] ); + if( p_context->p_pix[i] == NULL ) + return -1; /* Set it to all black */ memset( p_context->p_pix[i], ( i == 0 ) ? 0 : 128 , p_context->i_stride[i] * p_context->i_lines[i] ); @@ -457,18 +467,18 @@ static int cinepak_decode_frame( cinepak_context_t *p_context, /* Now decode each strip */ for( i_strip = 0; i_strip < i_frame_strips; i_strip++ ) { - int i_strip_id; - int i_strip_size; + uint16_t i_strip_size; if( i_length <= 12 ) { break; } - i_strip_id = GET2BYTES( p_data ); + p_data += 2; /* int16_t i_strip_id = GET2BYTES( p_data ); */ + i_strip_size = GET2BYTES( p_data ); i_strip_size = __MIN( i_strip_size, i_length ); - /* FIXME I don't really understand how it's work; */ + /* FIXME I don't really understand how it works; */ i_strip_y1 = i_strip_y2 + GET2BYTES( p_data ); i_strip_x1 = GET2BYTES( p_data ); i_strip_y2 = i_strip_y2 + GET2BYTES( p_data ); @@ -596,7 +606,6 @@ static int cinepak_decode_frame( cinepak_context_t *p_context, i_strip, i_strip_x1 + i_x, i_strip_y1 + i_y, - i_strip_x2, i_strip_y2, p_data ); p_data += 4; i_chunk_size -= 4; @@ -607,7 +616,6 @@ static int cinepak_decode_frame( cinepak_context_t *p_context, i_strip, i_strip_x1 + i_x, i_strip_y1 + i_y, - i_strip_x2, i_strip_y2, p_data ); p_data++; i_chunk_size--; @@ -655,7 +663,6 @@ static int cinepak_decode_frame( cinepak_context_t *p_context, i_strip, i_strip_x1 + i_x, i_strip_y1 + i_y, - i_strip_x2, i_strip_y2, p_data ); p_data += 4; i_chunk_size -= 4; @@ -667,7 +674,6 @@ static int cinepak_decode_frame( cinepak_context_t *p_context, i_strip, i_strip_x1 + i_x, i_strip_y1 + i_y, - i_strip_x2, i_strip_y2, p_data ); p_data++; i_chunk_size--; @@ -693,7 +699,6 @@ static int cinepak_decode_frame( cinepak_context_t *p_context, i_strip, i_strip_x1 + i_x, i_strip_y1 + i_y, - i_strip_x2, i_strip_y2, p_data ); p_data++; i_chunk_size--;