Commit 4f3ee7be authored by Gildas Bazin's avatar Gildas Bazin

* modules/codec/cinepak.c: ported the cinepak decoder to the new api.
parent 2f24327b
dnl Autoconf settings for vlc dnl Autoconf settings for vlc
dnl $Id: configure.ac,v 1.79 2003/10/01 22:19:57 gbazin Exp $ dnl $Id: configure.ac,v 1.80 2003/10/02 21:12:45 gbazin Exp $
AC_INIT(vlc,0.6.3-cvs) AC_INIT(vlc,0.6.3-cvs)
...@@ -3311,7 +3311,6 @@ AC_OUTPUT([ ...@@ -3311,7 +3311,6 @@ AC_OUTPUT([
modules/codec/a52old/Makefile modules/codec/a52old/Makefile
modules/codec/a52old/downmix/Makefile modules/codec/a52old/downmix/Makefile
modules/codec/a52old/imdct/Makefile modules/codec/a52old/imdct/Makefile
modules/codec/cinepak/Makefile
modules/codec/faad/Makefile modules/codec/faad/Makefile
modules/codec/ffmpeg/Makefile modules/codec/ffmpeg/Makefile
modules/codec/ffmpeg/postprocessing/Makefile modules/codec/ffmpeg/postprocessing/Makefile
......
SOURCES_a52 = a52.c SOURCES_a52 = a52.c
SOURCES_cinepak = cinepak.c
SOURCES_dts = dts.c SOURCES_dts = dts.c
SOURCES_flacdec = flacdec.c SOURCES_flacdec = flacdec.c
SOURCES_lpcm = lpcm.c SOURCES_lpcm = lpcm.c
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* cinepak.c: cinepak video decoder * cinepak.c: cinepak video decoder
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: cinepak.c,v 1.12 2003/09/02 20:19:25 gbazin Exp $ * $Id: cinepak.c,v 1.1 2003/10/02 21:12:45 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -25,33 +25,68 @@ ...@@ -25,33 +25,68 @@
* Preamble * Preamble
*****************************************************************************/ *****************************************************************************/
#include <stdlib.h> /* malloc(), free() */ #include <stdlib.h> /* malloc(), free() */
#include <string.h>
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/vout.h> #include <vlc/vout.h>
#include <vlc/decoder.h> #include <vlc/decoder.h>
#include <vlc/input.h> #include <vlc/input.h>
#ifdef HAVE_UNISTD_H #define CINEPAK_MAXSTRIP 32
#include <unistd.h> /* getpid() */
#endif
#include <errno.h> typedef struct cinepak_codebook_s
#include <string.h> {
u8 i_y[4];
u8 i_u, i_v;
} cinepak_codebook_t;
typedef struct cinepak_context_s
{
int b_grayscale; /* force to grayscale */
int i_width;
int i_height;
int i_stride_x;
int i_stride_y;
u8 *p_y, *p_u, *p_v;
#ifdef HAVE_SYS_TIMES_H int i_stride[3]; /* our 3 planes */
# include <sys/times.h> int i_lines[3];
#endif u8 *p_pix[3];
cinepak_codebook_t codebook_v1[CINEPAK_MAXSTRIP][256];
cinepak_codebook_t codebook_v4[CINEPAK_MAXSTRIP][256];
} cinepak_context_t;
/*****************************************************************************
* decoder_sys_t : decoder descriptor
*****************************************************************************/
struct decoder_sys_t
{
/*
* Cinepak properties
*/
cinepak_context_t *p_context;
#include "cinepak.h" /*
* Output properties
*/
vout_thread_t *p_vout;
};
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
static int OpenDecoder ( vlc_object_t * ); static int OpenDecoder( vlc_object_t * );
static int RunDecoder ( decoder_fifo_t * ); static int InitDecoder( decoder_t * );
static int InitThread ( videodec_thread_t * ); static int RunDecoder ( decoder_t *, block_t * );
static void EndThread ( videodec_thread_t * ); static int EndDecoder ( decoder_t * );
static void DecodeThread ( videodec_thread_t * );
static int cinepak_decode_frame( cinepak_context_t *, int, u8 * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -76,60 +111,152 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -76,60 +111,152 @@ static int OpenDecoder( vlc_object_t *p_this )
{ {
case VLC_FOURCC('c','v','i','d'): case VLC_FOURCC('c','v','i','d'):
case VLC_FOURCC('C','V','I','D'): case VLC_FOURCC('C','V','I','D'):
p_dec->pf_run = RunDecoder; break;
return VLC_SUCCESS;
default:
return VLC_EGENERIC;
} }
return VLC_EGENERIC; /* Allocate the memory needed to store the decoder's structure */
if( ( p_dec->p_sys =
(decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
{
msg_Err( p_dec, "out of memory" );
return VLC_EGENERIC;
}
p_dec->pf_init = InitDecoder;
p_dec->pf_decode = RunDecoder;
p_dec->pf_end = EndDecoder;
return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* RunDecoder: this function is called just after the thread is created * InitDecoder: Initalize the decoder
*****************************************************************************/ *****************************************************************************/
static int RunDecoder( decoder_fifo_t *p_fifo ) static int InitDecoder( decoder_t *p_dec )
{ {
videodec_thread_t *p_vdec; decoder_sys_t *p_sys = p_dec->p_sys;
int b_error; vlc_value_t val;
if ( !(p_vdec = (videodec_thread_t*)malloc( sizeof(videodec_thread_t))) ) p_sys->p_vout = NULL;
if( !(p_sys->p_context = malloc( sizeof( cinepak_context_t ) ) ) )
{ {
msg_Err( p_fifo, "out of memory" ); msg_Err( p_dec, "out of memory" );
DecoderError( p_fifo );
return( -1 );
} }
memset( p_vdec, 0, sizeof( videodec_thread_t ) ); memset( p_sys->p_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;
msg_Dbg( p_dec, "cinepak decoder started" );
return VLC_SUCCESS;
}
p_vdec->p_fifo = p_fifo; /****************************************************************************
* RunDecoder: the whole thing
****************************************************************************
* This function must be fed with whole frames.
****************************************************************************/
static int RunDecoder( decoder_t *p_dec, block_t *p_block )
{
decoder_sys_t *p_sys = p_dec->p_sys;
int i_status, i_plane;
u8 *p_dst, *p_src;
picture_t *p_pic;
if( InitThread( p_vdec ) != 0 ) i_status = cinepak_decode_frame( p_sys->p_context,
p_block->i_buffer, p_block->p_buffer );
if( i_status < 0 )
{ {
DecoderError( p_fifo ); msg_Warn( p_dec, "cannot decode one frame (%d bytes)",
return( -1 ); p_block->i_buffer );
block_Release( p_block );
return VLC_SUCCESS;
} }
while( (!p_vdec->p_fifo->b_die) && (!p_vdec->p_fifo->b_error) ) /* Check our vout */
p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout,
p_sys->p_context->i_width,
p_sys->p_context->i_height,
VLC_FOURCC('I','4','2','0'),
p_sys->p_context->i_width
* VOUT_ASPECT_FACTOR
/ p_sys->p_context->i_height );
if( !p_sys->p_vout )
{ {
DecodeThread( p_vdec ); msg_Err( p_dec, "cannot create vout" );
block_Release( p_block );
return VLC_EGENERIC;
} }
if( ( b_error = p_vdec->p_fifo->b_error ) ) /* Send decoded frame to vout */
while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
{
if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
{
block_Release( p_block );
return VLC_EGENERIC;
}
msleep( VOUT_OUTMEM_SLEEP );
}
for( i_plane = 0; i_plane < 3; i_plane++ )
{ {
DecoderError( p_vdec->p_fifo ); int i_line, i_lines;
p_dst = p_pic->p[i_plane].p_pixels;
p_src = p_sys->p_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];
}
} }
EndThread( p_vdec ); vout_DatePicture( p_sys->p_vout, p_pic, p_block->i_pts);
vout_DisplayPicture( p_sys->p_vout, p_pic );
block_Release( p_block );
return VLC_SUCCESS;
}
/*****************************************************************************
* EndDecoder: theora decoder destruction
*****************************************************************************/
static int EndDecoder( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
int i;
msg_Dbg( p_dec, "cinepak decoder stopped" );
vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 );
if( b_error ) for( i = 0; i < 3; i++ )
{ {
return( -1 ); if( p_sys->p_context->p_pix[i] ) free( p_sys->p_context->p_pix[i] );
} }
return( 0 );
}
free( p_sys->p_context );
free( p_sys );
return VLC_SUCCESS;
}
/***************************************************************************** /*****************************************************************************
* locales Functions * local Functions
*****************************************************************************/ *****************************************************************************/
#define GET2BYTES( p ) \ #define GET2BYTES( p ) \
...@@ -144,44 +271,8 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) ...@@ -144,44 +271,8 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
#define FREE( p ) \ #define FREE( p ) \
if( p ) free( p ) if( p ) free( p )
static void cinepak_LoadCodebook( cinepak_codebook_t *p_codebook,
static void GetPESData( u8 *p_buf, int i_max, pes_packet_t *p_pes ) u8 *p_data, int b_grayscale )
{
int i_copy;
int i_count;
data_packet_t *p_data;
i_count = 0;
p_data = p_pes->p_first;
while( p_data != NULL && i_count < i_max )
{
i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
i_max - i_count );
if( i_copy > 0 )
{
memcpy( p_buf,
p_data->p_payload_start,
i_copy );
}
p_data = p_data->p_next;
i_count += i_copy;
p_buf += i_copy;
}
if( i_count < i_max )
{
memset( p_buf, 0, i_max - i_count );
}
}
void cinepak_LoadCodebook( cinepak_codebook_t *p_codebook,
u8 *p_data,
int b_grayscale )
{ {
int i, i_y[4], i_u, i_v, i_Cb, i_Cr; int i, i_y[4], i_u, i_v, i_Cb, i_Cr;
int i_uv; int i_uv;
...@@ -202,7 +293,7 @@ void cinepak_LoadCodebook( cinepak_codebook_t *p_codebook, ...@@ -202,7 +293,7 @@ void cinepak_LoadCodebook( cinepak_codebook_t *p_codebook,
i_u = 0; i_u = 0;
i_v = 0; i_v = 0;
} }
/* /*
| Y | | 1 -0.0655 0.0110 | | CY | | Y | | 1 -0.0655 0.0110 | | CY |
| Cb | = | 0 1.1656 -0.0062 | | CU | | Cb | = | 0 1.1656 -0.0062 | | CU |
...@@ -215,34 +306,32 @@ void cinepak_LoadCodebook( cinepak_codebook_t *p_codebook, ...@@ -215,34 +306,32 @@ void cinepak_LoadCodebook( cinepak_codebook_t *p_codebook,
} }
i_Cb = ( FIX( 1.1656 ) * i_u + FIX( -0.0062 ) * i_v ) >> SCALEBITS; i_Cb = ( FIX( 1.1656 ) * i_u + FIX( -0.0062 ) * i_v ) >> SCALEBITS;
i_Cr = ( FIX( 0.0467 ) * i_u + FIX( 1.4187 ) * i_v ) >> SCALEBITS; i_Cr = ( FIX( 0.0467 ) * i_u + FIX( 1.4187 ) * i_v ) >> SCALEBITS;
for( i = 0; i < 4; i++ ) for( i = 0; i < 4; i++ )
{ {
p_codebook->i_y[i] = __MIN( __MAX( 0, i_y[i] ), 255 ); p_codebook->i_y[i] = __MIN( __MAX( 0, i_y[i] ), 255 );
} }
p_codebook->i_u = __MIN( __MAX( 0, i_Cb + 128 ), 255 ); p_codebook->i_u = __MIN( __MAX( 0, i_Cb + 128 ), 255 );
p_codebook->i_v = __MIN( __MAX( 0, i_Cr + 128 ), 255 ); p_codebook->i_v = __MIN( __MAX( 0, i_Cr + 128 ), 255 );
#undef FIX #undef FIX
#undef SCALEBITS #undef SCALEBITS
} }
void cinepak_Getv4( cinepak_context_t *p_context, static void cinepak_Getv4( cinepak_context_t *p_context,
int i_strip, int i_strip, int i_x, int i_y,
int i_x, int i_y, int i_x2, int i_y2, u8 *p_data )
int i_x2, int i_y2,
u8 *p_data )
{ {
u8 i_index[4]; u8 i_index[4];
int i,j; int i,j;
u8 *p_dst_y, *p_dst_u, *p_dst_v; u8 *p_dst_y, *p_dst_u, *p_dst_v;
#define PIX_SET_Y( x, y, v ) \ #define PIX_SET_Y( x, y, v ) \
p_dst_y[(x) + (y)* p_context->i_stride[0]] = (v); p_dst_y[(x) + (y)* p_context->i_stride[0]] = (v);
#define PIX_SET_UV( i, p, x, y, v ) \ #define PIX_SET_UV( i, p, x, y, v ) \
p[(x) + (y)* (p_context->i_stride[i])] = (v); p[(x) + (y)* (p_context->i_stride[i])] = (v);
for( i = 0; i < 4; i++ ) for( i = 0; i < 4; i++ )
{ {
i_index[i] = *(p_data++); i_index[i] = *(p_data++);
...@@ -252,7 +341,7 @@ void cinepak_Getv4( cinepak_context_t *p_context, ...@@ -252,7 +341,7 @@ void cinepak_Getv4( cinepak_context_t *p_context,
p_dst_y = p_context->p_pix[0] + p_context->i_stride[0] * i_y + i_x; p_dst_y = p_context->p_pix[0] + p_context->i_stride[0] * i_y + i_x;
p_dst_u = p_context->p_pix[1] + p_context->i_stride[1] * (i_y/2) + (i_x/2); p_dst_u = p_context->p_pix[1] + p_context->i_stride[1] * (i_y/2) + (i_x/2);
p_dst_v = p_context->p_pix[2] + p_context->i_stride[2] * (i_y/2) + (i_x/2); p_dst_v = p_context->p_pix[2] + p_context->i_stride[2] * (i_y/2) + (i_x/2);
for( i = 0; i < 2; i++ ) for( i = 0; i < 2; i++ )
{ {
for( j = 0; j < 2; j ++ ) for( j = 0; j < 2; j ++ )
...@@ -276,22 +365,20 @@ void cinepak_Getv4( cinepak_context_t *p_context, ...@@ -276,22 +365,20 @@ void cinepak_Getv4( cinepak_context_t *p_context,
#undef PIX_SET_UV #undef PIX_SET_UV
} }
void cinepak_Getv1( cinepak_context_t *p_context, static void cinepak_Getv1( cinepak_context_t *p_context,
int i_strip, int i_strip, int i_x, int i_y,
int i_x, int i_y, int i_x2, int i_y2, u8 *p_data )
int i_x2, int i_y2,
u8 *p_data )
{ {
u8 i_index; u8 i_index;
int i,j; int i,j;
u8 *p_dst_y, *p_dst_u, *p_dst_v; u8 *p_dst_y, *p_dst_u, *p_dst_v;
#define PIX_SET_Y( x, y, v ) \ #define PIX_SET_Y( x, y, v ) \
p_dst_y[(x) + (y)* p_context->i_stride[0]] = (v); p_dst_y[(x) + (y)* p_context->i_stride[0]] = (v);
#define PIX_SET_UV( i,p, x, y, v ) \ #define PIX_SET_UV( i,p, x, y, v ) \
p[(x) + (y)* (p_context->i_stride[i])] = (v); p[(x) + (y)* (p_context->i_stride[i])] = (v);
i_index = *(p_data++); i_index = *(p_data++);
/* y plane */ /* y plane */
...@@ -326,8 +413,8 @@ void cinepak_Getv1( cinepak_context_t *p_context, ...@@ -326,8 +413,8 @@ void cinepak_Getv1( cinepak_context_t *p_context,
/***************************************************************************** /*****************************************************************************
* The function that decode one frame * The function that decode one frame
*****************************************************************************/ *****************************************************************************/
int cinepak_decode_frame( cinepak_context_t *p_context, static int cinepak_decode_frame( cinepak_context_t *p_context,
int i_length, u8 *p_data ) int i_length, u8 *p_data )
{ {
int i_strip; int i_strip;
...@@ -338,22 +425,28 @@ int cinepak_decode_frame( cinepak_context_t *p_context, ...@@ -338,22 +425,28 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
int i_index; int i_index;
int i_strip_x1 =0, i_strip_y1=0; int i_strip_x1 =0, i_strip_y1=0;
int i_strip_x2 =0, i_strip_y2=0; int i_strip_x2 =0, i_strip_y2=0;
if( i_length <= 10 ) if( i_length <= 10 )
{ {
/* Broken header or no data */ /* Broken header or no data */
return( -1 ); return( -1 );
} }
/* get header */ /* get header */
i_frame_flags = *(p_data++); i_frame_flags = *(p_data++);
i_frame_size = GET3BYTES( p_data ); i_frame_size = GET3BYTES( p_data );
i_width = GET2BYTES( p_data ); i_width = GET2BYTES( p_data );
i_height = GET2BYTES( p_data ); i_height = GET2BYTES( p_data );
i_frame_strips = GET2BYTES( p_data ); i_frame_strips = GET2BYTES( p_data );
if( !i_frame_size || !i_width || !i_height )
{
/* Broken header */
return( -1 );
}
/* Check if we have a picture buffer with good size */ /* Check if we have a picture buffer with good size */
if( ( p_context->i_width != i_width )|| if( ( p_context->i_width != i_width ) ||
( p_context->i_height != i_height ) ) ( p_context->i_height != i_height ) )
{ {
int i; int i;
...@@ -365,14 +458,14 @@ int cinepak_decode_frame( cinepak_context_t *p_context, ...@@ -365,14 +458,14 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
p_context->i_width = i_width; p_context->i_width = i_width;
p_context->i_height = i_height; p_context->i_height = i_height;
p_context->i_stride[0] = ( i_width + 3)&0xfffc; p_context->i_stride[0] = ( i_width + 3 ) & 0xfffc;
p_context->i_stride[1] = p_context->i_stride[2] = p_context->i_stride[1] = p_context->i_stride[2] =
p_context->i_stride[0] / 2; p_context->i_stride[0] / 2;
p_context->i_lines[0] = ( i_height + 3 )&0xfffc; p_context->i_lines[0] = ( i_height + 3 ) & 0xfffc;
p_context->i_lines[1] = p_context->i_lines[2] = p_context->i_lines[1] = p_context->i_lines[2] =
p_context->i_lines[0] /2; p_context->i_lines[0] /2;
for( i = 0; i < 3; i++ ) for( i = 0; i < 3; i++ )
{ {
p_context->p_pix[i] = malloc( p_context->i_stride[i] * p_context->p_pix[i] = malloc( p_context->i_stride[i] *
...@@ -395,7 +488,6 @@ int cinepak_decode_frame( cinepak_context_t *p_context, ...@@ -395,7 +488,6 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
} }
/* Now decode each strip */ /* Now decode each strip */
for( i_strip = 0; i_strip < i_frame_strips; i_strip++ ) for( i_strip = 0; i_strip < i_frame_strips; i_strip++ )
{ {
int i_strip_id; int i_strip_id;
...@@ -405,8 +497,7 @@ int cinepak_decode_frame( cinepak_context_t *p_context, ...@@ -405,8 +497,7 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
{ {
break; break;
} }
i_strip_id = GET2BYTES( p_data ); i_strip_id = GET2BYTES( p_data );
i_strip_size = GET2BYTES( p_data ); i_strip_size = GET2BYTES( p_data );
i_strip_size = __MIN( i_strip_size, i_length ); i_strip_size = __MIN( i_strip_size, i_length );
...@@ -448,7 +539,7 @@ int cinepak_decode_frame( cinepak_context_t *p_context, ...@@ -448,7 +539,7 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
i_chunk_size = GET2BYTES( p_data ); i_chunk_size = GET2BYTES( p_data );
i_chunk_size = __MIN( i_chunk_size, i_strip_size ); i_chunk_size = __MIN( i_chunk_size, i_strip_size );
i_strip_size -= i_chunk_size; i_strip_size -= i_chunk_size;
i_chunk_size -= 4; i_chunk_size -= 4;
i_x = 0; i_x = 0;
...@@ -457,82 +548,142 @@ int cinepak_decode_frame( cinepak_context_t *p_context, ...@@ -457,82 +548,142 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
{ {
break; break;
} }
switch( i_chunk_id ) switch( i_chunk_id )
{ {
case( 0x2000 ): /* 12bits v4 Intra*/ case( 0x2000 ): /* 12bits v4 Intra*/
case( 0x2200 ): /* 12bits v1 Intra*/ case( 0x2200 ): /* 12bits v1 Intra*/
case( 0x2400 ): /* 8bits v4 Intra*/ case( 0x2400 ): /* 8bits v4 Intra*/
case( 0x2600 ): /* 8bits v1 Intra */ case( 0x2600 ): /* 8bits v1 Intra */
i_mode = ( ( i_chunk_id&0x0400 ) == 0 ); i_mode = ( ( i_chunk_id&0x0400 ) == 0 );
p_codebook = ( i_chunk_id&0x0200 ) ? p_codebook = ( i_chunk_id&0x0200 ) ?
&p_context->codebook_v1 : &p_context->codebook_v1 :
&p_context->codebook_v4; &p_context->codebook_v4;
i_count = __MIN( i_chunk_size / ( i_mode ? 6 : 4 ), 256 ); i_count = __MIN( i_chunk_size / ( i_mode ? 6 : 4 ), 256 );
for( i = 0; i < i_count; i++ ) for( i = 0; i < i_count; i++ )
{
cinepak_LoadCodebook( &((*p_codebook)[i_strip][i]),
p_data,
i_mode&~p_context->b_grayscale );
p_data += i_mode ? 6 : 4;
i_chunk_size -= i_mode ? 6 : 4;
}
break;
case( 0x2100 ): /* selective 12bits v4 Inter*/
case( 0x2300 ): /* selective 12bits v1 Inter*/
case( 0x2500 ): /* selective 8bits v4 Inter*/
case( 0x2700 ): /* selective 8bits v1 Inter*/
i_mode = ( ( i_chunk_id&0x0400 ) == 0 );
p_codebook = ( i_chunk_id&0x0200 ) ?
&p_context->codebook_v1 :
&p_context->codebook_v4;
i_index = 0;
while( (i_chunk_size > 4)&&(i_index<256))
{
i_vector_flags = GET4BYTES( p_data );
i_chunk_size -= 4;
for( i = 0; i < 32; i++ )
{ {
cinepak_LoadCodebook( &((*p_codebook)[i_strip][i]), if( ( i_chunk_size < ( i_mode ? 6 : 4 ) )
p_data, || (i_index >= 256 ) )
i_mode&~p_context->b_grayscale ); {
p_data += i_mode ? 6 : 4; break;
i_chunk_size -= i_mode ? 6 : 4; }
if( i_vector_flags&0x80000000UL )
{
cinepak_LoadCodebook(
&((*p_codebook)[i_strip][i_index]),
p_data, i_mode&~p_context->b_grayscale );
p_data += i_mode ? 6 : 4;
i_chunk_size -= i_mode ? 6 : 4;
}
i_index++;
i_vector_flags <<= 1;
} }
break; }
break;
case( 0x2100 ): /* selective 12bits v4 Inter*/
case( 0x2300 ): /* selective 12bits v1 Inter*/ case( 0x3000 ): /* load image Intra */
case( 0x2500 ): /* selective 8bits v4 Inter*/ while( (i_chunk_size >= 4 )&&(i_y<i_strip_y2-i_strip_y1) )
case( 0x2700 ): /* selective 8bits v1 Inter*/ {
i_mode = ( ( i_chunk_id&0x0400 ) == 0 ); i_vector_flags = GET4BYTES( p_data );
p_codebook = ( i_chunk_id&0x0200 ) ? i_chunk_size -= 4;
&p_context->codebook_v1 : i_strip_size -= 4;
&p_context->codebook_v4; i_length -= 4;
i_index = 0; for( i = 0; i < 32; i++ )
while( (i_chunk_size > 4)&&(i_index<256))
{ {
i_vector_flags = GET4BYTES( p_data ); if( ( i_y >= i_strip_y2 - i_strip_y1) ||
i_chunk_size -= 4; ( i_chunk_size<=0 ) )
for( i = 0; i < 32; i++ )
{ {
if( ( i_chunk_size < ( i_mode ? 6 : 4 ) )||(i_index >= 256 )) break;
{ }
break; if( i_vector_flags&0x80000000UL )
} {
if( i_vector_flags&0x80000000UL ) cinepak_Getv4( p_context,
{ i_strip,
cinepak_LoadCodebook( &((*p_codebook)[i_strip][i_index]), i_strip_x1 + i_x,
p_data, i_strip_y1 + i_y,
i_mode&~p_context->b_grayscale ); i_strip_x2, i_strip_y2,
p_data );
p_data += 4;
i_chunk_size -= 4;
}
else
{
cinepak_Getv1( 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--;
}
p_data += i_mode ? 6 : 4; i_x += 4;
i_chunk_size -= i_mode ? 6 : 4; if( i_x >= i_strip_x2 - i_strip_x1 )
} {
i_index++; i_x = 0;
i_vector_flags <<= 1; i_y += 4;
} }
i_vector_flags <<= 1;
} }
break; }
break;
case( 0x3000 ): /* load image Intra */ case( 0x3100 ): /* load image Inter */
while( (i_chunk_size >= 4 )&&(i_y<i_strip_y2-i_strip_y1) ) while( ( i_chunk_size > 4 )&&( i_y < i_strip_y2 - i_strip_y1) )
{ {
i_vector_flags = GET4BYTES( p_data ); u32 i_mask;
i_chunk_size -= 4; i_vector_flags = GET4BYTES( p_data );
i_strip_size -= 4; i_chunk_size -= 4;
i_length -= 4; i_mask = 0x80000000UL;
for( i = 0; i < 32; i++ ) while( (i_chunk_size > 0 ) && ( i_mask )
&& ( i_y < i_strip_y2 - i_strip_y1 ) )
{
if( i_vector_flags&i_mask )
{ {
if( ( i_y >= i_strip_y2 - i_strip_y1)|| i_mask >>= 1;
( i_chunk_size<=0) ) if( !i_mask )
{ {
break; if( i_chunk_size < 4 )
{
break;
}
i_vector_flags = GET4BYTES( p_data );
i_chunk_size -= 4;
i_mask = 0x80000000UL;
} }
if( i_vector_flags&0x80000000UL ) if( i_vector_flags&i_mask )
{ {
if( i_chunk_size < 4 ) break;
cinepak_Getv4( p_context, cinepak_Getv4( p_context,
i_strip, i_strip,
i_strip_x1 + i_x, i_strip_x1 + i_x,
...@@ -544,6 +695,7 @@ int cinepak_decode_frame( cinepak_context_t *p_context, ...@@ -544,6 +695,7 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
} }
else else
{ {
if( i_chunk_size < 1 ) break;
cinepak_Getv1( p_context, cinepak_Getv1( p_context,
i_strip, i_strip,
i_strip_x1 + i_x, i_strip_x1 + i_x,
...@@ -553,90 +705,8 @@ int cinepak_decode_frame( cinepak_context_t *p_context, ...@@ -553,90 +705,8 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
p_data++; p_data++;
i_chunk_size--; i_chunk_size--;
} }
i_x += 4;
if( i_x >= i_strip_x2 - i_strip_x1 )
{
i_x = 0;
i_y += 4;
}
i_vector_flags <<= 1;
} }
} i_mask >>= 1;
break;
case( 0x3100 ): /* load image Inter */
while( ( i_chunk_size > 4 )&&( i_y < i_strip_y2 - i_strip_y1) )
{
u32 i_mask;
i_vector_flags = GET4BYTES( p_data );
i_chunk_size -= 4;
i_mask = 0x80000000UL;
while((i_chunk_size > 0 )&&( i_mask )&&( i_y < i_strip_y2 - i_strip_y1 ))
{
if( i_vector_flags&i_mask)
{
i_mask >>= 1;
if( !i_mask )
{
if( i_chunk_size < 4 )
{
break;
}
i_vector_flags = GET4BYTES( p_data );
i_chunk_size -= 4;
i_mask = 0x80000000UL;
}
if( i_vector_flags&i_mask )
{
if( i_chunk_size < 4 ) break;
cinepak_Getv4( 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;
}
else
{
if( i_chunk_size < 1 ) break;
cinepak_Getv1( 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--;
}
}
i_mask >>= 1;
i_x += 4;
if( i_x >= i_strip_x2 - i_strip_x1 )
{
i_x = 0;
i_y += 4;
}
}
}
break;
case( 0x3200 ): /* load intra picture but all v1*/
while( ( i_chunk_size > 0 )&&
( i_y < i_strip_y2 - i_strip_y1) )
{
cinepak_Getv1( 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--;
i_x += 4; i_x += 4;
if( i_x >= i_strip_x2 - i_strip_x1 ) if( i_x >= i_strip_x2 - i_strip_x1 )
...@@ -644,193 +714,39 @@ int cinepak_decode_frame( cinepak_context_t *p_context, ...@@ -644,193 +714,39 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
i_x = 0; i_x = 0;
i_y += 4; i_y += 4;
} }
}
} }
break; break;
case( 0x3200 ): /* load intra picture but all v1*/
while( ( i_chunk_size > 0 ) &&
( i_y < i_strip_y2 - i_strip_y1 ) )
{
cinepak_Getv1( 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--;
i_x += 4;
if( i_x >= i_strip_x2 - i_strip_x1 )
{
i_x = 0;
i_y += 4;
}
}
break;
default: default:
break; break;
} }
p_data += i_chunk_size ; /* skip remains bytes */ p_data += i_chunk_size ; /* skip remains bytes */
} }
} }
return( 0 );
}
/*****************************************************************************
*
* Functions that initialize, decode and end the decoding process
*
*****************************************************************************/
/*****************************************************************************
* InitThread: initialize vdec output thread
*****************************************************************************
* This function is called from decoder_Run and performs the second step
* of the initialization. It returns 0 on success. Note that the thread's
* flag are not modified inside this function.
*****************************************************************************/
static int InitThread( videodec_thread_t *p_vdec )
{
/* This will be created after the first decoded frame */
if( !(p_vdec->p_context = malloc( sizeof( cinepak_context_t ) ) ) )
{
msg_Err( p_vdec->p_fifo, "out of memory" );
}
memset( p_vdec->p_context, 0, sizeof( cinepak_context_t ) );
if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
{
p_vdec->p_context->b_grayscale = 1;
}
else
{
p_vdec->p_context->b_grayscale = 0;
}
p_vdec->p_vout = NULL;
msg_Dbg( p_vdec->p_fifo, "cinepak decoder started" );
return( 0 ); return( 0 );
} }
/*****************************************************************************
* DecodeThread: Called for decode one frame
*****************************************************************************/
static void DecodeThread( videodec_thread_t *p_vdec )
{
pes_packet_t *p_pes;
int i_frame_size;
int i_status;
int i_plane;
u8 *p_dst, *p_src;
picture_t *p_pic; /* videolan picture */
do
{
input_ExtractPES( p_vdec->p_fifo, &p_pes );
if( !p_pes )
{
p_vdec->p_fifo->b_error = 1;
return;
}
p_vdec->i_pts = p_pes->i_pts;
i_frame_size = p_pes->i_pes_size;
if( i_frame_size > 0 )
{
if( p_vdec->i_buffer < i_frame_size + 16 )
{
FREE( p_vdec->p_buffer );
p_vdec->p_buffer = malloc( i_frame_size + 16 );
p_vdec->i_buffer = i_frame_size + 16;
}
GetPESData( p_vdec->p_buffer, p_vdec->i_buffer, p_pes );
}
input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
} while( i_frame_size <= 0 );
i_status = cinepak_decode_frame( p_vdec->p_context,
i_frame_size,
p_vdec->p_buffer );
if( i_status < 0 )
{
msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
i_frame_size );
return;
}
/* Check our vout */
p_vdec->p_vout = vout_Request( p_vdec->p_fifo, p_vdec->p_vout,
p_vdec->p_context->i_width,
p_vdec->p_context->i_height,
VLC_FOURCC('I','4','2','0'),
p_vdec->p_context->i_width
* VOUT_ASPECT_FACTOR
/ p_vdec->p_context->i_height );
if( !p_vdec->p_vout )
{
msg_Err( p_vdec->p_fifo, "cannot create vout" );
p_vdec->p_fifo->b_error = VLC_TRUE; /* abort */
return;
}
/* Send decoded frame to vout */
while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
{
if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
{
return;
}
msleep( VOUT_OUTMEM_SLEEP );
}
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_vdec->p_context->p_pix[i_plane];
i_lines = __MIN( p_vdec->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_vdec->p_context->i_stride[i_plane] ) );
p_dst += p_pic->p[i_plane].i_pitch;
p_src += p_vdec->p_context->i_stride[i_plane];
}
}
vout_DatePicture( p_vdec->p_vout, p_pic, p_vdec->i_pts);
vout_DisplayPicture( p_vdec->p_vout, p_pic );
return;
}
/*****************************************************************************
* EndThread: thread destruction
*****************************************************************************
* This function is called when the thread ends after a sucessful
* initialization.
*****************************************************************************/
static void EndThread( videodec_thread_t *p_vdec )
{
int i;
if( !p_vdec )
{
return;
}
msg_Dbg( p_vdec->p_fifo, "cinepak decoder stopped" );
for( i = 0; i < 3; i++ )
{
FREE( p_vdec->p_context->p_pix[i] );
}
free( p_vdec->p_context );
/* Get rid of our video output if we have one. */
vout_Request( p_vdec->p_fifo, p_vdec->p_vout, 0, 0, 0, 0 );
free( p_vdec );
}
.deps
.dirstamp
*.lo
*.la
*.dll
*.dylib
*.sl
*.so
Makefile.am
Makefile.in
Makefile
SOURCES_cinepak = \
cinepak.c \
cinepak.h \
$(NULL)
/*****************************************************************************
* cinepak.h: Cinepak video decoder
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: cinepak.h,v 1.2 2002/11/27 13:17:27 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* 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.
*****************************************************************************/
#define CINEPAK_MAXSTRIP 32
typedef struct cinepak_codebook_s
{
u8 i_y[4];
u8 i_u, i_v;
} cinepak_codebook_t;
typedef struct cinepak_context_s
{
int b_grayscale; /* force to grayscale */
int i_width;
int i_height;
int i_stride_x;
int i_stride_y;
u8 *p_y, *p_u, *p_v;
int i_stride[3]; /* our 3 planes */
int i_lines[3];
u8 *p_pix[3];
cinepak_codebook_t codebook_v1[CINEPAK_MAXSTRIP][256];
cinepak_codebook_t codebook_v4[CINEPAK_MAXSTRIP][256];
} cinepak_context_t;
typedef struct videodec_thread_s
{
decoder_fifo_t *p_fifo;
vout_thread_t *p_vout;
cinepak_context_t *p_context;
/* private */
mtime_t i_pts;
u8 *p_buffer; /* buffer for gather pes */ \
int i_buffer; /* size of allocated p_framedata */
// int i_framesize;
// byte_t *p_framedata;
} videodec_thread_t;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment