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 $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)
......@@ -3311,7 +3311,6 @@ AC_OUTPUT([
modules/codec/a52old/Makefile
modules/codec/a52old/downmix/Makefile
modules/codec/a52old/imdct/Makefile
modules/codec/cinepak/Makefile
modules/codec/faad/Makefile
modules/codec/ffmpeg/Makefile
modules/codec/ffmpeg/postprocessing/Makefile
......
SOURCES_a52 = a52.c
SOURCES_cinepak = cinepak.c
SOURCES_dts = dts.c
SOURCES_flacdec = flacdec.c
SOURCES_lpcm = lpcm.c
......
......@@ -2,7 +2,7 @@
* cinepak.c: cinepak video decoder
*****************************************************************************
* 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>
*
......@@ -25,33 +25,68 @@
* Preamble
*****************************************************************************/
#include <stdlib.h> /* malloc(), free() */
#include <string.h>
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/decoder.h>
#include <vlc/input.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* getpid() */
#endif
#define CINEPAK_MAXSTRIP 32
#include <errno.h>
#include <string.h>
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;
#ifdef HAVE_SYS_TIMES_H
# include <sys/times.h>
#endif
int i_stride_x;
int i_stride_y;
#include "cinepak.h"
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;
/*****************************************************************************
* decoder_sys_t : decoder descriptor
*****************************************************************************/
struct decoder_sys_t
{
/*
* Cinepak properties
*/
cinepak_context_t *p_context;
/*
* Output properties
*/
vout_thread_t *p_vout;
};
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int OpenDecoder ( vlc_object_t * );
static int RunDecoder ( decoder_fifo_t * );
static int InitThread ( videodec_thread_t * );
static void EndThread ( videodec_thread_t * );
static void DecodeThread ( videodec_thread_t * );
static int OpenDecoder( vlc_object_t * );
static int InitDecoder( decoder_t * );
static int RunDecoder ( decoder_t *, block_t * );
static int EndDecoder ( decoder_t * );
static int cinepak_decode_frame( cinepak_context_t *, int, u8 * );
/*****************************************************************************
* Module descriptor
......@@ -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'):
p_dec->pf_run = RunDecoder;
return VLC_SUCCESS;
break;
default:
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;
int b_error;
decoder_sys_t *p_sys = p_dec->p_sys;
vlc_value_t val;
p_sys->p_vout = NULL;
if ( !(p_vdec = (videodec_thread_t*)malloc( sizeof(videodec_thread_t))) )
if( !(p_sys->p_context = malloc( sizeof( cinepak_context_t ) ) ) )
{
msg_Err( p_fifo, "out of memory" );
DecoderError( p_fifo );
return( -1 );
msg_Err( p_dec, "out of memory" );
}
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;
p_vdec->p_fifo = p_fifo;
msg_Dbg( p_dec, "cinepak decoder started" );
if( InitThread( p_vdec ) != 0 )
return VLC_SUCCESS;
}
/****************************************************************************
* 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;
i_status = cinepak_decode_frame( p_sys->p_context,
p_block->i_buffer, p_block->p_buffer );
if( i_status < 0 )
{
DecoderError( p_fifo );
return( -1 );
msg_Warn( p_dec, "cannot decode one frame (%d bytes)",
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 ) ) )
{
DecoderError( p_vdec->p_fifo );
if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
{
block_Release( p_block );
return VLC_EGENERIC;
}
msleep( VOUT_OUTMEM_SLEEP );
}
EndThread( p_vdec );
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];
if( b_error )
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++ )
{
return( -1 );
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];
}
}
return( 0 );
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 );
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 );
return VLC_SUCCESS;
}
/*****************************************************************************
* locales Functions
* local Functions
*****************************************************************************/
#define GET2BYTES( p ) \
......@@ -144,44 +271,8 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
#define FREE( p ) \
if( p ) free( p )
static void GetPESData( u8 *p_buf, int i_max, pes_packet_t *p_pes )
{
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 )
static 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_uv;
......@@ -227,11 +318,9 @@ void cinepak_LoadCodebook( cinepak_codebook_t *p_codebook,
#undef SCALEBITS
}
void cinepak_Getv4( cinepak_context_t *p_context,
int i_strip,
int i_x, int i_y,
int i_x2, int i_y2,
u8 *p_data )
static void cinepak_Getv4( cinepak_context_t *p_context,
int i_strip, int i_x, int i_y,
int i_x2, int i_y2, u8 *p_data )
{
u8 i_index[4];
int i,j;
......@@ -276,11 +365,9 @@ void cinepak_Getv4( cinepak_context_t *p_context,
#undef PIX_SET_UV
}
void cinepak_Getv1( cinepak_context_t *p_context,
int i_strip,
int i_x, int i_y,
int i_x2, int i_y2,
u8 *p_data )
static void cinepak_Getv1( cinepak_context_t *p_context,
int i_strip, int i_x, int i_y,
int i_x2, int i_y2, u8 *p_data )
{
u8 i_index;
int i,j;
......@@ -326,7 +413,7 @@ void cinepak_Getv1( cinepak_context_t *p_context,
/*****************************************************************************
* 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_strip;
......@@ -352,8 +439,14 @@ 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 )
{
/* Broken header */
return( -1 );
}
/* 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 ) )
{
int i;
......@@ -365,11 +458,11 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
p_context->i_width = i_width;
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[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[0] /2;
......@@ -395,7 +488,6 @@ 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;
......@@ -406,7 +498,6 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
break;
}
i_strip_id = GET2BYTES( p_data );
i_strip_size = GET2BYTES( p_data );
i_strip_size = __MIN( i_strip_size, i_length );
......@@ -497,15 +588,16 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
i_chunk_size -= 4;
for( i = 0; i < 32; i++ )
{
if( ( i_chunk_size < ( i_mode ? 6 : 4 ) )||(i_index >= 256 ))
if( ( i_chunk_size < ( i_mode ? 6 : 4 ) )
|| (i_index >= 256 ) )
{
break;
}
if( i_vector_flags&0x80000000UL )
{
cinepak_LoadCodebook( &((*p_codebook)[i_strip][i_index]),
p_data,
i_mode&~p_context->b_grayscale );
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;
......@@ -526,8 +618,8 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
for( i = 0; i < 32; i++ )
{
if( ( i_y >= i_strip_y2 - i_strip_y1)||
( i_chunk_size<=0) )
if( ( i_y >= i_strip_y2 - i_strip_y1) ||
( i_chunk_size<=0 ) )
{
break;
}
......@@ -573,9 +665,10 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
i_chunk_size -= 4;
i_mask = 0x80000000UL;
while((i_chunk_size > 0 )&&( i_mask )&&( i_y < i_strip_y2 - i_strip_y1 ))
while( (i_chunk_size > 0 ) && ( i_mask )
&& ( i_y < i_strip_y2 - i_strip_y1 ) )
{
if( i_vector_flags&i_mask)
if( i_vector_flags&i_mask )
{
i_mask >>= 1;
if( !i_mask )
......@@ -626,8 +719,8 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
break;
case( 0x3200 ): /* load intra picture but all v1*/
while( ( i_chunk_size > 0 )&&
( i_y < i_strip_y2 - i_strip_y1) )
while( ( i_chunk_size > 0 ) &&
( i_y < i_strip_y2 - i_strip_y1 ) )
{
cinepak_Getv1( p_context,
i_strip,
......@@ -644,193 +737,16 @@ int cinepak_decode_frame( cinepak_context_t *p_context,
i_x = 0;
i_y += 4;
}
}
break;
default:
break;
}
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 );
}
/*****************************************************************************
* 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