mirror of https://code.videolan.org/videolan/vlc
* Removed the plugins/ directory.
This commit is contained in:
parent
a46b30014c
commit
7ba73a88cb
|
@ -1,5 +0,0 @@
|
|||
*.a
|
||||
*.so
|
||||
*.so.*
|
||||
*.tds
|
||||
*.lib
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1 +0,0 @@
|
|||
a52_SOURCES = a52.c
|
|
@ -1,386 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* a52.c: ATSC A/52 aka AC-3 decoder plugin for vlc.
|
||||
* This plugin makes use of liba52 to decode A/52 audio
|
||||
* (http://liba52.sf.net/).
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: a52.c,v 1.22 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Gildas Bazin <gbazin@netcourrier.com>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/aout.h>
|
||||
#include <vlc/decoder.h>
|
||||
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
#include <string.h> /* strdup() */
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h> /* int16_t .. */
|
||||
#elif HAVE_INTTYPES_H
|
||||
# include <inttypes.h> /* int16_t .. */
|
||||
#endif
|
||||
|
||||
#ifdef USE_A52DEC_TREE /* liba52 header file */
|
||||
# include "include/a52.h"
|
||||
#else
|
||||
# include "a52dec/a52.h"
|
||||
#endif
|
||||
|
||||
#include "a52.h"
|
||||
|
||||
#define AC3DEC_FRAME_SIZE 1536
|
||||
|
||||
/*
|
||||
* Global lock for accessing liba52 functions.
|
||||
* Currently, liba52 isn't thread-safe. So to prevent two threads from
|
||||
* using liba52 at the same time, we have to set up a global lock.
|
||||
* I know static variables aren't a good idea in multi-threaded programs,
|
||||
* but believe me, this is the way to go.
|
||||
* --Meuuh 2002-07-19
|
||||
*/
|
||||
static vlc_mutex_t a52_lock;
|
||||
static vlc_bool_t b_liba52_initialized = 0;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int OpenDecoder ( vlc_object_t * );
|
||||
static int RunDecoder ( decoder_fifo_t * );
|
||||
static int DecodeFrame ( a52_adec_thread_t * );
|
||||
static int InitThread ( a52_adec_thread_t * );
|
||||
static void EndThread ( a52_adec_thread_t * );
|
||||
|
||||
static void BitstreamCallback ( bit_stream_t *, vlc_bool_t );
|
||||
static void float2s16_2 ( float *, int16_t * );
|
||||
static inline int16_t convert ( int32_t );
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
#define DYNRNG_TEXT N_("A/52 dynamic range compression")
|
||||
#define DYNRNG_LONGTEXT N_( \
|
||||
"Dynamic range compression makes the loud sounds softer, and the soft " \
|
||||
"sounds louder, so you can more easily listen to the stream in a noisy " \
|
||||
"environment without disturbing anyone. If you disable the dynamic range "\
|
||||
"compression the playback will be more adapted to a movie theater or a " \
|
||||
"listening room.")
|
||||
|
||||
vlc_module_begin();
|
||||
add_category_hint( N_("Miscellaneous"), NULL );
|
||||
add_bool( "a52-dynrng", 1, NULL, DYNRNG_TEXT, DYNRNG_LONGTEXT );
|
||||
set_description( _("a52 ATSC A/52 aka AC-3 audio decoder module") );
|
||||
set_capability( "decoder", 60 );
|
||||
set_callbacks( OpenDecoder, NULL );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* OpenDecoder: probe the decoder and return score
|
||||
*****************************************************************************
|
||||
* Tries to launch a decoder and return score so that the interface is able
|
||||
* to choose.
|
||||
*****************************************************************************/
|
||||
static int OpenDecoder( vlc_object_t *p_this )
|
||||
{
|
||||
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
|
||||
|
||||
if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') )
|
||||
{
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
p_fifo->pf_run = RunDecoder;
|
||||
return VLC_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* RunDecoder: this function is called just after the thread is created
|
||||
*****************************************************************************/
|
||||
static int RunDecoder( decoder_fifo_t *p_fifo )
|
||||
{
|
||||
a52_adec_thread_t *p_a52_adec;
|
||||
|
||||
/* Allocate the memory needed to store the thread's structure */
|
||||
p_a52_adec = (a52_adec_thread_t *)malloc( sizeof(a52_adec_thread_t) );
|
||||
if (p_a52_adec == NULL)
|
||||
{
|
||||
msg_Err( p_fifo, "out of memory" );
|
||||
DecoderError( p_fifo );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* FIXME */
|
||||
p_a52_adec->i_channels = 2;
|
||||
|
||||
/*
|
||||
* Initialize the thread properties
|
||||
*/
|
||||
p_a52_adec->p_aout_fifo = NULL;
|
||||
p_a52_adec->p_fifo = p_fifo;
|
||||
|
||||
if( InitThread( p_a52_adec ) )
|
||||
{
|
||||
msg_Err( p_a52_adec->p_fifo, "could not initialize thread" );
|
||||
DecoderError( p_fifo );
|
||||
free( p_a52_adec );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* liba52 decoder thread's main loop */
|
||||
while( !p_a52_adec->p_fifo->b_die && !p_a52_adec->p_fifo->b_error )
|
||||
{
|
||||
|
||||
/* look for sync word - should be 0x0b77 */
|
||||
RealignBits(&p_a52_adec->bit_stream);
|
||||
while( (ShowBits( &p_a52_adec->bit_stream, 16 ) ) != 0x0b77 &&
|
||||
(!p_a52_adec->p_fifo->b_die) && (!p_a52_adec->p_fifo->b_error))
|
||||
{
|
||||
RemoveBits( &p_a52_adec->bit_stream, 8 );
|
||||
}
|
||||
|
||||
/* get a52 frame header */
|
||||
GetChunk( &p_a52_adec->bit_stream, p_a52_adec->p_frame_buffer, 7 );
|
||||
if( p_a52_adec->p_fifo->b_die ) break;
|
||||
|
||||
/* check if frame is valid and get frame info */
|
||||
vlc_mutex_lock( &a52_lock );
|
||||
p_a52_adec->frame_size = a52_syncinfo( p_a52_adec->p_frame_buffer,
|
||||
&p_a52_adec->flags,
|
||||
&p_a52_adec->sample_rate,
|
||||
&p_a52_adec->bit_rate );
|
||||
vlc_mutex_unlock( &a52_lock );
|
||||
|
||||
if( !p_a52_adec->frame_size )
|
||||
{
|
||||
msg_Warn( p_a52_adec->p_fifo, "a52_syncinfo failed" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( DecodeFrame( p_a52_adec ) && !p_a52_adec->p_fifo->b_die )
|
||||
{
|
||||
DecoderError( p_fifo );
|
||||
free( p_a52_adec );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* If b_error is set, the decoder thread enters the error loop */
|
||||
if( p_a52_adec->p_fifo->b_error )
|
||||
{
|
||||
DecoderError( p_a52_adec->p_fifo );
|
||||
}
|
||||
|
||||
/* End of the liba52 decoder thread */
|
||||
EndThread( p_a52_adec );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* InitThread: initialize data before entering main loop
|
||||
*****************************************************************************/
|
||||
static int InitThread( a52_adec_thread_t * p_a52_adec )
|
||||
{
|
||||
/* Initialize the global lock */
|
||||
vlc_mutex_lock( p_a52_adec->p_fifo->p_vlc->p_global_lock );
|
||||
if ( !b_liba52_initialized )
|
||||
{
|
||||
vlc_mutex_init( p_a52_adec->p_fifo, &a52_lock );
|
||||
b_liba52_initialized = 1;
|
||||
}
|
||||
vlc_mutex_unlock( p_a52_adec->p_fifo->p_vlc->p_global_lock );
|
||||
|
||||
/* Initialize liba52 */
|
||||
vlc_mutex_lock( &a52_lock );
|
||||
p_a52_adec->p_a52_state = a52_init( 0 );
|
||||
vlc_mutex_unlock( &a52_lock );
|
||||
if( p_a52_adec->p_a52_state == NULL )
|
||||
{
|
||||
msg_Err( p_a52_adec->p_fifo, "unable to initialize liba52" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
p_a52_adec->b_dynrng = config_GetInt( p_a52_adec->p_fifo, "a52-dynrng" );
|
||||
|
||||
/* Init the BitStream */
|
||||
InitBitstream( &p_a52_adec->bit_stream,
|
||||
p_a52_adec->p_fifo,
|
||||
BitstreamCallback, NULL );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* DecodeFrame: decodes an ATSC A/52 frame.
|
||||
*****************************************************************************/
|
||||
static int DecodeFrame( a52_adec_thread_t * p_a52_adec )
|
||||
{
|
||||
sample_t sample_level = 1;
|
||||
byte_t *p_buffer;
|
||||
int i;
|
||||
|
||||
if( ( p_a52_adec->p_aout_fifo != NULL ) &&
|
||||
( p_a52_adec->p_aout_fifo->i_rate != p_a52_adec->sample_rate ) )
|
||||
{
|
||||
/* Make sure the output thread leaves the NextFrame() function */
|
||||
vlc_mutex_lock (&(p_a52_adec->p_aout_fifo->data_lock));
|
||||
aout_DestroyFifo (p_a52_adec->p_aout_fifo);
|
||||
vlc_cond_signal (&(p_a52_adec->p_aout_fifo->data_wait));
|
||||
vlc_mutex_unlock (&(p_a52_adec->p_aout_fifo->data_lock));
|
||||
|
||||
p_a52_adec->p_aout_fifo = NULL;
|
||||
}
|
||||
|
||||
/* Creating the audio output fifo if not created yet */
|
||||
if( p_a52_adec->p_aout_fifo == NULL )
|
||||
{
|
||||
p_a52_adec->p_aout_fifo = aout_CreateFifo( p_a52_adec->p_fifo,
|
||||
AOUT_FIFO_PCM, p_a52_adec->i_channels,
|
||||
p_a52_adec->sample_rate,
|
||||
AC3DEC_FRAME_SIZE * p_a52_adec->i_channels,
|
||||
NULL );
|
||||
|
||||
if ( p_a52_adec->p_aout_fifo == NULL )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the Presentation Time Stamp */
|
||||
CurrentPTS( &p_a52_adec->bit_stream,
|
||||
&p_a52_adec->p_aout_fifo->date[
|
||||
p_a52_adec->p_aout_fifo->i_end_frame],
|
||||
NULL );
|
||||
|
||||
if( !p_a52_adec->p_aout_fifo->date[
|
||||
p_a52_adec->p_aout_fifo->i_end_frame] )
|
||||
{
|
||||
p_a52_adec->p_aout_fifo->date[
|
||||
p_a52_adec->p_aout_fifo->i_end_frame] = LAST_MDATE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
p_buffer = ((byte_t *)p_a52_adec->p_aout_fifo->buffer) +
|
||||
( p_a52_adec->p_aout_fifo->i_end_frame * AC3DEC_FRAME_SIZE *
|
||||
p_a52_adec->i_channels * sizeof(s16) );
|
||||
|
||||
/* FIXME */
|
||||
p_a52_adec->flags = A52_STEREO | A52_ADJUST_LEVEL;
|
||||
|
||||
/* Get the complete frame */
|
||||
GetChunk( &p_a52_adec->bit_stream, p_a52_adec->p_frame_buffer + 7,
|
||||
p_a52_adec->frame_size - 7 );
|
||||
if( p_a52_adec->p_fifo->b_die ) return( -1 );
|
||||
|
||||
/* do the actual decoding now */
|
||||
vlc_mutex_lock( &a52_lock );
|
||||
a52_frame( p_a52_adec->p_a52_state, p_a52_adec->p_frame_buffer,
|
||||
&p_a52_adec->flags, &sample_level, 384 );
|
||||
|
||||
if( !p_a52_adec->b_dynrng )
|
||||
a52_dynrng( p_a52_adec->p_a52_state, NULL, NULL );
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
if( a52_block( p_a52_adec->p_a52_state ) )
|
||||
{
|
||||
msg_Warn( p_a52_adec->p_fifo, "a52_block failed for block %i", i );
|
||||
}
|
||||
|
||||
float2s16_2( a52_samples( p_a52_adec->p_a52_state ),
|
||||
((int16_t *)p_buffer) + i * 256 * p_a52_adec->i_channels );
|
||||
}
|
||||
vlc_mutex_unlock( &a52_lock );
|
||||
|
||||
|
||||
vlc_mutex_lock( &p_a52_adec->p_aout_fifo->data_lock );
|
||||
p_a52_adec->p_aout_fifo->i_end_frame =
|
||||
(p_a52_adec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
|
||||
vlc_cond_signal (&p_a52_adec->p_aout_fifo->data_wait);
|
||||
vlc_mutex_unlock (&p_a52_adec->p_aout_fifo->data_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* EndThread : liba52 decoder thread destruction
|
||||
*****************************************************************************/
|
||||
static void EndThread (a52_adec_thread_t *p_a52_adec)
|
||||
{
|
||||
/* If the audio output fifo was created, we destroy it */
|
||||
if (p_a52_adec->p_aout_fifo != NULL)
|
||||
{
|
||||
aout_DestroyFifo (p_a52_adec->p_aout_fifo);
|
||||
|
||||
/* Make sure the output thread leaves the NextFrame() function */
|
||||
vlc_mutex_lock (&(p_a52_adec->p_aout_fifo->data_lock));
|
||||
vlc_cond_signal (&(p_a52_adec->p_aout_fifo->data_wait));
|
||||
vlc_mutex_unlock (&(p_a52_adec->p_aout_fifo->data_lock));
|
||||
}
|
||||
|
||||
vlc_mutex_lock( &a52_lock );
|
||||
a52_free( p_a52_adec->p_a52_state );
|
||||
vlc_mutex_unlock( &a52_lock );
|
||||
free( p_a52_adec );
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* float2s16_2 : converts floats to ints using a trick based on the IEEE
|
||||
* floating-point format
|
||||
*****************************************************************************/
|
||||
static inline int16_t convert (int32_t i)
|
||||
{
|
||||
if (i > 0x43c07fff)
|
||||
return 32767;
|
||||
else if (i < 0x43bf8000)
|
||||
return -32768;
|
||||
else
|
||||
return i - 0x43c00000;
|
||||
}
|
||||
|
||||
static void float2s16_2 (float * _f, int16_t * s16)
|
||||
{
|
||||
int i;
|
||||
int32_t * f = (int32_t *) _f;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
s16[2*i] = convert (f[i]);
|
||||
s16[2*i+1] = convert (f[i+256]);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* BitstreamCallback: Import parameters from the new data/PES packet
|
||||
*****************************************************************************
|
||||
* This function is called by input's NextDataPacket.
|
||||
*****************************************************************************/
|
||||
static void BitstreamCallback ( bit_stream_t * p_bit_stream,
|
||||
vlc_bool_t b_new_pes )
|
||||
{
|
||||
if( b_new_pes )
|
||||
{
|
||||
/* Drop special AC3 header */
|
||||
/* p_bit_stream->p_byte += 3; */
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* a52.h: ATSC A/52 aka AC-3 decoder plugin for vlc.
|
||||
* This plugin makes use of liba52 to decode A/52 audio
|
||||
* (http://liba52.sf.net/).
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: a52.h,v 1.4 2002/06/01 12:31:58 sam Exp $
|
||||
*
|
||||
* Authors: Gildas Bazin <gbazin@netcourrier.com>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* a52_adec_thread_t : a52 decoder thread descriptor
|
||||
*****************************************************************************/
|
||||
typedef struct a52_adec_thread_s
|
||||
{
|
||||
/*
|
||||
* liba52 properties
|
||||
*/
|
||||
a52_state_t *p_a52_state;
|
||||
int frame_size;
|
||||
int flags;
|
||||
int sample_rate;
|
||||
int bit_rate;
|
||||
vlc_bool_t b_dynrng;
|
||||
|
||||
/* The bit stream structure handles the PES stream at the bit level */
|
||||
bit_stream_t bit_stream;
|
||||
|
||||
/*
|
||||
* Input properties
|
||||
*/
|
||||
decoder_fifo_t *p_fifo; /* stores the PES stream data */
|
||||
data_packet_t *p_data;
|
||||
|
||||
/*
|
||||
* Output properties
|
||||
*/
|
||||
aout_fifo_t *p_aout_fifo; /* stores the decompressed audio frames */
|
||||
int i_channels;
|
||||
|
||||
/* temporary buffer to store the raw frame to be decoded */
|
||||
u8 p_frame_buffer[3840];
|
||||
|
||||
} a52_adec_thread_t;
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1,2 +0,0 @@
|
|||
a52_system_SOURCES = a52_system.c
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* a52_system.c : A52 input module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: a52_system.c,v 1.3 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Arnaud de Bossoreille de Ribou <bozo@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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
#include <string.h> /* strdup() */
|
||||
#include <errno.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/input.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* Constants
|
||||
*****************************************************************************/
|
||||
#define A52_PACKET_SIZE 16384
|
||||
#define MAX_PACKETS_IN_FIFO 3
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int Init ( vlc_object_t * );
|
||||
static int Demux ( input_thread_t * );
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
set_description( "A52 demuxer" );
|
||||
set_capability( "demux", 150 );
|
||||
set_callbacks( Init, NULL );
|
||||
add_shortcut( "a52sys" );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* Init: initializes ES structures
|
||||
*****************************************************************************/
|
||||
static int Init( vlc_object_t * p_this )
|
||||
{
|
||||
input_thread_t * p_input = (input_thread_t *)p_this;
|
||||
es_descriptor_t * p_es;
|
||||
byte_t * p_peek;
|
||||
|
||||
/* Initialize access plug-in structures. */
|
||||
if( p_input->i_mtu == 0 )
|
||||
{
|
||||
/* Improve speed. */
|
||||
p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
|
||||
}
|
||||
|
||||
p_input->pf_demux = Demux;
|
||||
p_input->pf_rewind = NULL;
|
||||
|
||||
/* Have a peep at the show. */
|
||||
if( input_Peek( p_input, &p_peek, 2 ) < 2 )
|
||||
{
|
||||
/* Stream shorter than 4 bytes... */
|
||||
msg_Err( p_input, "cannot peek()" );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( *p_peek != 0x0b || *(p_peek + 1) != 0x77 )
|
||||
{
|
||||
if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "a52sys", 3 ) )
|
||||
{
|
||||
/* User forced */
|
||||
msg_Err( p_input, "this doesn't look like an a52 stream, continuing" );
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_Warn( p_input, "a52 module discarded (no startcode)" );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
if( input_InitStream( p_input, 0 ) == -1 )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
input_AddProgram( p_input, 0, 0 );
|
||||
p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
|
||||
vlc_mutex_lock( &p_input->stream.stream_lock );
|
||||
p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xBD, 0 );
|
||||
p_es->i_stream_id = 0xBD;
|
||||
p_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
|
||||
p_es->i_cat = AUDIO_ES;
|
||||
input_SelectES( p_input, p_es );
|
||||
p_input->stream.p_selected_area->i_tell = 0;
|
||||
p_input->stream.p_selected_program->b_is_ok = 1;
|
||||
vlc_mutex_unlock( &p_input->stream.stream_lock );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Demux: reads and demuxes data packets
|
||||
*****************************************************************************
|
||||
* Returns -1 in case of error, 0 in case of EOF, 1 otherwise
|
||||
*****************************************************************************/
|
||||
static int Demux( input_thread_t * p_input )
|
||||
{
|
||||
ssize_t i_read;
|
||||
decoder_fifo_t * p_fifo =
|
||||
p_input->stream.p_selected_program->pp_es[0]->p_decoder_fifo;
|
||||
pes_packet_t * p_pes;
|
||||
data_packet_t * p_data;
|
||||
|
||||
i_read = input_SplitBuffer( p_input, &p_data, A52_PACKET_SIZE );
|
||||
|
||||
if ( i_read <= 0 )
|
||||
{
|
||||
return( i_read );
|
||||
}
|
||||
|
||||
p_pes = input_NewPES( p_input->p_method_data );
|
||||
|
||||
if( p_pes == NULL )
|
||||
{
|
||||
msg_Err( p_input, "out of memory" );
|
||||
input_DeletePacket( p_input->p_method_data, p_data );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
p_pes->i_rate = p_input->stream.control.i_rate;
|
||||
p_pes->p_first = p_pes->p_last = p_data;
|
||||
p_pes->i_nb_data = 1;
|
||||
|
||||
vlc_mutex_lock( &p_fifo->data_lock );
|
||||
if( p_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
|
||||
{
|
||||
/* Wait for the decoder. */
|
||||
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
|
||||
}
|
||||
vlc_mutex_unlock( &p_fifo->data_lock );
|
||||
|
||||
if( (p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT)
|
||||
|(p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_START)
|
||||
| (input_ClockManageControl( p_input,
|
||||
p_input->stream.p_selected_program,
|
||||
(mtime_t)0 ) == PAUSE_S) )
|
||||
{
|
||||
msg_Warn( p_input, "synchro reinit" );
|
||||
p_pes->i_pts = mdate() + DEFAULT_PTS_DELAY;
|
||||
p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
|
||||
}
|
||||
|
||||
input_DecodePES( p_fifo, p_pes );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1,2 +0,0 @@
|
|||
aa_SOURCES = aa.c
|
||||
|
260
plugins/aa/aa.c
260
plugins/aa/aa.c
|
@ -1,260 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* vout_aa.c: Aa video output display method for testing purposes
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2002 VideoLAN
|
||||
* $Id: aa.c,v 1.9 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <stdlib.h> /* free() */
|
||||
#include <string.h> /* strerror() */
|
||||
|
||||
#include <aalib.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/vout.h>
|
||||
#include <vlc/intf.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int Create ( vlc_object_t * );
|
||||
static void Destroy ( vlc_object_t * );
|
||||
|
||||
static int Init ( vout_thread_t * );
|
||||
static void End ( vout_thread_t * );
|
||||
static int Manage ( vout_thread_t * );
|
||||
static void Render ( vout_thread_t *, picture_t * );
|
||||
static void Display ( vout_thread_t *, picture_t * );
|
||||
|
||||
static void SetPalette ( vout_thread_t *, u16 *, u16 *, u16 * );
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
set_description( _("ASCII-art video output module") );
|
||||
set_capability( "video output", 10 );
|
||||
add_shortcut( "aalib" );
|
||||
set_callbacks( Create, Destroy );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* vout_sys_t: aa video output method descriptor
|
||||
*****************************************************************************
|
||||
* This structure is part of the video output thread descriptor.
|
||||
* It describes the aa specific properties of an output thread.
|
||||
*****************************************************************************/
|
||||
struct vout_sys_t
|
||||
{
|
||||
struct aa_context* aa_context;
|
||||
aa_palette palette;
|
||||
int i_width; /* width of main window */
|
||||
int i_height; /* height of main window */
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Create: allocates aa video thread output method
|
||||
*****************************************************************************
|
||||
* This function allocates and initializes a aa vout method.
|
||||
*****************************************************************************/
|
||||
static int Create( vlc_object_t *p_this )
|
||||
{
|
||||
vout_thread_t *p_vout = (vout_thread_t *)p_this;
|
||||
|
||||
/* Allocate structure */
|
||||
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
|
||||
if( p_vout->p_sys == NULL )
|
||||
{
|
||||
msg_Err( p_vout, "out of memory" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* Don't parse any options, but take $AAOPTS into account */
|
||||
aa_parseoptions( NULL, NULL, NULL, NULL );
|
||||
|
||||
if (!(p_vout->p_sys->aa_context = aa_autoinit(&aa_defparams)))
|
||||
{
|
||||
msg_Err( p_vout, "cannot initialize aalib" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
p_vout->pf_init = Init;
|
||||
p_vout->pf_end = End;
|
||||
p_vout->pf_manage = Manage;
|
||||
p_vout->pf_render = Render;
|
||||
p_vout->pf_display = Display;
|
||||
|
||||
p_vout->p_sys->i_width = aa_imgwidth(p_vout->p_sys->aa_context);
|
||||
p_vout->p_sys->i_height = aa_imgheight(p_vout->p_sys->aa_context);
|
||||
aa_autoinitkbd( p_vout->p_sys->aa_context, 0 );
|
||||
aa_autoinitmouse( p_vout->p_sys->aa_context, AA_MOUSEPRESSMASK );
|
||||
aa_hidemouse( p_vout->p_sys->aa_context );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Init: initialize aa video thread output method
|
||||
*****************************************************************************/
|
||||
static int Init( vout_thread_t *p_vout )
|
||||
{
|
||||
int i_index;
|
||||
picture_t *p_pic = NULL;
|
||||
|
||||
I_OUTPUTPICTURES = 0;
|
||||
|
||||
p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
|
||||
p_vout->output.i_width = p_vout->p_sys->i_width;
|
||||
p_vout->output.i_height = p_vout->p_sys->i_height;
|
||||
p_vout->output.i_aspect = p_vout->p_sys->i_width
|
||||
* VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
|
||||
p_vout->output.pf_setpalette = SetPalette;
|
||||
|
||||
/* Find an empty picture slot */
|
||||
for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
|
||||
{
|
||||
if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
|
||||
{
|
||||
p_pic = p_vout->p_picture + i_index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( p_pic == NULL )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate the picture */
|
||||
p_pic->p->p_pixels = aa_image( p_vout->p_sys->aa_context );
|
||||
p_pic->p->i_lines = p_vout->p_sys->i_height;
|
||||
p_pic->p->i_pitch = p_vout->p_sys->i_width;
|
||||
p_pic->p->i_pixel_pitch = 1;
|
||||
p_pic->p->i_visible_pitch = p_vout->p_sys->i_width;
|
||||
p_pic->i_planes = 1;
|
||||
|
||||
p_pic->i_status = DESTROYED_PICTURE;
|
||||
p_pic->i_type = DIRECT_PICTURE;
|
||||
|
||||
PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
|
||||
I_OUTPUTPICTURES++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* End: terminate aa video thread output method
|
||||
*****************************************************************************/
|
||||
static void End( vout_thread_t *p_vout )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Destroy: destroy aa video thread output method
|
||||
*****************************************************************************
|
||||
* Terminate an output method created by AaCreateOutputMethod
|
||||
*****************************************************************************/
|
||||
static void Destroy( vlc_object_t *p_this )
|
||||
{
|
||||
vout_thread_t *p_vout = (vout_thread_t *)p_this;
|
||||
|
||||
aa_close( p_vout->p_sys->aa_context );
|
||||
free( p_vout->p_sys );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Manage: handle aa events
|
||||
*****************************************************************************
|
||||
* This function should be called regularly by video output thread. It manages
|
||||
* console events. It returns a non null value on error.
|
||||
*****************************************************************************/
|
||||
static int Manage( vout_thread_t *p_vout )
|
||||
{
|
||||
int event, x, y, b;
|
||||
event = aa_getevent( p_vout->p_sys->aa_context, 0 );
|
||||
switch ( event )
|
||||
{
|
||||
case AA_MOUSE:
|
||||
aa_getmouse( p_vout->p_sys->aa_context, &x, &y, &b );
|
||||
if ( b & AA_BUTTON3 )
|
||||
{
|
||||
intf_thread_t *p_intf;
|
||||
p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF, FIND_ANYWHERE );
|
||||
if( p_intf )
|
||||
{
|
||||
p_intf->b_menu_change = 1;
|
||||
vlc_object_release( p_intf );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AA_RESIZE:
|
||||
p_vout->i_changes |= VOUT_SIZE_CHANGE;
|
||||
aa_resize( p_vout->p_sys->aa_context );
|
||||
p_vout->p_sys->i_width = aa_imgwidth( p_vout->p_sys->aa_context );
|
||||
p_vout->p_sys->i_height = aa_imgheight( p_vout->p_sys->aa_context );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Render: render previously calculated output
|
||||
*****************************************************************************/
|
||||
static void Render( vout_thread_t *p_vout, picture_t *p_pic )
|
||||
{
|
||||
aa_fastrender( p_vout->p_sys->aa_context, 0, 0,
|
||||
aa_imgwidth( p_vout->p_sys->aa_context ),
|
||||
aa_imgheight( p_vout->p_sys->aa_context ) );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Display: displays previously rendered output
|
||||
*****************************************************************************/
|
||||
static void Display( vout_thread_t *p_vout, picture_t *p_pic )
|
||||
{
|
||||
/* No need to do anything, the fake direct buffers stay as they are */
|
||||
int i_width, i_height, i_x, i_y;
|
||||
|
||||
vout_PlacePicture( p_vout, p_vout->p_sys->i_width, p_vout->p_sys->i_height,
|
||||
&i_x, &i_y, &i_width, &i_height );
|
||||
|
||||
aa_flush(p_vout->p_sys->aa_context);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* SetPalette: set the 8bpp palette
|
||||
*****************************************************************************/
|
||||
static void SetPalette( vout_thread_t *p_vout, u16 *red, u16 *green, u16 *blue )
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Fill colors with color information */
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
aa_setpalette( p_vout->p_sys->palette, 256 -i,
|
||||
red[ i ], green[ i ], blue[ i ] );
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1 +0,0 @@
|
|||
ac3_adec_SOURCES = ac3_adec.c ac3_decoder.c ac3_parse.c ac3_exponent.c ac3_bit_allocate.c ac3_mantissa.c ac3_rematrix.c ac3_imdct.c
|
|
@ -1,384 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_adec.c: ac3 decoder module main file
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: ac3_adec.c,v 1.35 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Michel Lespinasse <walken@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
#include <string.h> /* memset() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/aout.h>
|
||||
#include <vlc/decoder.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h> /* getpid() */
|
||||
#endif
|
||||
|
||||
#include "ac3_imdct.h"
|
||||
#include "ac3_downmix.h"
|
||||
#include "ac3_adec.h"
|
||||
|
||||
#define AC3DEC_FRAME_SIZE (2*1536)
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int OpenDecoder ( vlc_object_t * );
|
||||
static int RunDecoder ( decoder_fifo_t * );
|
||||
static int InitThread ( ac3dec_t * p_adec );
|
||||
static void EndThread ( ac3dec_t * p_adec );
|
||||
static void BitstreamCallback ( bit_stream_t *p_bit_stream,
|
||||
vlc_bool_t b_new_pes );
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
add_category_hint( N_("Miscellaneous"), NULL );
|
||||
add_module ( "ac3-downmix", "downmix", NULL, NULL,
|
||||
N_("AC3 downmix module"), NULL );
|
||||
add_module ( "ac3-imdct", "imdct", NULL, NULL,
|
||||
N_("AC3 IMDCT module"), NULL );
|
||||
set_description( _("software AC3 decoder") );
|
||||
set_capability( "decoder", 50 );
|
||||
set_callbacks( OpenDecoder, NULL );
|
||||
add_shortcut( "ac3" );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* OpenDecoder: probe the decoder and return score
|
||||
*****************************************************************************
|
||||
* Tries to launch a decoder and return score so that the interface is able
|
||||
* to chose.
|
||||
*****************************************************************************/
|
||||
static int OpenDecoder( vlc_object_t *p_this )
|
||||
{
|
||||
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
|
||||
|
||||
if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') )
|
||||
{
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
p_fifo->pf_run = RunDecoder;
|
||||
return VLC_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* RunDecoder: this function is called just after the thread is created
|
||||
*****************************************************************************/
|
||||
static int RunDecoder( decoder_fifo_t *p_fifo )
|
||||
{
|
||||
ac3dec_t * p_ac3dec;
|
||||
void * p_orig; /* pointer before memalign */
|
||||
vlc_bool_t b_sync = 0;
|
||||
|
||||
/* Allocate the memory needed to store the thread's structure */
|
||||
p_ac3dec = (ac3dec_t *)vlc_memalign( &p_orig, 16, sizeof(ac3dec_t) );
|
||||
memset( p_ac3dec, 0, sizeof( ac3dec_t ) );
|
||||
|
||||
if( p_ac3dec == NULL )
|
||||
{
|
||||
msg_Err( p_fifo, "out of memory" );
|
||||
DecoderError( p_fifo );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the thread properties
|
||||
*/
|
||||
p_ac3dec->p_fifo = p_fifo;
|
||||
if( InitThread( p_ac3dec ) )
|
||||
{
|
||||
msg_Err( p_fifo, "could not initialize thread" );
|
||||
DecoderError( p_fifo );
|
||||
free( p_orig );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* ac3 decoder thread's main loop */
|
||||
/* FIXME : do we have enough room to store the decoded frames ?? */
|
||||
while ((!p_ac3dec->p_fifo->b_die) && (!p_ac3dec->p_fifo->b_error))
|
||||
{
|
||||
s16 * buffer;
|
||||
ac3_sync_info_t sync_info;
|
||||
|
||||
if( !b_sync )
|
||||
{
|
||||
int i_sync_ptr;
|
||||
#define p_bit_stream (&p_ac3dec->bit_stream)
|
||||
|
||||
/* Go to the next PES packet and jump to sync_ptr */
|
||||
do {
|
||||
BitstreamNextDataPacket( p_bit_stream );
|
||||
} while( !p_bit_stream->p_decoder_fifo->b_die
|
||||
&& !p_bit_stream->p_decoder_fifo->b_error
|
||||
&& p_bit_stream->p_data !=
|
||||
p_bit_stream->p_decoder_fifo->p_first->p_first );
|
||||
i_sync_ptr = *(p_bit_stream->p_byte - 2) << 8
|
||||
| *(p_bit_stream->p_byte - 1);
|
||||
p_bit_stream->p_byte += i_sync_ptr;
|
||||
|
||||
/* Empty the bit FIFO and realign the bit stream */
|
||||
p_bit_stream->fifo.buffer = 0;
|
||||
p_bit_stream->fifo.i_available = 0;
|
||||
AlignWord( p_bit_stream );
|
||||
b_sync = 1;
|
||||
#undef p_bit_stream
|
||||
}
|
||||
|
||||
if (ac3_sync_frame (p_ac3dec, &sync_info))
|
||||
{
|
||||
b_sync = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ( p_ac3dec->p_aout_fifo != NULL ) &&
|
||||
( p_ac3dec->p_aout_fifo->i_rate != sync_info.sample_rate ) )
|
||||
{
|
||||
/* Make sure the output thread leaves the NextFrame() function */
|
||||
vlc_mutex_lock (&(p_ac3dec->p_aout_fifo->data_lock));
|
||||
aout_DestroyFifo (p_ac3dec->p_aout_fifo);
|
||||
vlc_cond_signal (&(p_ac3dec->p_aout_fifo->data_wait));
|
||||
vlc_mutex_unlock (&(p_ac3dec->p_aout_fifo->data_lock));
|
||||
|
||||
p_ac3dec->p_aout_fifo = NULL;
|
||||
}
|
||||
|
||||
/* Creating the audio output fifo if not created yet */
|
||||
if (p_ac3dec->p_aout_fifo == NULL ) {
|
||||
p_ac3dec->p_aout_fifo =
|
||||
aout_CreateFifo( p_ac3dec->p_fifo, AOUT_FIFO_PCM, 2,
|
||||
sync_info.sample_rate, AC3DEC_FRAME_SIZE, NULL );
|
||||
if ( p_ac3dec->p_aout_fifo == NULL )
|
||||
{
|
||||
p_ac3dec->p_fifo->b_error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CurrentPTS( &p_ac3dec->bit_stream,
|
||||
&p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->i_end_frame],
|
||||
NULL );
|
||||
if( !p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->i_end_frame] )
|
||||
{
|
||||
p_ac3dec->p_aout_fifo->date[
|
||||
p_ac3dec->p_aout_fifo->i_end_frame] =
|
||||
LAST_MDATE;
|
||||
}
|
||||
|
||||
buffer = ((s16 *)p_ac3dec->p_aout_fifo->buffer) +
|
||||
(p_ac3dec->p_aout_fifo->i_end_frame * AC3DEC_FRAME_SIZE);
|
||||
|
||||
if (ac3_decode_frame (p_ac3dec, buffer))
|
||||
{
|
||||
b_sync = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
vlc_mutex_lock (&p_ac3dec->p_aout_fifo->data_lock);
|
||||
p_ac3dec->p_aout_fifo->i_end_frame =
|
||||
(p_ac3dec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
|
||||
vlc_cond_signal (&p_ac3dec->p_aout_fifo->data_wait);
|
||||
vlc_mutex_unlock (&p_ac3dec->p_aout_fifo->data_lock);
|
||||
|
||||
RealignBits(&p_ac3dec->bit_stream);
|
||||
}
|
||||
|
||||
/* If b_error is set, the ac3 decoder thread enters the error loop */
|
||||
if (p_ac3dec->p_fifo->b_error)
|
||||
{
|
||||
DecoderError( p_ac3dec->p_fifo );
|
||||
}
|
||||
|
||||
/* End of the ac3 decoder thread */
|
||||
EndThread (p_ac3dec);
|
||||
|
||||
free( p_orig );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* InitThread: initialize data before entering main loop
|
||||
*****************************************************************************/
|
||||
static int InitThread( ac3dec_t * p_ac3dec )
|
||||
{
|
||||
char *psz_name;
|
||||
|
||||
/*
|
||||
* Choose the best downmix module
|
||||
*/
|
||||
p_ac3dec->p_downmix = vlc_object_create( p_ac3dec->p_fifo,
|
||||
sizeof( downmix_t ) );
|
||||
p_ac3dec->p_downmix->psz_object_name = "downmix";
|
||||
|
||||
psz_name = config_GetPsz( p_ac3dec->p_downmix, "ac3-downmix" );
|
||||
p_ac3dec->p_downmix->p_module =
|
||||
module_Need( p_ac3dec->p_downmix, "downmix", psz_name );
|
||||
if( psz_name ) free( psz_name );
|
||||
|
||||
if( p_ac3dec->p_downmix->p_module == NULL )
|
||||
{
|
||||
msg_Err( p_ac3dec->p_fifo, "no suitable downmix module" );
|
||||
vlc_object_destroy( p_ac3dec->p_downmix );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Choose the best IMDCT module
|
||||
*/
|
||||
p_ac3dec->p_imdct = vlc_object_create( p_ac3dec->p_fifo,
|
||||
sizeof( imdct_t ) );
|
||||
|
||||
#define IMDCT p_ac3dec->p_imdct
|
||||
psz_name = config_GetPsz( p_ac3dec->p_fifo, "ac3-imdct" );
|
||||
p_ac3dec->p_imdct->p_module =
|
||||
module_Need( p_ac3dec->p_imdct, "imdct", psz_name );
|
||||
if( psz_name ) free( psz_name );
|
||||
|
||||
if( p_ac3dec->p_imdct->p_module == NULL )
|
||||
{
|
||||
msg_Err( p_ac3dec->p_fifo, "no suitable IMDCT module" );
|
||||
vlc_object_destroy( p_ac3dec->p_imdct );
|
||||
module_Unneed( p_ac3dec->p_downmix, p_ac3dec->p_downmix->p_module );
|
||||
vlc_object_destroy( p_ac3dec->p_downmix );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Initialize the ac3 decoder structures */
|
||||
p_ac3dec->samples = vlc_memalign( &p_ac3dec->samples_orig,
|
||||
16, 6 * 256 * sizeof(float) );
|
||||
|
||||
IMDCT->buf = vlc_memalign( &IMDCT->buf_orig,
|
||||
16, N/4 * sizeof(complex_t) );
|
||||
IMDCT->delay = vlc_memalign( &IMDCT->delay_orig,
|
||||
16, 6 * 256 * sizeof(float) );
|
||||
IMDCT->delay1 = vlc_memalign( &IMDCT->delay1_orig,
|
||||
16, 6 * 256 * sizeof(float) );
|
||||
IMDCT->xcos1 = vlc_memalign( &IMDCT->xcos1_orig,
|
||||
16, N/4 * sizeof(float) );
|
||||
IMDCT->xsin1 = vlc_memalign( &IMDCT->xsin1_orig,
|
||||
16, N/4 * sizeof(float) );
|
||||
IMDCT->xcos2 = vlc_memalign( &IMDCT->xcos2_orig,
|
||||
16, N/8 * sizeof(float) );
|
||||
IMDCT->xsin2 = vlc_memalign( &IMDCT->xsin2_orig,
|
||||
16, N/8 * sizeof(float) );
|
||||
IMDCT->xcos_sin_sse = vlc_memalign( &IMDCT->xcos_sin_sse_orig,
|
||||
16, 128 * 4 * sizeof(float) );
|
||||
IMDCT->w_1 = vlc_memalign( &IMDCT->w_1_orig,
|
||||
16, 1 * sizeof(complex_t) );
|
||||
IMDCT->w_2 = vlc_memalign( &IMDCT->w_2_orig,
|
||||
16, 2 * sizeof(complex_t) );
|
||||
IMDCT->w_4 = vlc_memalign( &IMDCT->w_4_orig,
|
||||
16, 4 * sizeof(complex_t) );
|
||||
IMDCT->w_8 = vlc_memalign( &IMDCT->w_8_orig,
|
||||
16, 8 * sizeof(complex_t) );
|
||||
IMDCT->w_16 = vlc_memalign( &IMDCT->w_16_orig,
|
||||
16, 16 * sizeof(complex_t) );
|
||||
IMDCT->w_32 = vlc_memalign( &IMDCT->w_32_orig,
|
||||
16, 32 * sizeof(complex_t) );
|
||||
IMDCT->w_64 = vlc_memalign( &IMDCT->w_64_orig,
|
||||
16, 64 * sizeof(complex_t) );
|
||||
#undef IMDCT
|
||||
|
||||
E_( ac3_init )( p_ac3dec );
|
||||
|
||||
/*
|
||||
* Initialize the output properties
|
||||
*/
|
||||
p_ac3dec->p_aout_fifo = NULL;
|
||||
|
||||
/*
|
||||
* Bit stream
|
||||
*/
|
||||
InitBitstream( &p_ac3dec->bit_stream, p_ac3dec->p_fifo,
|
||||
BitstreamCallback, (void *) p_ac3dec );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* EndThread : ac3 decoder thread destruction
|
||||
*****************************************************************************/
|
||||
static void EndThread (ac3dec_t * p_ac3dec)
|
||||
{
|
||||
/* If the audio output fifo was created, we destroy it */
|
||||
if (p_ac3dec->p_aout_fifo != NULL)
|
||||
{
|
||||
aout_DestroyFifo (p_ac3dec->p_aout_fifo);
|
||||
|
||||
/* Make sure the output thread leaves the NextFrame() function */
|
||||
vlc_mutex_lock (&(p_ac3dec->p_aout_fifo->data_lock));
|
||||
vlc_cond_signal (&(p_ac3dec->p_aout_fifo->data_wait));
|
||||
vlc_mutex_unlock (&(p_ac3dec->p_aout_fifo->data_lock));
|
||||
}
|
||||
|
||||
/* Free allocated structures */
|
||||
#define IMDCT p_ac3dec->p_imdct
|
||||
free( IMDCT->w_1_orig );
|
||||
free( IMDCT->w_64_orig );
|
||||
free( IMDCT->w_32_orig );
|
||||
free( IMDCT->w_16_orig );
|
||||
free( IMDCT->w_8_orig );
|
||||
free( IMDCT->w_4_orig );
|
||||
free( IMDCT->w_2_orig );
|
||||
free( IMDCT->xcos_sin_sse_orig );
|
||||
free( IMDCT->xsin2_orig );
|
||||
free( IMDCT->xcos2_orig );
|
||||
free( IMDCT->xsin1_orig );
|
||||
free( IMDCT->xcos1_orig );
|
||||
free( IMDCT->delay1_orig );
|
||||
free( IMDCT->delay_orig );
|
||||
free( IMDCT->buf_orig );
|
||||
#undef IMDCT
|
||||
|
||||
free( p_ac3dec->samples_orig );
|
||||
|
||||
/* Unlock the modules */
|
||||
module_Unneed( p_ac3dec->p_downmix, p_ac3dec->p_downmix->p_module );
|
||||
vlc_object_destroy( p_ac3dec->p_downmix );
|
||||
|
||||
module_Unneed( p_ac3dec->p_imdct, p_ac3dec->p_imdct->p_module );
|
||||
vlc_object_destroy( p_ac3dec->p_imdct );
|
||||
|
||||
/* Free what's left of the decoder */
|
||||
free( p_ac3dec->imdct_orig );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* BitstreamCallback: Import parameters from the new data/PES packet
|
||||
*****************************************************************************
|
||||
* This function is called by input's NextDataPacket.
|
||||
*****************************************************************************/
|
||||
static void BitstreamCallback ( bit_stream_t * p_bit_stream,
|
||||
vlc_bool_t b_new_pes )
|
||||
{
|
||||
if( b_new_pes )
|
||||
{
|
||||
/* Drop special AC3 header */
|
||||
/* p_bit_stream->p_byte += 3; */
|
||||
}
|
||||
}
|
||||
|
|
@ -1,409 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_adec.h : ac3 decoder interface
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000 VideoLAN
|
||||
* $Id: ac3_adec.h,v 1.5 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Michel Kaempf <maxx@via.ecp.fr>
|
||||
* Renaud Dartus <reno@videolan.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Prototypes
|
||||
*****************************************************************************/
|
||||
vlc_thread_t ac3dec_CreateThread( decoder_fifo_t * p_fifo );
|
||||
|
||||
/**** ac3 decoder API - public ac3 decoder structures */
|
||||
|
||||
typedef struct ac3dec_s ac3dec_t;
|
||||
|
||||
typedef struct ac3_sync_info_s {
|
||||
int sample_rate; /* sample rate in Hz */
|
||||
int frame_size; /* frame size in bytes */
|
||||
int bit_rate; /* nominal bit rate in kbps */
|
||||
} ac3_sync_info_t;
|
||||
|
||||
|
||||
/**** ac3 decoder API - functions publically provided by the ac3 decoder ****/
|
||||
|
||||
int E_( ac3_init )(ac3dec_t * p_ac3dec);
|
||||
int ac3_sync_frame (ac3dec_t * p_ac3dec, ac3_sync_info_t * p_sync_info);
|
||||
int ac3_decode_frame (ac3dec_t * p_ac3dec, s16 * buffer);
|
||||
|
||||
/**** EVERYTHING AFTER THIS POINT IS PRIVATE ! DO NOT USE DIRECTLY ****/
|
||||
|
||||
/**** ac3 decoder internal structures ****/
|
||||
|
||||
/* The following structures are filled in by their corresponding parse_*
|
||||
* functions. See http://www.atsc.org/Standards/A52/a_52.pdf for
|
||||
* full details on each field. Indented fields are used to denote
|
||||
* conditional fields.
|
||||
*/
|
||||
|
||||
typedef struct syncinfo_s {
|
||||
/* Sync word == 0x0B77 */
|
||||
/* u16 syncword; */
|
||||
/* crc for the first 5/8 of the sync block */
|
||||
/* u16 crc1; */
|
||||
/* Stream Sampling Rate (kHz) 0 = 48, 1 = 44.1, 2 = 32, 3 = reserved */
|
||||
u16 fscod;
|
||||
/* Frame size code */
|
||||
u16 frmsizecod;
|
||||
|
||||
/* Information not in the AC-3 bitstream, but derived */
|
||||
/* Frame size in 16 bit words */
|
||||
u16 frame_size;
|
||||
/* Bit rate in kilobits */
|
||||
//u16 bit_rate;
|
||||
} syncinfo_t;
|
||||
|
||||
typedef struct bsi_s {
|
||||
/* Bit stream identification == 0x8 */
|
||||
u16 bsid;
|
||||
/* Bit stream mode */
|
||||
u16 bsmod;
|
||||
/* Audio coding mode */
|
||||
u16 acmod;
|
||||
/* If we're using the centre channel then */
|
||||
/* centre mix level */
|
||||
u16 cmixlev;
|
||||
/* If we're using the surround channel then */
|
||||
/* surround mix level */
|
||||
u16 surmixlev;
|
||||
/* If we're in 2/0 mode then */
|
||||
/* Dolby surround mix level - NOT USED - */
|
||||
u16 dsurmod;
|
||||
/* Low frequency effects on */
|
||||
u16 lfeon;
|
||||
/* Dialogue Normalization level */
|
||||
u16 dialnorm;
|
||||
/* Compression exists */
|
||||
u16 compre;
|
||||
/* Compression level */
|
||||
u16 compr;
|
||||
/* Language code exists */
|
||||
u16 langcode;
|
||||
/* Language code */
|
||||
u16 langcod;
|
||||
/* Audio production info exists*/
|
||||
u16 audprodie;
|
||||
u16 mixlevel;
|
||||
u16 roomtyp;
|
||||
/* If we're in dual mono mode (acmod == 0) then extra stuff */
|
||||
u16 dialnorm2;
|
||||
u16 compr2e;
|
||||
u16 compr2;
|
||||
u16 langcod2e;
|
||||
u16 langcod2;
|
||||
u16 audprodi2e;
|
||||
u16 mixlevel2;
|
||||
u16 roomtyp2;
|
||||
/* Copyright bit */
|
||||
u16 copyrightb;
|
||||
/* Original bit */
|
||||
u16 origbs;
|
||||
/* Timecode 1 exists */
|
||||
u16 timecod1e;
|
||||
/* Timecode 1 */
|
||||
u16 timecod1;
|
||||
/* Timecode 2 exists */
|
||||
u16 timecod2e;
|
||||
/* Timecode 2 */
|
||||
u16 timecod2;
|
||||
/* Additional bit stream info exists */
|
||||
u16 addbsie;
|
||||
/* Additional bit stream length - 1 (in bytes) */
|
||||
u16 addbsil;
|
||||
/* Additional bit stream information (max 64 bytes) */
|
||||
u8 addbsi[64];
|
||||
|
||||
/* Information not in the AC-3 bitstream, but derived */
|
||||
/* Number of channels (excluding LFE)
|
||||
* Derived from acmod */
|
||||
u16 nfchans;
|
||||
} bsi_t;
|
||||
|
||||
/* more pain */
|
||||
typedef struct audblk_s {
|
||||
/* block switch bit indexed by channel num */
|
||||
u16 blksw[5];
|
||||
/* dither enable bit indexed by channel num */
|
||||
u16 dithflag[5];
|
||||
/* dynamic range gain exists */
|
||||
u16 dynrnge;
|
||||
/* dynamic range gain */
|
||||
u16 dynrng;
|
||||
/* if acmod==0 then */
|
||||
/* dynamic range 2 gain exists */
|
||||
u16 dynrng2e;
|
||||
/* dynamic range 2 gain */
|
||||
u16 dynrng2;
|
||||
/* coupling strategy exists */
|
||||
u16 cplstre;
|
||||
/* coupling in use */
|
||||
u16 cplinu;
|
||||
/* channel coupled */
|
||||
u16 chincpl[5];
|
||||
/* if acmod==2 then */
|
||||
/* Phase flags in use */
|
||||
u16 phsflginu;
|
||||
/* coupling begin frequency code */
|
||||
u16 cplbegf;
|
||||
/* coupling end frequency code */
|
||||
u16 cplendf;
|
||||
/* coupling band structure bits */
|
||||
u16 cplbndstrc[18];
|
||||
/* Do coupling co-ords exist for this channel? */
|
||||
u16 cplcoe[5];
|
||||
/* Master coupling co-ordinate */
|
||||
u16 mstrcplco[5];
|
||||
/* Per coupling band coupling co-ordinates */
|
||||
u16 cplcoexp[5][18];
|
||||
u16 cplcomant[5][18];
|
||||
/* Phase flags for dual mono */
|
||||
u16 phsflg[18];
|
||||
/* Is there a rematrixing strategy */
|
||||
u16 rematstr;
|
||||
/* Rematrixing bits */
|
||||
u16 rematflg[4];
|
||||
/* Coupling exponent strategy */
|
||||
u16 cplexpstr;
|
||||
/* Exponent strategy for full bandwidth channels */
|
||||
u16 chexpstr[5];
|
||||
/* Exponent strategy for lfe channel */
|
||||
u16 lfeexpstr;
|
||||
/* Channel bandwidth for independent channels */
|
||||
u16 chbwcod[5];
|
||||
/* The absolute coupling exponent */
|
||||
u16 cplabsexp;
|
||||
/* Coupling channel exponents (D15 mode gives 18 * 12 /3 encoded exponents */
|
||||
u16 cplexps[18 * 12 / 3];
|
||||
/* Sanity checking constant */
|
||||
u32 magic2;
|
||||
/* fbw channel exponents */
|
||||
u16 exps[5][252 / 3];
|
||||
/* channel gain range */
|
||||
u16 gainrng[5];
|
||||
/* low frequency exponents */
|
||||
u16 lfeexps[3];
|
||||
|
||||
/* Bit allocation info */
|
||||
u16 baie;
|
||||
/* Slow decay code */
|
||||
u16 sdcycod;
|
||||
/* Fast decay code */
|
||||
u16 fdcycod;
|
||||
/* Slow gain code */
|
||||
u16 sgaincod;
|
||||
/* dB per bit code */
|
||||
u16 dbpbcod;
|
||||
/* masking floor code */
|
||||
u16 floorcod;
|
||||
|
||||
/* SNR offset info */
|
||||
u16 snroffste;
|
||||
/* coarse SNR offset */
|
||||
u16 csnroffst;
|
||||
/* coupling fine SNR offset */
|
||||
u16 cplfsnroffst;
|
||||
/* coupling fast gain code */
|
||||
u16 cplfgaincod;
|
||||
/* fbw fine SNR offset */
|
||||
u16 fsnroffst[5];
|
||||
/* fbw fast gain code */
|
||||
u16 fgaincod[5];
|
||||
/* lfe fine SNR offset */
|
||||
u16 lfefsnroffst;
|
||||
/* lfe fast gain code */
|
||||
u16 lfefgaincod;
|
||||
|
||||
/* Coupling leak info */
|
||||
u16 cplleake;
|
||||
/* coupling fast leak initialization */
|
||||
u16 cplfleak;
|
||||
/* coupling slow leak initialization */
|
||||
u16 cplsleak;
|
||||
|
||||
/* delta bit allocation info */
|
||||
u16 deltbaie;
|
||||
/* coupling delta bit allocation exists */
|
||||
u16 cpldeltbae;
|
||||
/* fbw delta bit allocation exists */
|
||||
u16 deltbae[5];
|
||||
/* number of cpl delta bit segments */
|
||||
u16 cpldeltnseg;
|
||||
/* coupling delta bit allocation offset */
|
||||
u16 cpldeltoffst[8];
|
||||
/* coupling delta bit allocation length */
|
||||
u16 cpldeltlen[8];
|
||||
/* coupling delta bit allocation length */
|
||||
u16 cpldeltba[8];
|
||||
/* number of delta bit segments */
|
||||
u16 deltnseg[5];
|
||||
/* fbw delta bit allocation offset */
|
||||
u16 deltoffst[5][8];
|
||||
/* fbw delta bit allocation length */
|
||||
u16 deltlen[5][8];
|
||||
/* fbw delta bit allocation length */
|
||||
u16 deltba[5][8];
|
||||
|
||||
/* skip length exists */
|
||||
u16 skiple;
|
||||
/* skip length */
|
||||
u16 skipl;
|
||||
|
||||
/* channel mantissas */
|
||||
// u16 chmant[5][256];
|
||||
|
||||
/* coupling mantissas */
|
||||
float cpl_flt[ 256 ];
|
||||
// u16 cplmant[256];
|
||||
|
||||
/* coupling mantissas */
|
||||
// u16 lfemant[7];
|
||||
|
||||
/* -- Information not in the bitstream, but derived thereof -- */
|
||||
|
||||
/* Number of coupling sub-bands */
|
||||
u16 ncplsubnd;
|
||||
|
||||
/* Number of combined coupling sub-bands
|
||||
* Derived from ncplsubnd and cplbndstrc */
|
||||
u16 ncplbnd;
|
||||
|
||||
/* Number of exponent groups by channel
|
||||
* Derived from strmant, endmant */
|
||||
u16 nchgrps[5];
|
||||
|
||||
/* Number of coupling exponent groups
|
||||
* Derived from cplbegf, cplendf, cplexpstr */
|
||||
u16 ncplgrps;
|
||||
|
||||
/* End mantissa numbers of fbw channels */
|
||||
u16 endmant[5];
|
||||
|
||||
/* Start and end mantissa numbers for the coupling channel */
|
||||
u16 cplstrtmant;
|
||||
u16 cplendmant;
|
||||
|
||||
/* Decoded exponent info */
|
||||
u16 fbw_exp[5][256];
|
||||
u16 cpl_exp[256];
|
||||
u16 lfe_exp[7];
|
||||
|
||||
/* Bit allocation pointer results */
|
||||
u16 fbw_bap[5][256];
|
||||
/* FIXME?? figure out exactly how many entries there should be (253-37?) */
|
||||
u16 cpl_bap[256];
|
||||
u16 lfe_bap[7];
|
||||
} audblk_t;
|
||||
|
||||
/* Everything you wanted to know about band structure */
|
||||
|
||||
/*
|
||||
* The entire frequency domain is represented by 256 real
|
||||
* floating point fourier coefficients. Only the lower 253
|
||||
* coefficients are actually utilized however. We use arrays
|
||||
* of 256 to be efficient in some cases.
|
||||
*
|
||||
* The 5 full bandwidth channels (fbw) can have their higher
|
||||
* frequencies coupled together. These coupled channels then
|
||||
* share their high frequency components.
|
||||
*
|
||||
* This coupling band is broken up into 18 sub-bands starting
|
||||
* at mantissa number 37. Each sub-band is 12 bins wide.
|
||||
*
|
||||
* There are 50 bit allocation sub-bands which cover the entire
|
||||
* frequency range. The sub-bands are of non-uniform width, and
|
||||
* approximate a 1/6 octave scale.
|
||||
*/
|
||||
|
||||
typedef struct bit_allocate_s
|
||||
{
|
||||
s16 psd[256];
|
||||
s16 bndpsd[256];
|
||||
s16 excite[256];
|
||||
s16 mask[256];
|
||||
s16 sdecay;
|
||||
s16 fdecay;
|
||||
s16 sgain;
|
||||
s16 dbknee;
|
||||
s16 floor;
|
||||
} bit_allocate_t;
|
||||
|
||||
/* These store the persistent state of the packed mantissas */
|
||||
typedef struct mantissa_s
|
||||
{
|
||||
float q_1[2];
|
||||
float q_2[2];
|
||||
float q_4[1];
|
||||
s32 q_1_pointer;
|
||||
s32 q_2_pointer;
|
||||
s32 q_4_pointer;
|
||||
u16 lfsr_state;
|
||||
} mantissa_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* ac3dec_t : ac3 decoder thread descriptor
|
||||
*****************************************************************************/
|
||||
|
||||
struct ac3dec_s
|
||||
{
|
||||
/*
|
||||
* Decoder properties
|
||||
*/
|
||||
void * ac3_decoder_orig; /* pointer before memalign */
|
||||
|
||||
/*
|
||||
* Thread properties
|
||||
*/
|
||||
vlc_thread_t thread_id; /* id for thread functions */
|
||||
|
||||
/*
|
||||
* Input properties
|
||||
*/
|
||||
decoder_fifo_t * p_fifo; /* stores the PES stream data */
|
||||
|
||||
/* The bit stream structure handles the PES stream at the bit level */
|
||||
bit_stream_t bit_stream;
|
||||
int i_available;
|
||||
unsigned int total_bits_read; /* temporary */
|
||||
|
||||
/*
|
||||
* Decoder properties
|
||||
*/
|
||||
syncinfo_t syncinfo;
|
||||
bsi_t bsi;
|
||||
audblk_t audblk;
|
||||
|
||||
dm_par_t dm_par;
|
||||
|
||||
bit_allocate_t bit_allocate;
|
||||
mantissa_t mantissa;
|
||||
downmix_t * p_downmix;
|
||||
|
||||
/*
|
||||
* Output properties
|
||||
*/
|
||||
aout_fifo_t * p_aout_fifo; /* stores the decompressed audio frames */
|
||||
|
||||
float * samples;
|
||||
void * samples_orig; /* pointer before memalign */
|
||||
imdct_t * p_imdct;
|
||||
void * imdct_orig; /* pointer before memalign */
|
||||
};
|
||||
|
|
@ -1,452 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_bit_allocate.c: ac3 allocation tables
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000-2001 VideoLAN
|
||||
* $Id: ac3_bit_allocate.c,v 1.8 2002/06/01 12:31:58 sam Exp $
|
||||
*
|
||||
* Authors: Michel Kaempf <maxx@via.ecp.fr>
|
||||
* Aaron Holtzman <aholtzma@engr.uvic.ca>
|
||||
* Renaud Dartus <reno@videolan.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <string.h> /* memcpy() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/decoder.h>
|
||||
|
||||
#include "ac3_imdct.h"
|
||||
#include "ac3_downmix.h"
|
||||
#include "ac3_adec.h"
|
||||
|
||||
#include "ac3_internal.h" /* DELTA_BIT_REUSE */
|
||||
|
||||
|
||||
static void ba_compute_psd (bit_allocate_t * p_bit, s16 start, s16 end, s16 exps[]);
|
||||
|
||||
static void ba_compute_excitation (bit_allocate_t * p_bit, s16 start, s16 end, s16 fgain,
|
||||
s16 fastleak, s16 slowleak, s16 is_lfe);
|
||||
static void ba_compute_mask (bit_allocate_t * p_bit, s16 start, s16 end, u16 fscod,
|
||||
u16 deltbae, u16 deltnseg, u16 deltoffst[],
|
||||
u16 deltba[], u16 deltlen[]);
|
||||
static void ba_compute_bap (bit_allocate_t * p_bit, s16 start, s16 end,
|
||||
s16 snroffset, s16 bap[]);
|
||||
|
||||
/* Misc LUTs for bit allocation process */
|
||||
|
||||
static const s16 slowdec[] = { 0x0f, 0x11, 0x13, 0x15 };
|
||||
static const s16 fastdec[] = { 0x3f, 0x53, 0x67, 0x7b };
|
||||
static const s16 slowgain[] = { 0x540, 0x4d8, 0x478, 0x410 };
|
||||
static const s16 dbpbtab[] = { 0x000, 0x700, 0x900, 0xb00 };
|
||||
|
||||
static const u16 floortab[] = { 0x2f0, 0x2b0, 0x270, 0x230, 0x1f0, 0x170, 0x0f0, 0xf800 };
|
||||
static const s16 fastgain[] = { 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400 };
|
||||
|
||||
static const s16 bndtab[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||
20, 21, 22, 23, 24, 25, 26, 27, 28, 31,
|
||||
34, 37, 40, 43, 46, 49, 55, 61, 67, 73,
|
||||
79, 85, 97, 109, 121, 133, 157, 181, 205, 229 };
|
||||
|
||||
static const s16 bndsz[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 3, 3,
|
||||
3, 3, 3, 3, 3, 6, 6, 6, 6, 6,
|
||||
6, 12, 12, 12, 12, 24, 24, 24, 24, 24 };
|
||||
|
||||
static const s16 masktab[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 29,
|
||||
29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34,
|
||||
34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 37, 37, 37,
|
||||
37, 37, 37, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 40,
|
||||
40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
|
||||
41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43,
|
||||
43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44,
|
||||
44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
|
||||
45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46,
|
||||
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
|
||||
46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
|
||||
47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
|
||||
48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
|
||||
49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0 };
|
||||
|
||||
|
||||
static const s16 latab[] = { 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003b, 0x003a, 0x0039,
|
||||
0x0038, 0x0037, 0x0036, 0x0035, 0x0034, 0x0034, 0x0033, 0x0032,
|
||||
0x0031, 0x0030, 0x002f, 0x002f, 0x002e, 0x002d, 0x002c, 0x002c,
|
||||
0x002b, 0x002a, 0x0029, 0x0029, 0x0028, 0x0027, 0x0026, 0x0026,
|
||||
0x0025, 0x0024, 0x0024, 0x0023, 0x0023, 0x0022, 0x0021, 0x0021,
|
||||
0x0020, 0x0020, 0x001f, 0x001e, 0x001e, 0x001d, 0x001d, 0x001c,
|
||||
0x001c, 0x001b, 0x001b, 0x001a, 0x001a, 0x0019, 0x0019, 0x0018,
|
||||
0x0018, 0x0017, 0x0017, 0x0016, 0x0016, 0x0015, 0x0015, 0x0015,
|
||||
0x0014, 0x0014, 0x0013, 0x0013, 0x0013, 0x0012, 0x0012, 0x0012,
|
||||
0x0011, 0x0011, 0x0011, 0x0010, 0x0010, 0x0010, 0x000f, 0x000f,
|
||||
0x000f, 0x000e, 0x000e, 0x000e, 0x000d, 0x000d, 0x000d, 0x000d,
|
||||
0x000c, 0x000c, 0x000c, 0x000c, 0x000b, 0x000b, 0x000b, 0x000b,
|
||||
0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0009, 0x0009, 0x0009,
|
||||
0x0009, 0x0009, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
|
||||
0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0006, 0x0006,
|
||||
0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0005, 0x0005,
|
||||
0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0004, 0x0004,
|
||||
0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
|
||||
0x0004, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
|
||||
0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0002,
|
||||
0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
|
||||
0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
|
||||
0x0002, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
|
||||
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
|
||||
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
|
||||
0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
|
||||
0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000};
|
||||
|
||||
static const s16 hth[][50] = {{ 0x04d0, 0x04d0, 0x0440, 0x0400, 0x03e0, 0x03c0, 0x03b0, 0x03b0,
|
||||
0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390,
|
||||
0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360, 0x0350, 0x0350,
|
||||
0x0340, 0x0340, 0x0330, 0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0,
|
||||
0x02f0, 0x02f0, 0x0300, 0x0310, 0x0340, 0x0390, 0x03e0, 0x0420,
|
||||
0x0460, 0x0490, 0x04a0, 0x0460, 0x0440, 0x0440, 0x0520, 0x0800,
|
||||
0x0840, 0x0840 },
|
||||
|
||||
{ 0x04f0, 0x04f0, 0x0460, 0x0410, 0x03e0, 0x03d0, 0x03c0, 0x03b0,
|
||||
0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390,
|
||||
0x0390, 0x0380, 0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360,
|
||||
0x0350, 0x0350, 0x0340, 0x0340, 0x0320, 0x0310, 0x0300, 0x02f0,
|
||||
0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0320, 0x0350, 0x0390, 0x03e0,
|
||||
0x0420, 0x0450, 0x04a0, 0x0490, 0x0460, 0x0440, 0x0480, 0x0630,
|
||||
0x0840, 0x0840 },
|
||||
|
||||
{ 0x0580, 0x0580, 0x04b0, 0x0450, 0x0420, 0x03f0, 0x03e0, 0x03d0,
|
||||
0x03c0, 0x03b0, 0x03b0, 0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0,
|
||||
0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390, 0x0390,
|
||||
0x0380, 0x0380, 0x0380, 0x0370, 0x0360, 0x0350, 0x0340, 0x0330,
|
||||
0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0310,
|
||||
0x0330, 0x0350, 0x03c0, 0x0410, 0x0470, 0x04a0, 0x0460, 0x0440,
|
||||
0x0450, 0x04e0 }};
|
||||
|
||||
|
||||
static const s16 baptab[] = { 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
|
||||
6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10,
|
||||
10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
|
||||
|
||||
static inline u16 max_value (s16 a, s16 b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
static inline u16 min_value (s16 a, s16 b)
|
||||
{
|
||||
return (a < b ? a : b);
|
||||
}
|
||||
|
||||
static inline s16 logadd (s16 a, s16 b)
|
||||
{
|
||||
s16 c;
|
||||
|
||||
if ((c = a - b) >= 0) {
|
||||
return (a + latab[min_value(((c) >> 1), 255)]);
|
||||
} else {
|
||||
return (b + latab[min_value(((-c) >> 1), 255)]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline s16 calc_lowcomp (s16 a, s16 b0, s16 b1, s16 bin)
|
||||
{
|
||||
if (bin < 7) {
|
||||
if ((b0 + 256) == b1)
|
||||
a = 384;
|
||||
else if (b0 > b1)
|
||||
a = max_value(0, a - 64);
|
||||
} else if (bin < 20) {
|
||||
if ((b0 + 256) == b1)
|
||||
a = 320;
|
||||
else if (b0 > b1)
|
||||
a = max_value(0, a - 64) ;
|
||||
} else
|
||||
a = max_value(0, a - 128);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void bit_allocate (ac3dec_t * p_ac3dec)
|
||||
{
|
||||
u16 i;
|
||||
s16 fgain;
|
||||
s16 snroffset;
|
||||
s16 start;
|
||||
s16 end;
|
||||
s16 fastleak;
|
||||
s16 slowleak;
|
||||
|
||||
/* Only perform bit_allocation if the exponents have changed or we
|
||||
* have new sideband information */
|
||||
if (p_ac3dec->audblk.chexpstr[0] == 0 && p_ac3dec->audblk.chexpstr[1] == 0 &&
|
||||
p_ac3dec->audblk.chexpstr[2] == 0 && p_ac3dec->audblk.chexpstr[3] == 0 &&
|
||||
p_ac3dec->audblk.chexpstr[4] == 0 && p_ac3dec->audblk.cplexpstr == 0 &&
|
||||
p_ac3dec->audblk.lfeexpstr == 0 && p_ac3dec->audblk.baie == 0 &&
|
||||
p_ac3dec->audblk.snroffste == 0 && p_ac3dec->audblk.deltbaie == 0)
|
||||
return;
|
||||
|
||||
/* Do some setup before we do the bit alloc */
|
||||
p_ac3dec->bit_allocate.sdecay = slowdec[p_ac3dec->audblk.sdcycod];
|
||||
p_ac3dec->bit_allocate.fdecay = fastdec[p_ac3dec->audblk.fdcycod];
|
||||
p_ac3dec->bit_allocate.sgain = slowgain[p_ac3dec->audblk.sgaincod];
|
||||
p_ac3dec->bit_allocate.dbknee = dbpbtab[p_ac3dec->audblk.dbpbcod];
|
||||
p_ac3dec->bit_allocate.floor = floortab[p_ac3dec->audblk.floorcod];
|
||||
|
||||
/* if all the SNR offset constants are zero then the whole block is zero */
|
||||
if (!p_ac3dec->audblk.csnroffst && !p_ac3dec->audblk.fsnroffst[0] &&
|
||||
!p_ac3dec->audblk.fsnroffst[1] && !p_ac3dec->audblk.fsnroffst[2] &&
|
||||
!p_ac3dec->audblk.fsnroffst[3] && !p_ac3dec->audblk.fsnroffst[4] &&
|
||||
!p_ac3dec->audblk.cplfsnroffst && !p_ac3dec->audblk.lfefsnroffst) {
|
||||
memset(p_ac3dec->audblk.fbw_bap,0,sizeof(u16) * 256 * 5);
|
||||
memset(p_ac3dec->audblk.cpl_bap,0,sizeof(u16) * 256);
|
||||
memset(p_ac3dec->audblk.lfe_bap,0,sizeof(u16) * 7);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < p_ac3dec->bsi.nfchans; i++) {
|
||||
start = 0;
|
||||
end = p_ac3dec->audblk.endmant[i] ;
|
||||
fgain = fastgain[p_ac3dec->audblk.fgaincod[i]];
|
||||
snroffset = (((p_ac3dec->audblk.csnroffst - 15) << 4) + p_ac3dec->audblk.fsnroffst[i]) << 2;
|
||||
fastleak = 0;
|
||||
slowleak = 0;
|
||||
|
||||
ba_compute_psd (&p_ac3dec->bit_allocate, start, end, p_ac3dec->audblk.fbw_exp[i]);
|
||||
|
||||
ba_compute_excitation (&p_ac3dec->bit_allocate, start, end , fgain, fastleak, slowleak, 0);
|
||||
|
||||
ba_compute_mask (&p_ac3dec->bit_allocate, start, end, p_ac3dec->syncinfo.fscod,
|
||||
p_ac3dec->audblk.deltbae[i],
|
||||
p_ac3dec->audblk.deltnseg[i],
|
||||
p_ac3dec->audblk.deltoffst[i],
|
||||
p_ac3dec->audblk.deltba[i],
|
||||
p_ac3dec->audblk.deltlen[i]);
|
||||
|
||||
ba_compute_bap (&p_ac3dec->bit_allocate, start, end, snroffset, p_ac3dec->audblk.fbw_bap[i]);
|
||||
}
|
||||
|
||||
if (p_ac3dec->audblk.cplinu) {
|
||||
start = p_ac3dec->audblk.cplstrtmant;
|
||||
end = p_ac3dec->audblk.cplendmant;
|
||||
fgain = fastgain[p_ac3dec->audblk.cplfgaincod];
|
||||
snroffset = (((p_ac3dec->audblk.csnroffst - 15) << 4) + p_ac3dec->audblk.cplfsnroffst) << 2 ;
|
||||
fastleak = (p_ac3dec->audblk.cplfleak << 8) + 768;
|
||||
slowleak = (p_ac3dec->audblk.cplsleak << 8) + 768;
|
||||
|
||||
ba_compute_psd (&p_ac3dec->bit_allocate, start, end, p_ac3dec->audblk.cpl_exp);
|
||||
|
||||
ba_compute_excitation (&p_ac3dec->bit_allocate, start, end , fgain, fastleak, slowleak, 0);
|
||||
|
||||
ba_compute_mask (&p_ac3dec->bit_allocate, start, end, p_ac3dec->syncinfo.fscod,
|
||||
p_ac3dec->audblk.cpldeltbae,
|
||||
p_ac3dec->audblk.cpldeltnseg,
|
||||
p_ac3dec->audblk.cpldeltoffst,
|
||||
p_ac3dec->audblk.cpldeltba,
|
||||
p_ac3dec->audblk.cpldeltlen);
|
||||
|
||||
ba_compute_bap (&p_ac3dec->bit_allocate, start, end, snroffset, p_ac3dec->audblk.cpl_bap);
|
||||
}
|
||||
|
||||
if (p_ac3dec->bsi.lfeon) {
|
||||
start = 0;
|
||||
end = 7;
|
||||
fgain = fastgain[p_ac3dec->audblk.lfefgaincod];
|
||||
snroffset = (((p_ac3dec->audblk.csnroffst - 15) << 4) + p_ac3dec->audblk.lfefsnroffst) << 2 ;
|
||||
fastleak = 0;
|
||||
slowleak = 0;
|
||||
|
||||
ba_compute_psd (&p_ac3dec->bit_allocate, start, end, p_ac3dec->audblk.lfe_exp);
|
||||
|
||||
ba_compute_excitation (&p_ac3dec->bit_allocate, start, end , fgain, fastleak, slowleak, 1);
|
||||
|
||||
ba_compute_mask (&p_ac3dec->bit_allocate, start, end, p_ac3dec->syncinfo.fscod, 2, 0, 0, 0, 0);
|
||||
|
||||
ba_compute_bap (&p_ac3dec->bit_allocate, start, end, snroffset, p_ac3dec->audblk.lfe_bap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ba_compute_psd (bit_allocate_t * p_bit, s16 start, s16 end, s16 exps[])
|
||||
{
|
||||
int bin,j,k;
|
||||
s16 lastbin = 0;
|
||||
|
||||
/* Map the exponents into dBs */
|
||||
for (bin=start; bin<end; bin++) {
|
||||
p_bit->psd[bin] = (3072 - (exps[bin] << 7));
|
||||
}
|
||||
|
||||
/* Integrate the psd function over each bit allocation band */
|
||||
j = start;
|
||||
k = masktab[start];
|
||||
|
||||
do {
|
||||
lastbin = min_value(bndtab[k] + bndsz[k], end);
|
||||
p_bit->bndpsd[k] = p_bit->psd[j];
|
||||
j++;
|
||||
|
||||
for (; j < lastbin; j++) {
|
||||
p_bit->bndpsd[k] = logadd(p_bit->bndpsd[k],p_bit->psd[j]);
|
||||
}
|
||||
|
||||
k++;
|
||||
} while (end > lastbin);
|
||||
}
|
||||
|
||||
static void ba_compute_excitation (bit_allocate_t * p_bit, s16 start, s16 end,
|
||||
s16 fgain, s16 fastleak, s16 slowleak, s16 is_lfe)
|
||||
{
|
||||
int bin;
|
||||
s16 bndstrt;
|
||||
s16 bndend;
|
||||
s16 lowcomp = 0;
|
||||
s16 begin = 0;
|
||||
|
||||
/* Compute excitation function */
|
||||
bndstrt = masktab[start];
|
||||
bndend = masktab[end - 1] + 1;
|
||||
|
||||
if (bndstrt == 0) { /* For fbw and lfe channels */
|
||||
lowcomp = calc_lowcomp(lowcomp, p_bit->bndpsd[0], p_bit->bndpsd[1], 0);
|
||||
p_bit->excite[0] = p_bit->bndpsd[0] - fgain - lowcomp;
|
||||
lowcomp = calc_lowcomp(lowcomp, p_bit->bndpsd[1], p_bit->bndpsd[2], 1);
|
||||
p_bit->excite[1] = p_bit->bndpsd[1] - fgain - lowcomp;
|
||||
begin = 7 ;
|
||||
|
||||
/* Note: Do not call calc_lowcomp() for the last band of the lfe channel, (bin = 6) */
|
||||
for (bin = 2; bin < 7; bin++) {
|
||||
if (!(is_lfe && (bin == 6)))
|
||||
lowcomp = calc_lowcomp (lowcomp, p_bit->bndpsd[bin], p_bit->bndpsd[bin+1], bin);
|
||||
fastleak = p_bit->bndpsd[bin] - fgain;
|
||||
slowleak = p_bit->bndpsd[bin] - p_bit->sgain;
|
||||
p_bit->excite[bin] = fastleak - lowcomp;
|
||||
|
||||
if (!(is_lfe && (bin == 6))) {
|
||||
if (p_bit->bndpsd[bin] <=
|
||||
p_bit->bndpsd[bin+1])
|
||||
{
|
||||
begin = bin + 1 ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (bin = begin; bin < min_value(bndend, 22); bin++) {
|
||||
if (!(is_lfe && (bin == 6)))
|
||||
lowcomp = calc_lowcomp (lowcomp, p_bit->bndpsd[bin],
|
||||
p_bit->bndpsd[bin+1], bin);
|
||||
fastleak -= p_bit->fdecay ;
|
||||
fastleak = max_value(fastleak, p_bit->bndpsd[bin] - fgain);
|
||||
slowleak -= p_bit->sdecay ;
|
||||
slowleak = max_value(slowleak, p_bit->bndpsd[bin] - p_bit->sgain);
|
||||
p_bit->excite[bin] = max_value(fastleak - lowcomp, slowleak);
|
||||
}
|
||||
begin = 22;
|
||||
} else { /* For coupling channel */
|
||||
begin = bndstrt;
|
||||
}
|
||||
|
||||
for (bin = begin; bin < bndend; bin++) {
|
||||
fastleak -= p_bit->fdecay;
|
||||
fastleak = max_value(fastleak, p_bit->bndpsd[bin] - fgain);
|
||||
slowleak -= p_bit->sdecay;
|
||||
slowleak = max_value(slowleak, p_bit->bndpsd[bin] - p_bit->sgain);
|
||||
p_bit->excite[bin] = max_value(fastleak, slowleak) ;
|
||||
}
|
||||
}
|
||||
|
||||
static void ba_compute_mask (bit_allocate_t * p_bit, s16 start, s16 end, u16 fscod,
|
||||
u16 deltbae, u16 deltnseg, u16 deltoffst[],
|
||||
u16 deltba[], u16 deltlen[])
|
||||
{
|
||||
int bin,k;
|
||||
s16 bndstrt;
|
||||
s16 bndend;
|
||||
s16 delta;
|
||||
|
||||
bndstrt = masktab[start];
|
||||
bndend = masktab[end - 1] + 1;
|
||||
|
||||
/* Compute the masking curve */
|
||||
for (bin = bndstrt; bin < bndend; bin++) {
|
||||
if (p_bit->bndpsd[bin] < p_bit->dbknee) {
|
||||
p_bit->excite[bin] += ((p_bit->dbknee - p_bit->bndpsd[bin]) >> 2);
|
||||
}
|
||||
p_bit->mask[bin] = max_value(p_bit->excite[bin], hth[fscod][bin]);
|
||||
}
|
||||
|
||||
/* Perform delta bit modulation if necessary */
|
||||
if ((deltbae == DELTA_BIT_REUSE) || (deltbae == DELTA_BIT_NEW)) {
|
||||
s16 band = 0;
|
||||
s16 seg = 0;
|
||||
|
||||
for (seg = 0; seg < deltnseg+1; seg++) {
|
||||
band += deltoffst[seg];
|
||||
if (deltba[seg] >= 4) {
|
||||
delta = (deltba[seg] - 3) << 7;
|
||||
} else {
|
||||
delta = (deltba[seg] - 4) << 7;
|
||||
}
|
||||
for (k = 0; k < deltlen[seg]; k++) {
|
||||
p_bit->mask[band] += delta;
|
||||
band++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ba_compute_bap (bit_allocate_t * p_bit, s16 start, s16 end, s16 snroffset,
|
||||
s16 bap[])
|
||||
{
|
||||
int i,j,k;
|
||||
s16 lastbin = 0;
|
||||
s16 address = 0;
|
||||
|
||||
/* Compute the bit allocation pointer for each bin */
|
||||
i = start;
|
||||
j = masktab[start];
|
||||
|
||||
do {
|
||||
lastbin = min_value(bndtab[j] + bndsz[j], end);
|
||||
p_bit->mask[j] -= snroffset;
|
||||
p_bit->mask[j] -= p_bit->floor;
|
||||
|
||||
if (p_bit->mask[j] < 0)
|
||||
p_bit->mask[j] = 0;
|
||||
|
||||
p_bit->mask[j] &= 0x1fe0;
|
||||
p_bit->mask[j] += p_bit->floor;
|
||||
for (k = i; k < lastbin; k++) {
|
||||
address = (p_bit->psd[i] - p_bit->mask[j]) >> 5;
|
||||
address = min_value(63, max_value(0, address));
|
||||
bap[i] = baptab[address];
|
||||
i++;
|
||||
}
|
||||
j++;
|
||||
} while (end > lastbin);
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_decoder.c: core ac3 decoder
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: ac3_decoder.c,v 1.9 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Michel Kaempf <maxx@via.ecp.fr>
|
||||
* Michel Lespinasse <walken@zoy.org>
|
||||
* Aaron Holtzman <aholtzma@engr.uvic.ca>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <string.h> /* memcpy() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/decoder.h>
|
||||
|
||||
#include "ac3_imdct.h"
|
||||
#include "ac3_downmix.h"
|
||||
#include "ac3_adec.h" /* ac3dec_thread_t */
|
||||
|
||||
#include "ac3_internal.h"
|
||||
|
||||
static const float cmixlev_lut[4] = { 0.707, 0.595, 0.500, 0.707 };
|
||||
static const float smixlev_lut[4] = { 0.707, 0.500, 0.0 , 0.500 };
|
||||
|
||||
int E_( ac3_init )(ac3dec_t * p_ac3dec)
|
||||
{
|
||||
p_ac3dec->mantissa.lfsr_state = 1; /* dither_gen initialization */
|
||||
E_( imdct_init )(p_ac3dec->p_imdct) ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ac3_decode_frame (ac3dec_t * p_ac3dec, s16 * buffer)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (parse_bsi (p_ac3dec))
|
||||
{
|
||||
msg_Warn( p_ac3dec->p_fifo, "parse error" );
|
||||
parse_auxdata (p_ac3dec);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* compute downmix parameters
|
||||
* downmix to tow channels for now */
|
||||
p_ac3dec->dm_par.clev = 0.0;
|
||||
p_ac3dec->dm_par.slev = 0.0;
|
||||
p_ac3dec->dm_par.unit = 1.0;
|
||||
if (p_ac3dec->bsi.acmod & 0x1) /* have center */
|
||||
p_ac3dec->dm_par.clev = cmixlev_lut[p_ac3dec->bsi.cmixlev];
|
||||
|
||||
if (p_ac3dec->bsi.acmod & 0x4) /* have surround channels */
|
||||
p_ac3dec->dm_par.slev = smixlev_lut[p_ac3dec->bsi.surmixlev];
|
||||
|
||||
p_ac3dec->dm_par.unit /= 1.0 + p_ac3dec->dm_par.clev + p_ac3dec->dm_par.slev;
|
||||
p_ac3dec->dm_par.clev *= p_ac3dec->dm_par.unit;
|
||||
p_ac3dec->dm_par.slev *= p_ac3dec->dm_par.unit;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
/* Initialize freq/time sample storage */
|
||||
memset(p_ac3dec->samples, 0, sizeof(float) * 256 *
|
||||
(p_ac3dec->bsi.nfchans + p_ac3dec->bsi.lfeon));
|
||||
|
||||
|
||||
if( p_ac3dec->p_fifo->b_die || p_ac3dec->p_fifo->b_error )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( parse_audblk( p_ac3dec, i ) )
|
||||
{
|
||||
msg_Warn( p_ac3dec->p_fifo, "audioblock error" );
|
||||
parse_auxdata( p_ac3dec );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( p_ac3dec->p_fifo->b_die || p_ac3dec->p_fifo->b_error )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( exponent_unpack( p_ac3dec ) )
|
||||
{
|
||||
msg_Warn( p_ac3dec->p_fifo, "unpack error" );
|
||||
parse_auxdata( p_ac3dec );
|
||||
return 1;
|
||||
}
|
||||
|
||||
bit_allocate (p_ac3dec);
|
||||
mantissa_unpack (p_ac3dec);
|
||||
|
||||
if( p_ac3dec->p_fifo->b_die || p_ac3dec->p_fifo->b_error )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (p_ac3dec->bsi.acmod == 0x2)
|
||||
{
|
||||
rematrix (p_ac3dec);
|
||||
}
|
||||
|
||||
imdct (p_ac3dec, buffer);
|
||||
|
||||
buffer += 2 * 256;
|
||||
}
|
||||
|
||||
parse_auxdata (p_ac3dec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,385 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_decoder.h : ac3 decoder interface
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000 VideoLAN
|
||||
* $Id: ac3_decoder.h,v 1.5 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Michel Kaempf <maxx@via.ecp.fr>
|
||||
* Renaud Dartus <reno@videolan.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/**** ac3 decoder API - public ac3 decoder structures */
|
||||
|
||||
typedef struct ac3dec_s ac3dec_t;
|
||||
|
||||
typedef struct ac3_sync_info_s {
|
||||
int sample_rate; /* sample rate in Hz */
|
||||
int frame_size; /* frame size in bytes */
|
||||
int bit_rate; /* nominal bit rate in kbps */
|
||||
} ac3_sync_info_t;
|
||||
|
||||
|
||||
/**** ac3 decoder API - functions publically provided by the ac3 decoder ****/
|
||||
|
||||
int E_( ac3_init )(ac3dec_t * p_ac3dec);
|
||||
int ac3_sync_frame (ac3dec_t * p_ac3dec, ac3_sync_info_t * p_sync_info);
|
||||
int ac3_decode_frame (ac3dec_t * p_ac3dec, s16 * buffer);
|
||||
|
||||
/**** EVERYTHING AFTER THIS POINT IS PRIVATE ! DO NOT USE DIRECTLY ****/
|
||||
|
||||
/**** ac3 decoder internal structures ****/
|
||||
|
||||
/* The following structures are filled in by their corresponding parse_*
|
||||
* functions. See http://www.atsc.org/Standards/A52/a_52.pdf for
|
||||
* full details on each field. Indented fields are used to denote
|
||||
* conditional fields.
|
||||
*/
|
||||
|
||||
typedef struct syncinfo_s {
|
||||
/* Sync word == 0x0B77 */
|
||||
/* u16 syncword; */
|
||||
/* crc for the first 5/8 of the sync block */
|
||||
/* u16 crc1; */
|
||||
/* Stream Sampling Rate (kHz) 0 = 48, 1 = 44.1, 2 = 32, 3 = reserved */
|
||||
u16 fscod;
|
||||
/* Frame size code */
|
||||
u16 frmsizecod;
|
||||
|
||||
/* Information not in the AC-3 bitstream, but derived */
|
||||
/* Frame size in 16 bit words */
|
||||
u16 frame_size;
|
||||
/* Bit rate in kilobits */
|
||||
//u16 bit_rate;
|
||||
} syncinfo_t;
|
||||
|
||||
typedef struct bsi_s {
|
||||
/* Bit stream identification == 0x8 */
|
||||
u16 bsid;
|
||||
/* Bit stream mode */
|
||||
u16 bsmod;
|
||||
/* Audio coding mode */
|
||||
u16 acmod;
|
||||
/* If we're using the centre channel then */
|
||||
/* centre mix level */
|
||||
u16 cmixlev;
|
||||
/* If we're using the surround channel then */
|
||||
/* surround mix level */
|
||||
u16 surmixlev;
|
||||
/* If we're in 2/0 mode then */
|
||||
/* Dolby surround mix level - NOT USED - */
|
||||
u16 dsurmod;
|
||||
/* Low frequency effects on */
|
||||
u16 lfeon;
|
||||
/* Dialogue Normalization level */
|
||||
u16 dialnorm;
|
||||
/* Compression exists */
|
||||
u16 compre;
|
||||
/* Compression level */
|
||||
u16 compr;
|
||||
/* Language code exists */
|
||||
u16 langcode;
|
||||
/* Language code */
|
||||
u16 langcod;
|
||||
/* Audio production info exists*/
|
||||
u16 audprodie;
|
||||
u16 mixlevel;
|
||||
u16 roomtyp;
|
||||
/* If we're in dual mono mode (acmod == 0) then extra stuff */
|
||||
u16 dialnorm2;
|
||||
u16 compr2e;
|
||||
u16 compr2;
|
||||
u16 langcod2e;
|
||||
u16 langcod2;
|
||||
u16 audprodi2e;
|
||||
u16 mixlevel2;
|
||||
u16 roomtyp2;
|
||||
/* Copyright bit */
|
||||
u16 copyrightb;
|
||||
/* Original bit */
|
||||
u16 origbs;
|
||||
/* Timecode 1 exists */
|
||||
u16 timecod1e;
|
||||
/* Timecode 1 */
|
||||
u16 timecod1;
|
||||
/* Timecode 2 exists */
|
||||
u16 timecod2e;
|
||||
/* Timecode 2 */
|
||||
u16 timecod2;
|
||||
/* Additional bit stream info exists */
|
||||
u16 addbsie;
|
||||
/* Additional bit stream length - 1 (in bytes) */
|
||||
u16 addbsil;
|
||||
/* Additional bit stream information (max 64 bytes) */
|
||||
u8 addbsi[64];
|
||||
|
||||
/* Information not in the AC-3 bitstream, but derived */
|
||||
/* Number of channels (excluding LFE)
|
||||
* Derived from acmod */
|
||||
u16 nfchans;
|
||||
} bsi_t;
|
||||
|
||||
/* more pain */
|
||||
typedef struct audblk_s {
|
||||
/* block switch bit indexed by channel num */
|
||||
u16 blksw[5];
|
||||
/* dither enable bit indexed by channel num */
|
||||
u16 dithflag[5];
|
||||
/* dynamic range gain exists */
|
||||
u16 dynrnge;
|
||||
/* dynamic range gain */
|
||||
u16 dynrng;
|
||||
/* if acmod==0 then */
|
||||
/* dynamic range 2 gain exists */
|
||||
u16 dynrng2e;
|
||||
/* dynamic range 2 gain */
|
||||
u16 dynrng2;
|
||||
/* coupling strategy exists */
|
||||
u16 cplstre;
|
||||
/* coupling in use */
|
||||
u16 cplinu;
|
||||
/* channel coupled */
|
||||
u16 chincpl[5];
|
||||
/* if acmod==2 then */
|
||||
/* Phase flags in use */
|
||||
u16 phsflginu;
|
||||
/* coupling begin frequency code */
|
||||
u16 cplbegf;
|
||||
/* coupling end frequency code */
|
||||
u16 cplendf;
|
||||
/* coupling band structure bits */
|
||||
u16 cplbndstrc[18];
|
||||
/* Do coupling co-ords exist for this channel? */
|
||||
u16 cplcoe[5];
|
||||
/* Master coupling co-ordinate */
|
||||
u16 mstrcplco[5];
|
||||
/* Per coupling band coupling co-ordinates */
|
||||
u16 cplcoexp[5][18];
|
||||
u16 cplcomant[5][18];
|
||||
/* Phase flags for dual mono */
|
||||
u16 phsflg[18];
|
||||
/* Is there a rematrixing strategy */
|
||||
u16 rematstr;
|
||||
/* Rematrixing bits */
|
||||
u16 rematflg[4];
|
||||
/* Coupling exponent strategy */
|
||||
u16 cplexpstr;
|
||||
/* Exponent strategy for full bandwidth channels */
|
||||
u16 chexpstr[5];
|
||||
/* Exponent strategy for lfe channel */
|
||||
u16 lfeexpstr;
|
||||
/* Channel bandwidth for independent channels */
|
||||
u16 chbwcod[5];
|
||||
/* The absolute coupling exponent */
|
||||
u16 cplabsexp;
|
||||
/* Coupling channel exponents (D15 mode gives 18 * 12 /3 encoded exponents */
|
||||
u16 cplexps[18 * 12 / 3];
|
||||
/* Sanity checking constant */
|
||||
u32 magic2;
|
||||
/* fbw channel exponents */
|
||||
u16 exps[5][252 / 3];
|
||||
/* channel gain range */
|
||||
u16 gainrng[5];
|
||||
/* low frequency exponents */
|
||||
u16 lfeexps[3];
|
||||
|
||||
/* Bit allocation info */
|
||||
u16 baie;
|
||||
/* Slow decay code */
|
||||
u16 sdcycod;
|
||||
/* Fast decay code */
|
||||
u16 fdcycod;
|
||||
/* Slow gain code */
|
||||
u16 sgaincod;
|
||||
/* dB per bit code */
|
||||
u16 dbpbcod;
|
||||
/* masking floor code */
|
||||
u16 floorcod;
|
||||
|
||||
/* SNR offset info */
|
||||
u16 snroffste;
|
||||
/* coarse SNR offset */
|
||||
u16 csnroffst;
|
||||
/* coupling fine SNR offset */
|
||||
u16 cplfsnroffst;
|
||||
/* coupling fast gain code */
|
||||
u16 cplfgaincod;
|
||||
/* fbw fine SNR offset */
|
||||
u16 fsnroffst[5];
|
||||
/* fbw fast gain code */
|
||||
u16 fgaincod[5];
|
||||
/* lfe fine SNR offset */
|
||||
u16 lfefsnroffst;
|
||||
/* lfe fast gain code */
|
||||
u16 lfefgaincod;
|
||||
|
||||
/* Coupling leak info */
|
||||
u16 cplleake;
|
||||
/* coupling fast leak initialization */
|
||||
u16 cplfleak;
|
||||
/* coupling slow leak initialization */
|
||||
u16 cplsleak;
|
||||
|
||||
/* delta bit allocation info */
|
||||
u16 deltbaie;
|
||||
/* coupling delta bit allocation exists */
|
||||
u16 cpldeltbae;
|
||||
/* fbw delta bit allocation exists */
|
||||
u16 deltbae[5];
|
||||
/* number of cpl delta bit segments */
|
||||
u16 cpldeltnseg;
|
||||
/* coupling delta bit allocation offset */
|
||||
u16 cpldeltoffst[8];
|
||||
/* coupling delta bit allocation length */
|
||||
u16 cpldeltlen[8];
|
||||
/* coupling delta bit allocation length */
|
||||
u16 cpldeltba[8];
|
||||
/* number of delta bit segments */
|
||||
u16 deltnseg[5];
|
||||
/* fbw delta bit allocation offset */
|
||||
u16 deltoffst[5][8];
|
||||
/* fbw delta bit allocation length */
|
||||
u16 deltlen[5][8];
|
||||
/* fbw delta bit allocation length */
|
||||
u16 deltba[5][8];
|
||||
|
||||
/* skip length exists */
|
||||
u16 skiple;
|
||||
/* skip length */
|
||||
u16 skipl;
|
||||
|
||||
/* channel mantissas */
|
||||
// u16 chmant[5][256];
|
||||
|
||||
/* coupling mantissas */
|
||||
float cpl_flt[ 256 ];
|
||||
// u16 cplmant[256];
|
||||
|
||||
/* coupling mantissas */
|
||||
// u16 lfemant[7];
|
||||
|
||||
/* -- Information not in the bitstream, but derived thereof -- */
|
||||
|
||||
/* Number of coupling sub-bands */
|
||||
u16 ncplsubnd;
|
||||
|
||||
/* Number of combined coupling sub-bands
|
||||
* Derived from ncplsubnd and cplbndstrc */
|
||||
u16 ncplbnd;
|
||||
|
||||
/* Number of exponent groups by channel
|
||||
* Derived from strmant, endmant */
|
||||
u16 nchgrps[5];
|
||||
|
||||
/* Number of coupling exponent groups
|
||||
* Derived from cplbegf, cplendf, cplexpstr */
|
||||
u16 ncplgrps;
|
||||
|
||||
/* End mantissa numbers of fbw channels */
|
||||
u16 endmant[5];
|
||||
|
||||
/* Start and end mantissa numbers for the coupling channel */
|
||||
u16 cplstrtmant;
|
||||
u16 cplendmant;
|
||||
|
||||
/* Decoded exponent info */
|
||||
u16 fbw_exp[5][256];
|
||||
u16 cpl_exp[256];
|
||||
u16 lfe_exp[7];
|
||||
|
||||
/* Bit allocation pointer results */
|
||||
u16 fbw_bap[5][256];
|
||||
/* FIXME?? figure out exactly how many entries there should be (253-37?) */
|
||||
u16 cpl_bap[256];
|
||||
u16 lfe_bap[7];
|
||||
} audblk_t;
|
||||
|
||||
/* Everything you wanted to know about band structure */
|
||||
|
||||
/*
|
||||
* The entire frequency domain is represented by 256 real
|
||||
* floating point fourier coefficients. Only the lower 253
|
||||
* coefficients are actually utilized however. We use arrays
|
||||
* of 256 to be efficient in some cases.
|
||||
*
|
||||
* The 5 full bandwidth channels (fbw) can have their higher
|
||||
* frequencies coupled together. These coupled channels then
|
||||
* share their high frequency components.
|
||||
*
|
||||
* This coupling band is broken up into 18 sub-bands starting
|
||||
* at mantissa number 37. Each sub-band is 12 bins wide.
|
||||
*
|
||||
* There are 50 bit allocation sub-bands which cover the entire
|
||||
* frequency range. The sub-bands are of non-uniform width, and
|
||||
* approximate a 1/6 octave scale.
|
||||
*/
|
||||
|
||||
typedef struct bit_allocate_s
|
||||
{
|
||||
s16 psd[256];
|
||||
s16 bndpsd[256];
|
||||
s16 excite[256];
|
||||
s16 mask[256];
|
||||
s16 sdecay;
|
||||
s16 fdecay;
|
||||
s16 sgain;
|
||||
s16 dbknee;
|
||||
s16 floor;
|
||||
} bit_allocate_t;
|
||||
|
||||
/* These store the persistent state of the packed mantissas */
|
||||
typedef struct mantissa_s
|
||||
{
|
||||
float q_1[2];
|
||||
float q_2[2];
|
||||
float q_4[1];
|
||||
s32 q_1_pointer;
|
||||
s32 q_2_pointer;
|
||||
s32 q_4_pointer;
|
||||
u16 lfsr_state;
|
||||
} mantissa_t;
|
||||
|
||||
struct ac3dec_s
|
||||
{
|
||||
float * samples;
|
||||
void * samples_orig; /* pointer before memalign */
|
||||
imdct_t * imdct;
|
||||
void * imdct_orig; /* pointer before memalign */
|
||||
|
||||
/*
|
||||
* Input properties
|
||||
*/
|
||||
|
||||
/* The bit stream structure handles the PES stream at the bit level */
|
||||
bit_stream_t bit_stream;
|
||||
int i_available;
|
||||
unsigned int total_bits_read; /* temporary */
|
||||
|
||||
/*
|
||||
* Decoder properties
|
||||
*/
|
||||
syncinfo_t syncinfo;
|
||||
bsi_t bsi;
|
||||
audblk_t audblk;
|
||||
|
||||
dm_par_t dm_par;
|
||||
|
||||
bit_allocate_t bit_allocate;
|
||||
mantissa_t mantissa;
|
||||
downmix_t downmix;
|
||||
|
||||
};
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_exponent.c: ac3 exponent calculations
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: ac3_exponent.c,v 1.7 2002/06/01 12:31:58 sam Exp $
|
||||
*
|
||||
* Authors: Michel Kaempf <maxx@via.ecp.fr>
|
||||
* Michel Lespinasse <walken@zoy.org>
|
||||
* Aaron Holtzman <aholtzma@engr.uvic.ca>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <string.h> /* memcpy(), memset() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/decoder.h>
|
||||
|
||||
#include "ac3_imdct.h"
|
||||
#include "ac3_downmix.h"
|
||||
#include "ac3_adec.h"
|
||||
|
||||
#include "ac3_internal.h"
|
||||
|
||||
#include "ac3_exponent.h"
|
||||
|
||||
int exponent_unpack (ac3dec_t * p_ac3dec)
|
||||
{
|
||||
u16 i;
|
||||
|
||||
for (i = 0; i < p_ac3dec->bsi.nfchans; i++)
|
||||
{
|
||||
if (exp_unpack_ch (p_ac3dec, UNPACK_FBW, p_ac3dec->audblk.chexpstr[i],
|
||||
p_ac3dec->audblk.nchgrps[i],
|
||||
p_ac3dec->audblk.exps[i][0],
|
||||
&p_ac3dec->audblk.exps[i][1],
|
||||
p_ac3dec->audblk.fbw_exp[i]))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_ac3dec->audblk.cplinu)
|
||||
{
|
||||
if (exp_unpack_ch (p_ac3dec, UNPACK_CPL, p_ac3dec->audblk.cplexpstr,
|
||||
p_ac3dec->audblk.ncplgrps,
|
||||
p_ac3dec->audblk.cplabsexp << 1,
|
||||
p_ac3dec->audblk.cplexps,
|
||||
&p_ac3dec->audblk.cpl_exp[p_ac3dec->audblk.cplstrtmant]))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_ac3dec->bsi.lfeon)
|
||||
{
|
||||
if (exp_unpack_ch (p_ac3dec, UNPACK_LFE, p_ac3dec->audblk.lfeexpstr,
|
||||
2, p_ac3dec->audblk.lfeexps[0],
|
||||
&p_ac3dec->audblk.lfeexps[1],
|
||||
p_ac3dec->audblk.lfe_exp))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_exponent.h: ac3 exponent calculations
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000 VideoLAN
|
||||
* $Id: ac3_exponent.h,v 1.3 2002/06/01 12:31:58 sam Exp $
|
||||
*
|
||||
* Authors: Michel Kaempf <maxx@via.ecp.fr>
|
||||
* Michel Lespinasse <walken@zoy.org>
|
||||
* Aaron Holtzman <aholtzma@engr.uvic.ca>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
static const s16 exps_1[128] =
|
||||
{
|
||||
-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
static const s16 exps_2[128] =
|
||||
{
|
||||
-2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
|
||||
-2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
|
||||
-2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
|
||||
-2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
|
||||
-2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
static const s16 exps_3[128] =
|
||||
{
|
||||
-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
|
||||
-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
|
||||
-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
|
||||
-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
|
||||
-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
#define UNPACK_FBW 1
|
||||
#define UNPACK_CPL 2
|
||||
#define UNPACK_LFE 4
|
||||
|
||||
static inline int exp_unpack_ch( ac3dec_t * p_ac3dec, u16 type,
|
||||
u16 expstr, u16 ngrps, u16 initial_exp,
|
||||
u16 exps[], u16 * dest )
|
||||
{
|
||||
u16 i,j;
|
||||
s16 exp_acc;
|
||||
|
||||
if (expstr == EXP_REUSE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle the initial absolute exponent */
|
||||
exp_acc = initial_exp;
|
||||
j = 0;
|
||||
|
||||
/* In the case of a fbw channel then the initial absolute values is
|
||||
* also an exponent */
|
||||
if (type != UNPACK_CPL)
|
||||
{
|
||||
dest[j++] = exp_acc;
|
||||
}
|
||||
|
||||
/* Loop through the groups and fill the dest array appropriately */
|
||||
switch (expstr)
|
||||
{
|
||||
case EXP_D15: /* 1 */
|
||||
for (i = 0; i < ngrps; i++)
|
||||
{
|
||||
if (exps[i] > 124)
|
||||
{
|
||||
msg_Err( p_ac3dec->p_fifo, "invalid exponent" );
|
||||
return 1;
|
||||
}
|
||||
exp_acc += (exps_1[exps[i]] /*- 2*/);
|
||||
dest[j++] = exp_acc;
|
||||
exp_acc += (exps_2[exps[i]] /*- 2*/);
|
||||
dest[j++] = exp_acc;
|
||||
exp_acc += (exps_3[exps[i]] /*- 2*/);
|
||||
dest[j++] = exp_acc;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXP_D25: /* 2 */
|
||||
for (i = 0; i < ngrps; i++)
|
||||
{
|
||||
if (exps[i] > 124)
|
||||
{
|
||||
msg_Err( p_ac3dec->p_fifo, "invalid exponent" );
|
||||
return 1;
|
||||
}
|
||||
exp_acc += (exps_1[exps[i]] /*- 2*/);
|
||||
dest[j++] = exp_acc;
|
||||
dest[j++] = exp_acc;
|
||||
exp_acc += (exps_2[exps[i]] /*- 2*/);
|
||||
dest[j++] = exp_acc;
|
||||
dest[j++] = exp_acc;
|
||||
exp_acc += (exps_3[exps[i]] /*- 2*/);
|
||||
dest[j++] = exp_acc;
|
||||
dest[j++] = exp_acc;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXP_D45: /* 3 */
|
||||
for (i = 0; i < ngrps; i++)
|
||||
{
|
||||
if (exps[i] > 124)
|
||||
{
|
||||
msg_Err( p_ac3dec->p_fifo, "invalid exponent" );
|
||||
return 1;
|
||||
}
|
||||
exp_acc += (exps_1[exps[i]] /*- 2*/);
|
||||
dest[j++] = exp_acc;
|
||||
dest[j++] = exp_acc;
|
||||
dest[j++] = exp_acc;
|
||||
dest[j++] = exp_acc;
|
||||
exp_acc += (exps_2[exps[i]] /*- 2*/);
|
||||
dest[j++] = exp_acc;
|
||||
dest[j++] = exp_acc;
|
||||
dest[j++] = exp_acc;
|
||||
dest[j++] = exp_acc;
|
||||
exp_acc += (exps_3[exps[i]] /*- 2*/);
|
||||
dest[j++] = exp_acc;
|
||||
dest[j++] = exp_acc;
|
||||
dest[j++] = exp_acc;
|
||||
dest[j++] = exp_acc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,262 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_imdct.c: ac3 DCT
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: ac3_imdct.c,v 1.10 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Michel Kaempf <maxx@via.ecp.fr>
|
||||
* Aaron Holtzman <aholtzma@engr.uvic.ca>
|
||||
* Renaud Dartus <reno@videolan.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <string.h> /* memcpy() */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/decoder.h>
|
||||
|
||||
#include "ac3_imdct.h"
|
||||
#include "ac3_downmix.h"
|
||||
#include "ac3_adec.h"
|
||||
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
void E_( imdct_init )(imdct_t * p_imdct)
|
||||
{
|
||||
int i;
|
||||
float scale = 181.019;
|
||||
|
||||
p_imdct->pf_imdct_init( p_imdct );
|
||||
|
||||
/* More twiddle factors to turn IFFT into IMDCT */
|
||||
for (i=0; i < 64; i++) {
|
||||
p_imdct->xcos2[i] = cos(2.0f * M_PI * (8*i+1)/(4*N)) * scale;
|
||||
p_imdct->xsin2[i] = sin(2.0f * M_PI * (8*i+1)/(4*N)) * scale;
|
||||
}
|
||||
}
|
||||
|
||||
void imdct (ac3dec_t * p_ac3dec, s16 * buffer)
|
||||
{
|
||||
int i;
|
||||
int doable = 0;
|
||||
float *center=NULL, *left, *right, *left_sur, *right_sur;
|
||||
float *delay_left, *delay_right;
|
||||
float *delay1_left, *delay1_right, *delay1_center, *delay1_sr, *delay1_sl;
|
||||
float right_tmp, left_tmp;
|
||||
void (*do_imdct)(imdct_t * p_imdct, float data[], float delay[]);
|
||||
|
||||
/* test if dm in frequency is doable */
|
||||
if (!(doable = p_ac3dec->audblk.blksw[0]))
|
||||
{
|
||||
do_imdct = p_ac3dec->p_imdct->pf_imdct_512;
|
||||
}
|
||||
else
|
||||
{
|
||||
do_imdct = p_ac3dec->p_imdct->pf_imdct_256;
|
||||
}
|
||||
|
||||
/* downmix in the frequency domain if all the channels
|
||||
* use the same imdct */
|
||||
for (i=0; i < p_ac3dec->bsi.nfchans; i++)
|
||||
{
|
||||
if (doable != p_ac3dec->audblk.blksw[i])
|
||||
{
|
||||
do_imdct = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_imdct)
|
||||
{
|
||||
/* dowmix first and imdct */
|
||||
switch(p_ac3dec->bsi.acmod)
|
||||
{
|
||||
case 7: /* 3/2 */
|
||||
p_ac3dec->p_downmix->pf_downmix_3f_2r_to_2ch (p_ac3dec->samples, &p_ac3dec->dm_par);
|
||||
break;
|
||||
case 6: /* 2/2 */
|
||||
p_ac3dec->p_downmix->pf_downmix_2f_2r_to_2ch (p_ac3dec->samples, &p_ac3dec->dm_par);
|
||||
break;
|
||||
case 5: /* 3/1 */
|
||||
p_ac3dec->p_downmix->pf_downmix_3f_1r_to_2ch (p_ac3dec->samples, &p_ac3dec->dm_par);
|
||||
break;
|
||||
case 4: /* 2/1 */
|
||||
p_ac3dec->p_downmix->pf_downmix_2f_1r_to_2ch (p_ac3dec->samples, &p_ac3dec->dm_par);
|
||||
break;
|
||||
case 3: /* 3/0 */
|
||||
p_ac3dec->p_downmix->pf_downmix_3f_0r_to_2ch (p_ac3dec->samples, &p_ac3dec->dm_par);
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
default: /* 1/0 */
|
||||
// if (p_ac3dec->bsi.acmod == 1)
|
||||
center = p_ac3dec->samples;
|
||||
// else if (p_ac3dec->bsi.acmod == 0)
|
||||
// center = samples[ac3_config.dual_mono_ch_sel];
|
||||
do_imdct(p_ac3dec->p_imdct, center, p_ac3dec->p_imdct->delay); /* no downmix*/
|
||||
|
||||
p_ac3dec->p_downmix->pf_stream_sample_1ch_to_s16 (buffer, center);
|
||||
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
do_imdct (p_ac3dec->p_imdct, p_ac3dec->samples, p_ac3dec->p_imdct->delay);
|
||||
do_imdct (p_ac3dec->p_imdct, p_ac3dec->samples+256, p_ac3dec->p_imdct->delay+256);
|
||||
p_ac3dec->p_downmix->pf_stream_sample_2ch_to_s16(buffer, p_ac3dec->samples, p_ac3dec->samples+256);
|
||||
|
||||
} else {
|
||||
/* imdct and then downmix
|
||||
* delay and samples should be saved and mixed
|
||||
* fprintf(stderr, "time domain downmix\n"); */
|
||||
for (i=0; i<p_ac3dec->bsi.nfchans; i++)
|
||||
{
|
||||
if (p_ac3dec->audblk.blksw[i])
|
||||
{
|
||||
/* There is only a C function */
|
||||
p_ac3dec->p_imdct->pf_imdct_256_nol( p_ac3dec->p_imdct,
|
||||
p_ac3dec->samples+256*i, p_ac3dec->p_imdct->delay1+256*i );
|
||||
}
|
||||
else
|
||||
{
|
||||
p_ac3dec->p_imdct->pf_imdct_512_nol( p_ac3dec->p_imdct,
|
||||
p_ac3dec->samples+256*i, p_ac3dec->p_imdct->delay1+256*i );
|
||||
}
|
||||
}
|
||||
|
||||
/* mix the sample, overlap */
|
||||
switch(p_ac3dec->bsi.acmod)
|
||||
{
|
||||
case 7: /* 3/2 */
|
||||
left = p_ac3dec->samples;
|
||||
center = p_ac3dec->samples+256;
|
||||
right = p_ac3dec->samples+2*256;
|
||||
left_sur = p_ac3dec->samples+3*256;
|
||||
right_sur = p_ac3dec->samples+4*256;
|
||||
delay_left = p_ac3dec->p_imdct->delay;
|
||||
delay_right = p_ac3dec->p_imdct->delay+256;
|
||||
delay1_left = p_ac3dec->p_imdct->delay1;
|
||||
delay1_center = p_ac3dec->p_imdct->delay1+256;
|
||||
delay1_right = p_ac3dec->p_imdct->delay1+2*256;
|
||||
delay1_sl = p_ac3dec->p_imdct->delay1+3*256;
|
||||
delay1_sr = p_ac3dec->p_imdct->delay1+4*256;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
left_tmp = p_ac3dec->dm_par.unit * *left++ + p_ac3dec->dm_par.clev * *center + p_ac3dec->dm_par.slev * *left_sur++;
|
||||
right_tmp= p_ac3dec->dm_par.unit * *right++ + p_ac3dec->dm_par.clev * *center++ + p_ac3dec->dm_par.slev * *right_sur++;
|
||||
*buffer++ = (s16)(left_tmp + *delay_left);
|
||||
*buffer++ = (s16)(right_tmp + *delay_right);
|
||||
*delay_left++ = p_ac3dec->dm_par.unit * *delay1_left++ + p_ac3dec->dm_par.clev * *delay1_center + p_ac3dec->dm_par.slev * *delay1_sl++;
|
||||
*delay_right++ = p_ac3dec->dm_par.unit * *delay1_right++ + p_ac3dec->dm_par.clev * *center++ + p_ac3dec->dm_par.slev * *delay1_sr++;
|
||||
}
|
||||
break;
|
||||
case 6: /* 2/2 */
|
||||
left = p_ac3dec->samples;
|
||||
right = p_ac3dec->samples+256;
|
||||
left_sur = p_ac3dec->samples+2*256;
|
||||
right_sur = p_ac3dec->samples+3*256;
|
||||
delay_left = p_ac3dec->p_imdct->delay;
|
||||
delay_right = p_ac3dec->p_imdct->delay+256;
|
||||
delay1_left = p_ac3dec->p_imdct->delay1;
|
||||
delay1_right = p_ac3dec->p_imdct->delay1+256;
|
||||
delay1_sl = p_ac3dec->p_imdct->delay1+2*256;
|
||||
delay1_sr = p_ac3dec->p_imdct->delay1+3*256;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
left_tmp = p_ac3dec->dm_par.unit * *left++ + p_ac3dec->dm_par.slev * *left_sur++;
|
||||
right_tmp= p_ac3dec->dm_par.unit * *right++ + p_ac3dec->dm_par.slev * *right_sur++;
|
||||
*buffer++ = (s16)(left_tmp + *delay_left);
|
||||
*buffer++ = (s16)(right_tmp + *delay_right);
|
||||
*delay_left++ = p_ac3dec->dm_par.unit * *delay1_left++ + p_ac3dec->dm_par.slev * *delay1_sl++;
|
||||
*delay_right++ = p_ac3dec->dm_par.unit * *delay1_right++ + p_ac3dec->dm_par.slev * *delay1_sr++;
|
||||
}
|
||||
break;
|
||||
case 5: /* 3/1 */
|
||||
left = p_ac3dec->samples;
|
||||
center = p_ac3dec->samples+256;
|
||||
right = p_ac3dec->samples+2*256;
|
||||
right_sur = p_ac3dec->samples+3*256;
|
||||
delay_left = p_ac3dec->p_imdct->delay;
|
||||
delay_right = p_ac3dec->p_imdct->delay+256;
|
||||
delay1_left = p_ac3dec->p_imdct->delay1;
|
||||
delay1_center = p_ac3dec->p_imdct->delay1+256;
|
||||
delay1_right = p_ac3dec->p_imdct->delay1+2*256;
|
||||
delay1_sl = p_ac3dec->p_imdct->delay1+3*256;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
left_tmp = p_ac3dec->dm_par.unit * *left++ + p_ac3dec->dm_par.clev * *center - p_ac3dec->dm_par.slev * *right_sur;
|
||||
right_tmp= p_ac3dec->dm_par.unit * *right++ + p_ac3dec->dm_par.clev * *center++ + p_ac3dec->dm_par.slev * *right_sur++;
|
||||
*buffer++ = (s16)(left_tmp + *delay_left);
|
||||
*buffer++ = (s16)(right_tmp + *delay_right);
|
||||
*delay_left++ = p_ac3dec->dm_par.unit * *delay1_left++ + p_ac3dec->dm_par.clev * *delay1_center + p_ac3dec->dm_par.slev * *delay1_sl;
|
||||
*delay_right++ = p_ac3dec->dm_par.unit * *delay1_right++ + p_ac3dec->dm_par.clev * *center++ + p_ac3dec->dm_par.slev * *delay1_sl++;
|
||||
}
|
||||
break;
|
||||
case 4: /* 2/1 */
|
||||
left = p_ac3dec->samples;
|
||||
right = p_ac3dec->samples+256;
|
||||
right_sur = p_ac3dec->samples+2*256;
|
||||
delay_left = p_ac3dec->p_imdct->delay;
|
||||
delay_right = p_ac3dec->p_imdct->delay+256;
|
||||
delay1_left = p_ac3dec->p_imdct->delay1;
|
||||
delay1_right = p_ac3dec->p_imdct->delay1+256;
|
||||
delay1_sl = p_ac3dec->p_imdct->delay1+2*256;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
left_tmp = p_ac3dec->dm_par.unit * *left++ - p_ac3dec->dm_par.slev * *right_sur;
|
||||
right_tmp= p_ac3dec->dm_par.unit * *right++ + p_ac3dec->dm_par.slev * *right_sur++;
|
||||
*buffer++ = (s16)(left_tmp + *delay_left);
|
||||
*buffer++ = (s16)(right_tmp + *delay_right);
|
||||
*delay_left++ = p_ac3dec->dm_par.unit * *delay1_left++ + p_ac3dec->dm_par.slev * *delay1_sl;
|
||||
*delay_right++ = p_ac3dec->dm_par.unit * *delay1_right++ + p_ac3dec->dm_par.slev * *delay1_sl++;
|
||||
}
|
||||
break;
|
||||
case 3: /* 3/0 */
|
||||
left = p_ac3dec->samples;
|
||||
center = p_ac3dec->samples+256;
|
||||
right = p_ac3dec->samples+2*256;
|
||||
delay_left = p_ac3dec->p_imdct->delay;
|
||||
delay_right = p_ac3dec->p_imdct->delay+256;
|
||||
delay1_left = p_ac3dec->p_imdct->delay1;
|
||||
delay1_center = p_ac3dec->p_imdct->delay1+256;
|
||||
delay1_right = p_ac3dec->p_imdct->delay1+2*256;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
left_tmp = p_ac3dec->dm_par.unit * *left++ + p_ac3dec->dm_par.clev * *center;
|
||||
right_tmp= p_ac3dec->dm_par.unit * *right++ + p_ac3dec->dm_par.clev * *center++;
|
||||
*buffer++ = (s16)(left_tmp + *delay_left);
|
||||
*buffer++ = (s16)(right_tmp + *delay_right);
|
||||
*delay_left++ = p_ac3dec->dm_par.unit * *delay1_left++ + p_ac3dec->dm_par.clev * *delay1_center;
|
||||
*delay_right++ = p_ac3dec->dm_par.unit * *delay1_right++ + p_ac3dec->dm_par.clev * *center++;
|
||||
}
|
||||
break;
|
||||
case 2: /* copy to output */
|
||||
for (i = 0; i < 256; i++) {
|
||||
*buffer++ = (s16) *(p_ac3dec->samples+i);
|
||||
*buffer++ = (s16) *(p_ac3dec->samples+256+i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_internals.h: needed by the ac3 decoder
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000 VideoLAN
|
||||
* $Id: ac3_internal.h,v 1.3 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Michel Lespinasse <walken@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/* Exponent strategy constants */
|
||||
#define EXP_REUSE (0)
|
||||
#define EXP_D15 (1)
|
||||
#define EXP_D25 (2)
|
||||
#define EXP_D45 (3)
|
||||
|
||||
/* Delta bit allocation constants */
|
||||
#define DELTA_BIT_REUSE (0)
|
||||
#define DELTA_BIT_NEW (1)
|
||||
#define DELTA_BIT_NONE (2)
|
||||
#define DELTA_BIT_RESERVED (3)
|
||||
|
||||
/* ac3_bit_allocate.c */
|
||||
void bit_allocate (ac3dec_t *);
|
||||
|
||||
/* ac3_exponent.c */
|
||||
int exponent_unpack (ac3dec_t *);
|
||||
|
||||
/* ac3_imdct.c */
|
||||
void E_( imdct_init )(imdct_t * p_imdct);
|
||||
void imdct (ac3dec_t * p_ac3dec, s16 * buffer);
|
||||
|
||||
/* ac3_mantissa.c */
|
||||
void mantissa_unpack (ac3dec_t *);
|
||||
|
||||
/* ac3_parse.c */
|
||||
int parse_bsi (ac3dec_t *);
|
||||
int parse_audblk (ac3dec_t *, int);
|
||||
void parse_auxdata (ac3dec_t *);
|
||||
|
||||
/* ac3_rematrix.c */
|
||||
void rematrix (ac3dec_t *);
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_mantissa.c: ac3 mantissa computation
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: ac3_mantissa.c,v 1.7 2002/06/01 12:31:58 sam Exp $
|
||||
*
|
||||
* Authors: Michel Kaempf <maxx@via.ecp.fr>
|
||||
* Aaron Holtzman <aholtzma@engr.uvic.ca>
|
||||
* Renaud Dartus <reno@videolan.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <string.h> /* memcpy() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/decoder.h>
|
||||
|
||||
#include "ac3_imdct.h"
|
||||
#include "ac3_downmix.h"
|
||||
#include "ac3_adec.h"
|
||||
|
||||
#include "ac3_mantissa.h"
|
||||
|
||||
void mantissa_unpack (ac3dec_t * p_ac3dec)
|
||||
{
|
||||
int i, j;
|
||||
u32 done_cpl = 0;
|
||||
|
||||
p_ac3dec->mantissa.q_1_pointer = -1;
|
||||
p_ac3dec->mantissa.q_2_pointer = -1;
|
||||
p_ac3dec->mantissa.q_4_pointer = -1;
|
||||
|
||||
for (i=0; i< p_ac3dec->bsi.nfchans; i++) {
|
||||
for (j=0; j < p_ac3dec->audblk.endmant[i]; j++)
|
||||
*(p_ac3dec->samples+i*256+j) = coeff_get_float(p_ac3dec, p_ac3dec->audblk.fbw_bap[i][j],
|
||||
p_ac3dec->audblk.dithflag[i], p_ac3dec->audblk.fbw_exp[i][j]);
|
||||
|
||||
if (p_ac3dec->audblk.cplinu && p_ac3dec->audblk.chincpl[i] && !(done_cpl)) {
|
||||
/* ncplmant is equal to 12 * ncplsubnd
|
||||
* Don't dither coupling channel until channel
|
||||
* separation so that interchannel noise is uncorrelated
|
||||
*/
|
||||
for (j=p_ac3dec->audblk.cplstrtmant; j < p_ac3dec->audblk.cplendmant; j++)
|
||||
p_ac3dec->audblk.cpl_flt[j] = coeff_get_float(p_ac3dec, p_ac3dec->audblk.cpl_bap[j],
|
||||
0, p_ac3dec->audblk.cpl_exp[j]);
|
||||
done_cpl = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* uncouple the channel if necessary */
|
||||
if (p_ac3dec->audblk.cplinu) {
|
||||
for (i=0; i< p_ac3dec->bsi.nfchans; i++) {
|
||||
if (p_ac3dec->audblk.chincpl[i])
|
||||
uncouple_channel(p_ac3dec, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (p_ac3dec->bsi.lfeon) {
|
||||
/* There are always 7 mantissas for lfe, no dither for lfe */
|
||||
for (j=0; j < 7 ; j++)
|
||||
*(p_ac3dec->samples+5*256+j) = coeff_get_float(p_ac3dec, p_ac3dec->audblk.lfe_bap[j],
|
||||
0, p_ac3dec->audblk.lfe_exp[j]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,404 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_mantissa.h: ac3 mantissa computation
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: ac3_mantissa.h,v 1.3 2002/06/01 12:31:58 sam Exp $
|
||||
*
|
||||
* Authors: Michel Kaempf <maxx@via.ecp.fr>
|
||||
* Aaron Holtzman <aholtzma@engr.uvic.ca>
|
||||
* Renaud Dartus <reno@videolan.org>
|
||||
*
|
||||
* 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 Q0 ((-2 << 15) / 3.0)
|
||||
#define Q1 (0)
|
||||
#define Q2 ((2 << 15) / 3.0)
|
||||
static const float q_1_0[ 32 ] =
|
||||
{
|
||||
Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0,
|
||||
Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1,
|
||||
Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2,
|
||||
0, 0, 0, 0, 0
|
||||
};
|
||||
static const float q_1_1[ 32 ] =
|
||||
{
|
||||
Q0, Q0, Q0, Q1, Q1, Q1, Q2, Q2, Q2,
|
||||
Q0, Q0, Q0, Q1, Q1, Q1, Q2, Q2, Q2,
|
||||
Q0, Q0, Q0, Q1, Q1, Q1, Q2, Q2, Q2,
|
||||
0, 0, 0, 0, 0
|
||||
};
|
||||
static const float q_1_2[ 32 ] =
|
||||
{
|
||||
Q0, Q1, Q2, Q0, Q1, Q2, Q0, Q1, Q2,
|
||||
Q0, Q1, Q2, Q0, Q1, Q2, Q0, Q1, Q2,
|
||||
Q0, Q1, Q2, Q0, Q1, Q2, Q0, Q1, Q2,
|
||||
0, 0, 0, 0, 0
|
||||
};
|
||||
#undef Q0
|
||||
#undef Q1
|
||||
#undef Q2
|
||||
|
||||
#define Q0 ((-4 << 15) / 5.0)
|
||||
#define Q1 ((-2 << 15) / 5.0)
|
||||
#define Q2 (0)
|
||||
#define Q3 ((2 << 15) / 5.0)
|
||||
#define Q4 ((4 << 15) / 5.0)
|
||||
static const float q_2_0[ 128 ] =
|
||||
{
|
||||
Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,
|
||||
Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,
|
||||
Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,
|
||||
Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,
|
||||
Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,
|
||||
0, 0, 0
|
||||
};
|
||||
static const float q_2_1[ 128 ] =
|
||||
{
|
||||
Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
|
||||
Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
|
||||
Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
|
||||
Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
|
||||
Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
|
||||
0, 0, 0
|
||||
};
|
||||
static const float q_2_2[ 128 ] =
|
||||
{
|
||||
Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
|
||||
Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
|
||||
Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
|
||||
Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
|
||||
Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
|
||||
0, 0, 0
|
||||
};
|
||||
#undef Q0
|
||||
#undef Q1
|
||||
#undef Q2
|
||||
#undef Q3
|
||||
#undef Q4
|
||||
|
||||
#define Q0 ((-10 << 15) / 11.0)
|
||||
#define Q1 ((-8 << 15) / 11.0)
|
||||
#define Q2 ((-6 << 15) / 11.0)
|
||||
#define Q3 ((-4 << 15) / 11.0)
|
||||
#define Q4 ((-2 << 15) / 11.0)
|
||||
#define Q5 (0)
|
||||
#define Q6 ((2 << 15) / 11.0)
|
||||
#define Q7 ((4 << 15) / 11.0)
|
||||
#define Q8 ((6 << 15) / 11.0)
|
||||
#define Q9 ((8 << 15) / 11.0)
|
||||
#define QA ((10 << 15) / 11.0)
|
||||
static const float q_4_0[ 128 ] =
|
||||
{
|
||||
Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0,
|
||||
Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1,
|
||||
Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2,
|
||||
Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3,
|
||||
Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4,
|
||||
Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5,
|
||||
Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6,
|
||||
Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7,
|
||||
Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8,
|
||||
Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9,
|
||||
QA, QA, QA, QA, QA, QA, QA, QA, QA, QA, QA,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
static const float q_4_1[ 128 ] =
|
||||
{
|
||||
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
|
||||
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
|
||||
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
|
||||
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
|
||||
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
|
||||
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
|
||||
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
|
||||
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
|
||||
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
|
||||
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
|
||||
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
|
||||
0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
#undef Q0
|
||||
#undef Q1
|
||||
#undef Q2
|
||||
#undef Q3
|
||||
#undef Q4
|
||||
#undef Q5
|
||||
#undef Q6
|
||||
#undef Q7
|
||||
#undef Q8
|
||||
#undef Q9
|
||||
#undef QA
|
||||
|
||||
/* Lookup tables of 0.16 two's complement quantization values */
|
||||
|
||||
static const float q_3[8] =
|
||||
{
|
||||
(-6 << 15)/7.0, (-4 << 15)/7.0, (-2 << 15)/7.0,
|
||||
0 , (2 << 15)/7.0, (4 << 15)/7.0,
|
||||
(6 << 15)/7.0, 0
|
||||
};
|
||||
|
||||
static const float q_5[16] =
|
||||
{
|
||||
(-14 << 15)/15.0, (-12 << 15)/15.0, (-10 << 15)/15.0,
|
||||
(-8 << 15)/15.0, (-6 << 15)/15.0, (-4 << 15)/15.0,
|
||||
(-2 << 15)/15.0, 0 , (2 << 15)/15.0,
|
||||
(4 << 15)/15.0, (6 << 15)/15.0, (8 << 15)/15.0,
|
||||
(10 << 15)/15.0, (12 << 15)/15.0, (14 << 15)/15.0,
|
||||
0
|
||||
};
|
||||
|
||||
/* Conversion from bap to number of bits in the mantissas
|
||||
* zeros account for cases 0,1,2,4 which are special cased */
|
||||
static const u16 qnttztab[16] =
|
||||
{
|
||||
0, 0, 0, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16
|
||||
};
|
||||
|
||||
static const float scale_factor[25] =
|
||||
{
|
||||
6.10351562500000000000000000e-05,
|
||||
3.05175781250000000000000000e-05,
|
||||
1.52587890625000000000000000e-05,
|
||||
7.62939453125000000000000000e-06,
|
||||
3.81469726562500000000000000e-06,
|
||||
1.90734863281250000000000000e-06,
|
||||
9.53674316406250000000000000e-07,
|
||||
4.76837158203125000000000000e-07,
|
||||
2.38418579101562500000000000e-07,
|
||||
1.19209289550781250000000000e-07,
|
||||
5.96046447753906250000000000e-08,
|
||||
2.98023223876953125000000000e-08,
|
||||
1.49011611938476562500000000e-08,
|
||||
7.45058059692382812500000000e-09,
|
||||
3.72529029846191406250000000e-09,
|
||||
1.86264514923095703125000000e-09,
|
||||
9.31322574615478515625000000e-10,
|
||||
4.65661287307739257812500000e-10,
|
||||
2.32830643653869628906250000e-10,
|
||||
1.16415321826934814453125000e-10,
|
||||
5.82076609134674072265625000e-11,
|
||||
2.91038304567337036132812500e-11,
|
||||
1.45519152283668518066406250e-11,
|
||||
7.27595761418342590332031250e-12,
|
||||
3.63797880709171295166015625e-12,
|
||||
};
|
||||
|
||||
static const u16 dither_lut[256] =
|
||||
{
|
||||
0x0000, 0xa011, 0xe033, 0x4022, 0x6077, 0xc066, 0x8044, 0x2055,
|
||||
0xc0ee, 0x60ff, 0x20dd, 0x80cc, 0xa099, 0x0088, 0x40aa, 0xe0bb,
|
||||
0x21cd, 0x81dc, 0xc1fe, 0x61ef, 0x41ba, 0xe1ab, 0xa189, 0x0198,
|
||||
0xe123, 0x4132, 0x0110, 0xa101, 0x8154, 0x2145, 0x6167, 0xc176,
|
||||
0x439a, 0xe38b, 0xa3a9, 0x03b8, 0x23ed, 0x83fc, 0xc3de, 0x63cf,
|
||||
0x8374, 0x2365, 0x6347, 0xc356, 0xe303, 0x4312, 0x0330, 0xa321,
|
||||
0x6257, 0xc246, 0x8264, 0x2275, 0x0220, 0xa231, 0xe213, 0x4202,
|
||||
0xa2b9, 0x02a8, 0x428a, 0xe29b, 0xc2ce, 0x62df, 0x22fd, 0x82ec,
|
||||
0x8734, 0x2725, 0x6707, 0xc716, 0xe743, 0x4752, 0x0770, 0xa761,
|
||||
0x47da, 0xe7cb, 0xa7e9, 0x07f8, 0x27ad, 0x87bc, 0xc79e, 0x678f,
|
||||
0xa6f9, 0x06e8, 0x46ca, 0xe6db, 0xc68e, 0x669f, 0x26bd, 0x86ac,
|
||||
0x6617, 0xc606, 0x8624, 0x2635, 0x0660, 0xa671, 0xe653, 0x4642,
|
||||
0xc4ae, 0x64bf, 0x249d, 0x848c, 0xa4d9, 0x04c8, 0x44ea, 0xe4fb,
|
||||
0x0440, 0xa451, 0xe473, 0x4462, 0x6437, 0xc426, 0x8404, 0x2415,
|
||||
0xe563, 0x4572, 0x0550, 0xa541, 0x8514, 0x2505, 0x6527, 0xc536,
|
||||
0x258d, 0x859c, 0xc5be, 0x65af, 0x45fa, 0xe5eb, 0xa5c9, 0x05d8,
|
||||
0xae79, 0x0e68, 0x4e4a, 0xee5b, 0xce0e, 0x6e1f, 0x2e3d, 0x8e2c,
|
||||
0x6e97, 0xce86, 0x8ea4, 0x2eb5, 0x0ee0, 0xaef1, 0xeed3, 0x4ec2,
|
||||
0x8fb4, 0x2fa5, 0x6f87, 0xcf96, 0xefc3, 0x4fd2, 0x0ff0, 0xafe1,
|
||||
0x4f5a, 0xef4b, 0xaf69, 0x0f78, 0x2f2d, 0x8f3c, 0xcf1e, 0x6f0f,
|
||||
0xede3, 0x4df2, 0x0dd0, 0xadc1, 0x8d94, 0x2d85, 0x6da7, 0xcdb6,
|
||||
0x2d0d, 0x8d1c, 0xcd3e, 0x6d2f, 0x4d7a, 0xed6b, 0xad49, 0x0d58,
|
||||
0xcc2e, 0x6c3f, 0x2c1d, 0x8c0c, 0xac59, 0x0c48, 0x4c6a, 0xec7b,
|
||||
0x0cc0, 0xacd1, 0xecf3, 0x4ce2, 0x6cb7, 0xcca6, 0x8c84, 0x2c95,
|
||||
0x294d, 0x895c, 0xc97e, 0x696f, 0x493a, 0xe92b, 0xa909, 0x0918,
|
||||
0xe9a3, 0x49b2, 0x0990, 0xa981, 0x89d4, 0x29c5, 0x69e7, 0xc9f6,
|
||||
0x0880, 0xa891, 0xe8b3, 0x48a2, 0x68f7, 0xc8e6, 0x88c4, 0x28d5,
|
||||
0xc86e, 0x687f, 0x285d, 0x884c, 0xa819, 0x0808, 0x482a, 0xe83b,
|
||||
0x6ad7, 0xcac6, 0x8ae4, 0x2af5, 0x0aa0, 0xaab1, 0xea93, 0x4a82,
|
||||
0xaa39, 0x0a28, 0x4a0a, 0xea1b, 0xca4e, 0x6a5f, 0x2a7d, 0x8a6c,
|
||||
0x4b1a, 0xeb0b, 0xab29, 0x0b38, 0x2b6d, 0x8b7c, 0xcb5e, 0x6b4f,
|
||||
0x8bf4, 0x2be5, 0x6bc7, 0xcbd6, 0xeb83, 0x4b92, 0x0bb0, 0xaba1
|
||||
};
|
||||
|
||||
static inline u16 dither_gen (mantissa_t * p_mantissa)
|
||||
{
|
||||
s16 state;
|
||||
|
||||
state = dither_lut[p_mantissa->lfsr_state >> 8] ^
|
||||
(p_mantissa->lfsr_state << 8);
|
||||
p_mantissa->lfsr_state = (u16) state;
|
||||
return ( (state * (s32) (0.707106 * 256.0)) >> 8 );
|
||||
}
|
||||
|
||||
|
||||
/* Fetch an unpacked, left justified, and properly biased/dithered mantissa value */
|
||||
static inline float coeff_get_float( ac3dec_t * p_ac3dec, u16 bap, u16 dithflag,
|
||||
u16 exp )
|
||||
{
|
||||
u16 group_code = 0;
|
||||
|
||||
/* If the bap is 0-5 then we have special cases to take care of */
|
||||
switch (bap)
|
||||
{
|
||||
case 0:
|
||||
if (dithflag)
|
||||
{
|
||||
return ( dither_gen(&p_ac3dec->mantissa) * scale_factor[exp] );
|
||||
}
|
||||
return (0);
|
||||
|
||||
case 1:
|
||||
if (p_ac3dec->mantissa.q_1_pointer >= 0)
|
||||
{
|
||||
return (p_ac3dec->mantissa.q_1[p_ac3dec->mantissa.q_1_pointer--] *
|
||||
scale_factor[exp]);
|
||||
}
|
||||
|
||||
p_ac3dec->total_bits_read += 5;
|
||||
if ((group_code = GetBits (&p_ac3dec->bit_stream,5)) > 26)
|
||||
{
|
||||
msg_Warn( p_ac3dec->p_fifo, "invalid mantissa (1)" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
p_ac3dec->mantissa.q_1[ 1 ] = q_1_1[ group_code ];
|
||||
p_ac3dec->mantissa.q_1[ 0 ] = q_1_2[ group_code ];
|
||||
|
||||
p_ac3dec->mantissa.q_1_pointer = 1;
|
||||
|
||||
return (q_1_0[group_code] * scale_factor[exp]);
|
||||
|
||||
case 2:
|
||||
if (p_ac3dec->mantissa.q_2_pointer >= 0)
|
||||
{
|
||||
return (p_ac3dec->mantissa.q_2[p_ac3dec->mantissa.q_2_pointer--] *
|
||||
scale_factor[exp]);
|
||||
}
|
||||
|
||||
p_ac3dec->total_bits_read += 7;
|
||||
if ((group_code = GetBits (&p_ac3dec->bit_stream,7)) > 124)
|
||||
{
|
||||
msg_Warn( p_ac3dec->p_fifo, "invalid mantissa (2)" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
p_ac3dec->mantissa.q_2[ 1 ] = q_2_1[ group_code ];
|
||||
p_ac3dec->mantissa.q_2[ 0 ] = q_2_2[ group_code ];
|
||||
|
||||
p_ac3dec->mantissa.q_2_pointer = 1;
|
||||
|
||||
return (q_2_0[group_code] * scale_factor[exp]);
|
||||
|
||||
case 3:
|
||||
p_ac3dec->total_bits_read += 3;
|
||||
if ((group_code = GetBits (&p_ac3dec->bit_stream,3)) > 6)
|
||||
{
|
||||
msg_Warn( p_ac3dec->p_fifo, "invalid mantissa (3)" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (q_3[group_code] * scale_factor[exp]);
|
||||
|
||||
case 4:
|
||||
if (p_ac3dec->mantissa.q_4_pointer >= 0)
|
||||
{
|
||||
return (p_ac3dec->mantissa.q_4[p_ac3dec->mantissa.q_4_pointer--] *
|
||||
scale_factor[exp]);
|
||||
}
|
||||
|
||||
p_ac3dec->total_bits_read += 7;
|
||||
if ((group_code = GetBits (&p_ac3dec->bit_stream,7)) > 120)
|
||||
{
|
||||
msg_Warn( p_ac3dec->p_fifo, "invalid mantissa (4)" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
p_ac3dec->mantissa.q_4[ 0 ] = q_4_1[group_code];
|
||||
|
||||
p_ac3dec->mantissa.q_4_pointer = 0;
|
||||
|
||||
return (q_4_0[group_code] * scale_factor[exp]);
|
||||
|
||||
case 5:
|
||||
p_ac3dec->total_bits_read += 4;
|
||||
if ((group_code = GetBits (&p_ac3dec->bit_stream,4)) > 14)
|
||||
{
|
||||
msg_Warn( p_ac3dec->p_fifo, "invalid mantissa (5)" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (q_5[group_code] * scale_factor[exp]);
|
||||
|
||||
default:
|
||||
group_code = GetBits (&p_ac3dec->bit_stream,qnttztab[bap]);
|
||||
group_code <<= 16 - qnttztab[bap];
|
||||
p_ac3dec->total_bits_read += qnttztab[bap];
|
||||
|
||||
return ((s16)(group_code) * scale_factor[exp]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Uncouple the coupling channel into a fbw channel */
|
||||
static inline void uncouple_channel (ac3dec_t * p_ac3dec, u32 ch)
|
||||
{
|
||||
u32 bnd = 0;
|
||||
u32 sub_bnd = 0;
|
||||
u32 i,j;
|
||||
float cpl_coord = 1.0;
|
||||
u32 cpl_exp_tmp;
|
||||
u32 cpl_mant_tmp;
|
||||
|
||||
for (i = p_ac3dec->audblk.cplstrtmant; i < p_ac3dec->audblk.cplendmant;)
|
||||
{
|
||||
if (!p_ac3dec->audblk.cplbndstrc[sub_bnd++])
|
||||
{
|
||||
cpl_exp_tmp = p_ac3dec->audblk.cplcoexp[ch][bnd] +
|
||||
3 * p_ac3dec->audblk.mstrcplco[ch];
|
||||
if (p_ac3dec->audblk.cplcoexp[ch][bnd] == 15)
|
||||
{
|
||||
cpl_mant_tmp = (p_ac3dec->audblk.cplcomant[ch][bnd]) << 11;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpl_mant_tmp = ((0x10) | p_ac3dec->audblk.cplcomant[ch][bnd]) << 10;
|
||||
}
|
||||
cpl_coord = (cpl_mant_tmp) * scale_factor[cpl_exp_tmp] * 8.0f;
|
||||
|
||||
/* Invert the phase for the right channel if necessary */
|
||||
if (p_ac3dec->bsi.acmod == 0x02 && p_ac3dec->audblk.phsflginu &&
|
||||
ch == 1 && p_ac3dec->audblk.phsflg[bnd])
|
||||
{
|
||||
cpl_coord *= -1;
|
||||
}
|
||||
bnd++;
|
||||
}
|
||||
|
||||
for (j=0;j < 12; j++)
|
||||
{
|
||||
/* Get new dither values for each channel if necessary,
|
||||
* so the channels are uncorrelated */
|
||||
if (p_ac3dec->audblk.dithflag[ch] && !p_ac3dec->audblk.cpl_bap[i])
|
||||
{
|
||||
*(p_ac3dec->samples+ch*256+i) = cpl_coord * dither_gen(&p_ac3dec->mantissa) *
|
||||
scale_factor[p_ac3dec->audblk.cpl_exp[i]];
|
||||
} else {
|
||||
*(p_ac3dec->samples+ch*256+i) = cpl_coord * p_ac3dec->audblk.cpl_flt[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,862 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_parse.c: ac3 parsing procedures
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: ac3_parse.c,v 1.9 2002/06/01 12:31:58 sam Exp $
|
||||
*
|
||||
* Authors: Michel Kaempf <maxx@via.ecp.fr>
|
||||
* Aaron Holtzman <aholtzma@engr.uvic.ca>
|
||||
* Renaud Dartus <reno@videolan.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <string.h> /* memset() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/decoder.h>
|
||||
|
||||
#include "ac3_imdct.h"
|
||||
#include "ac3_downmix.h"
|
||||
#include "ac3_adec.h"
|
||||
|
||||
#include "ac3_internal.h" /* EXP_REUSE */
|
||||
|
||||
/* Misc LUT */
|
||||
static const u16 nfchans[] = { 2, 1, 2, 3, 3, 4, 4, 5 };
|
||||
|
||||
struct frmsize_s
|
||||
{
|
||||
u16 bit_rate;
|
||||
u16 frm_size[3];
|
||||
};
|
||||
|
||||
static const struct frmsize_s frmsizecod_tbl[] =
|
||||
{
|
||||
{ 32 ,{64 ,69 ,96 } },
|
||||
{ 32 ,{64 ,70 ,96 } },
|
||||
{ 40 ,{80 ,87 ,120 } },
|
||||
{ 40 ,{80 ,88 ,120 } },
|
||||
{ 48 ,{96 ,104 ,144 } },
|
||||
{ 48 ,{96 ,105 ,144 } },
|
||||
{ 56 ,{112 ,121 ,168 } },
|
||||
{ 56 ,{112 ,122 ,168 } },
|
||||
{ 64 ,{128 ,139 ,192 } },
|
||||
{ 64 ,{128 ,140 ,192 } },
|
||||
{ 80 ,{160 ,174 ,240 } },
|
||||
{ 80 ,{160 ,175 ,240 } },
|
||||
{ 96 ,{192 ,208 ,288 } },
|
||||
{ 96 ,{192 ,209 ,288 } },
|
||||
{ 112 ,{224 ,243 ,336 } },
|
||||
{ 112 ,{224 ,244 ,336 } },
|
||||
{ 128 ,{256 ,278 ,384 } },
|
||||
{ 128 ,{256 ,279 ,384 } },
|
||||
{ 160 ,{320 ,348 ,480 } },
|
||||
{ 160 ,{320 ,349 ,480 } },
|
||||
{ 192 ,{384 ,417 ,576 } },
|
||||
{ 192 ,{384 ,418 ,576 } },
|
||||
{ 224 ,{448 ,487 ,672 } },
|
||||
{ 224 ,{448 ,488 ,672 } },
|
||||
{ 256 ,{512 ,557 ,768 } },
|
||||
{ 256 ,{512 ,558 ,768 } },
|
||||
{ 320 ,{640 ,696 ,960 } },
|
||||
{ 320 ,{640 ,697 ,960 } },
|
||||
{ 384 ,{768 ,835 ,1152 } },
|
||||
{ 384 ,{768 ,836 ,1152 } },
|
||||
{ 448 ,{896 ,975 ,1344 } },
|
||||
{ 448 ,{896 ,976 ,1344 } },
|
||||
{ 512 ,{1024 ,1114 ,1536 } },
|
||||
{ 512 ,{1024 ,1115 ,1536 } },
|
||||
{ 576 ,{1152 ,1253 ,1728 } },
|
||||
{ 576 ,{1152 ,1254 ,1728 } },
|
||||
{ 640 ,{1280 ,1393 ,1920 } },
|
||||
{ 640 ,{1280 ,1394 ,1920 } }};
|
||||
|
||||
static const int fscod_tbl[] = {48000, 44100, 32000};
|
||||
|
||||
/* Some internal functions */
|
||||
static void parse_bsi_stats (ac3dec_t * p_ac3dec);
|
||||
static void parse_audblk_stats (ac3dec_t * p_ac3dec);
|
||||
|
||||
/* Parse a syncinfo structure */
|
||||
int ac3_sync_frame (ac3dec_t * p_ac3dec, ac3_sync_info_t * p_sync_info)
|
||||
{
|
||||
p_ac3dec->total_bits_read = 0;
|
||||
p_ac3dec->i_available = 0;
|
||||
|
||||
/* sync word - should be 0x0b77 */
|
||||
RealignBits(&p_ac3dec->bit_stream);
|
||||
while( (ShowBits (&p_ac3dec->bit_stream,16)) != 0x0b77 &&
|
||||
(!p_ac3dec->p_fifo->b_die) && (!p_ac3dec->p_fifo->b_error))
|
||||
{
|
||||
RemoveBits (&p_ac3dec->bit_stream,8);
|
||||
p_ac3dec->total_bits_read += 8;
|
||||
}
|
||||
RemoveBits (&p_ac3dec->bit_stream,16);
|
||||
p_ac3dec->total_bits_read += 16;
|
||||
|
||||
|
||||
/* Get crc1 - we don't actually use this data though */
|
||||
GetBits (&p_ac3dec->bit_stream,16);
|
||||
|
||||
/* Get the sampling rate */
|
||||
p_ac3dec->syncinfo.fscod = GetBits (&p_ac3dec->bit_stream,2);
|
||||
|
||||
if (p_ac3dec->syncinfo.fscod >= 3)
|
||||
{
|
||||
p_ac3dec->total_bits_read += 34;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get the frame size code */
|
||||
p_ac3dec->syncinfo.frmsizecod = GetBits (&p_ac3dec->bit_stream,6);
|
||||
p_ac3dec->total_bits_read += 40;
|
||||
|
||||
if (p_ac3dec->syncinfo.frmsizecod >= 38)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
p_sync_info->bit_rate = frmsizecod_tbl[p_ac3dec->syncinfo.frmsizecod].bit_rate;
|
||||
|
||||
p_ac3dec->syncinfo.frame_size = frmsizecod_tbl[p_ac3dec->syncinfo.frmsizecod].frm_size[p_ac3dec->syncinfo.fscod];
|
||||
p_sync_info->frame_size = 2 * p_ac3dec->syncinfo.frame_size;
|
||||
|
||||
p_sync_info->sample_rate = fscod_tbl[p_ac3dec->syncinfo.fscod];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine fills a bsi struct from the AC3 stream
|
||||
*/
|
||||
int parse_bsi (ac3dec_t * p_ac3dec)
|
||||
{
|
||||
/* Check the AC-3 version number */
|
||||
p_ac3dec->bsi.bsid = GetBits (&p_ac3dec->bit_stream,5);
|
||||
|
||||
if (p_ac3dec->bsi.bsid > 8)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get the audio service provided by the stream */
|
||||
p_ac3dec->bsi.bsmod = GetBits (&p_ac3dec->bit_stream,3);
|
||||
|
||||
/* Get the audio coding mode (ie how many channels)*/
|
||||
p_ac3dec->bsi.acmod = GetBits (&p_ac3dec->bit_stream,3);
|
||||
|
||||
/* Predecode the number of full bandwidth channels as we use this
|
||||
* number a lot */
|
||||
p_ac3dec->bsi.nfchans = nfchans[p_ac3dec->bsi.acmod];
|
||||
|
||||
/* If it is in use, get the centre channel mix level */
|
||||
if ((p_ac3dec->bsi.acmod & 0x1) && (p_ac3dec->bsi.acmod != 0x1))
|
||||
{
|
||||
p_ac3dec->bsi.cmixlev = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->total_bits_read += 2;
|
||||
}
|
||||
|
||||
/* If it is in use, get the surround channel mix level */
|
||||
if (p_ac3dec->bsi.acmod & 0x4)
|
||||
{
|
||||
p_ac3dec->bsi.surmixlev = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->total_bits_read += 2;
|
||||
}
|
||||
|
||||
/* Get the dolby surround mode if in 2/0 mode */
|
||||
if (p_ac3dec->bsi.acmod == 0x2)
|
||||
{
|
||||
p_ac3dec->bsi.dsurmod = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->total_bits_read += 2;
|
||||
}
|
||||
|
||||
/* Is the low frequency effects channel on? */
|
||||
p_ac3dec->bsi.lfeon = GetBits (&p_ac3dec->bit_stream,1);
|
||||
|
||||
/* Get the dialogue normalization level */
|
||||
p_ac3dec->bsi.dialnorm = GetBits (&p_ac3dec->bit_stream,5);
|
||||
|
||||
/* Does compression gain exist? */
|
||||
if ((p_ac3dec->bsi.compre = GetBits (&p_ac3dec->bit_stream,1)))
|
||||
{
|
||||
/* Get compression gain */
|
||||
p_ac3dec->bsi.compr = GetBits (&p_ac3dec->bit_stream,8);
|
||||
p_ac3dec->total_bits_read += 8;
|
||||
}
|
||||
|
||||
/* Does language code exist? */
|
||||
if ((p_ac3dec->bsi.langcode = GetBits (&p_ac3dec->bit_stream,1)))
|
||||
{
|
||||
/* Get langauge code */
|
||||
p_ac3dec->bsi.langcod = GetBits (&p_ac3dec->bit_stream,8);
|
||||
p_ac3dec->total_bits_read += 8;
|
||||
}
|
||||
|
||||
/* Does audio production info exist? */
|
||||
if ((p_ac3dec->bsi.audprodie = GetBits (&p_ac3dec->bit_stream,1)))
|
||||
{
|
||||
/* Get mix level */
|
||||
p_ac3dec->bsi.mixlevel = GetBits (&p_ac3dec->bit_stream,5);
|
||||
|
||||
/* Get room type */
|
||||
p_ac3dec->bsi.roomtyp = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->total_bits_read += 7;
|
||||
}
|
||||
|
||||
/* If we're in dual mono mode then get some extra info */
|
||||
if (p_ac3dec->bsi.acmod == 0)
|
||||
{
|
||||
/* Get the dialogue normalization level two */
|
||||
p_ac3dec->bsi.dialnorm2 = GetBits (&p_ac3dec->bit_stream,5);
|
||||
|
||||
/* Does compression gain two exist? */
|
||||
if ((p_ac3dec->bsi.compr2e = GetBits (&p_ac3dec->bit_stream,1)))
|
||||
{
|
||||
/* Get compression gain two */
|
||||
p_ac3dec->bsi.compr2 = GetBits (&p_ac3dec->bit_stream,8);
|
||||
p_ac3dec->total_bits_read += 8;
|
||||
}
|
||||
|
||||
/* Does language code two exist? */
|
||||
if ((p_ac3dec->bsi.langcod2e = GetBits (&p_ac3dec->bit_stream,1)))
|
||||
{
|
||||
/* Get langauge code two */
|
||||
p_ac3dec->bsi.langcod2 = GetBits (&p_ac3dec->bit_stream,8);
|
||||
p_ac3dec->total_bits_read += 8;
|
||||
}
|
||||
|
||||
/* Does audio production info two exist? */
|
||||
if ((p_ac3dec->bsi.audprodi2e = GetBits (&p_ac3dec->bit_stream,1)))
|
||||
{
|
||||
/* Get mix level two */
|
||||
p_ac3dec->bsi.mixlevel2 = GetBits (&p_ac3dec->bit_stream,5);
|
||||
|
||||
/* Get room type two */
|
||||
p_ac3dec->bsi.roomtyp2 = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->total_bits_read += 7;
|
||||
}
|
||||
p_ac3dec->total_bits_read += 8;
|
||||
}
|
||||
|
||||
/* Get the copyright bit */
|
||||
p_ac3dec->bsi.copyrightb = GetBits (&p_ac3dec->bit_stream,1);
|
||||
|
||||
/* Get the original bit */
|
||||
p_ac3dec->bsi.origbs = GetBits (&p_ac3dec->bit_stream,1);
|
||||
|
||||
/* Does timecode one exist? */
|
||||
if ((p_ac3dec->bsi.timecod1e = GetBits (&p_ac3dec->bit_stream,1)))
|
||||
{
|
||||
p_ac3dec->bsi.timecod1 = GetBits (&p_ac3dec->bit_stream,14);
|
||||
p_ac3dec->total_bits_read += 14;
|
||||
}
|
||||
|
||||
/* Does timecode two exist? */
|
||||
if ((p_ac3dec->bsi.timecod2e = GetBits (&p_ac3dec->bit_stream,1)))
|
||||
{
|
||||
p_ac3dec->bsi.timecod2 = GetBits (&p_ac3dec->bit_stream,14);
|
||||
p_ac3dec->total_bits_read += 14;
|
||||
}
|
||||
|
||||
/* Does addition info exist? */
|
||||
if ((p_ac3dec->bsi.addbsie = GetBits (&p_ac3dec->bit_stream,1)))
|
||||
{
|
||||
u32 i;
|
||||
|
||||
/* Get how much info is there */
|
||||
p_ac3dec->bsi.addbsil = GetBits (&p_ac3dec->bit_stream,6);
|
||||
|
||||
/* Get the additional info */
|
||||
for (i=0;i<(p_ac3dec->bsi.addbsil + 1);i++)
|
||||
{
|
||||
p_ac3dec->bsi.addbsi[i] = GetBits (&p_ac3dec->bit_stream,8);
|
||||
}
|
||||
p_ac3dec->total_bits_read += 6 + 8 * (p_ac3dec->bsi.addbsil + 1);
|
||||
}
|
||||
p_ac3dec->total_bits_read += 25;
|
||||
|
||||
parse_bsi_stats (p_ac3dec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* More pain inducing parsing */
|
||||
int parse_audblk (ac3dec_t * p_ac3dec, int blknum)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i=0; i < p_ac3dec->bsi.nfchans; i++)
|
||||
{
|
||||
/* Is this channel an interleaved 256 + 256 block ? */
|
||||
p_ac3dec->audblk.blksw[i] = GetBits (&p_ac3dec->bit_stream,1);
|
||||
}
|
||||
|
||||
for (i=0; i < p_ac3dec->bsi.nfchans; i++)
|
||||
{
|
||||
/* Should we dither this channel? */
|
||||
p_ac3dec->audblk.dithflag[i] = GetBits (&p_ac3dec->bit_stream,1);
|
||||
}
|
||||
|
||||
/* Does dynamic range control exist? */
|
||||
if ((p_ac3dec->audblk.dynrnge = GetBits (&p_ac3dec->bit_stream,1)))
|
||||
{
|
||||
/* Get dynamic range info */
|
||||
p_ac3dec->audblk.dynrng = GetBits (&p_ac3dec->bit_stream,8);
|
||||
p_ac3dec->total_bits_read += 8;
|
||||
}
|
||||
|
||||
/* If we're in dual mono mode then get the second channel DR info */
|
||||
if (p_ac3dec->bsi.acmod == 0)
|
||||
{
|
||||
/* Does dynamic range control two exist? */
|
||||
if ((p_ac3dec->audblk.dynrng2e = GetBits (&p_ac3dec->bit_stream,1)))
|
||||
{
|
||||
/* Get dynamic range info */
|
||||
p_ac3dec->audblk.dynrng2 = GetBits (&p_ac3dec->bit_stream,8);
|
||||
p_ac3dec->total_bits_read += 8;
|
||||
}
|
||||
p_ac3dec->total_bits_read += 1;
|
||||
}
|
||||
|
||||
/* Does coupling strategy exist? */
|
||||
p_ac3dec->audblk.cplstre = GetBits (&p_ac3dec->bit_stream,1);
|
||||
p_ac3dec->total_bits_read += 2 + 2 * p_ac3dec->bsi.nfchans;
|
||||
|
||||
if ((!blknum) && (!p_ac3dec->audblk.cplstre))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (p_ac3dec->audblk.cplstre)
|
||||
{
|
||||
/* Is coupling turned on? */
|
||||
if ((p_ac3dec->audblk.cplinu = GetBits (&p_ac3dec->bit_stream,1)))
|
||||
{
|
||||
int nb_coupled_channels;
|
||||
|
||||
nb_coupled_channels = 0;
|
||||
for (i=0; i < p_ac3dec->bsi.nfchans; i++)
|
||||
{
|
||||
p_ac3dec->audblk.chincpl[i] = GetBits (&p_ac3dec->bit_stream,1);
|
||||
if (p_ac3dec->audblk.chincpl[i])
|
||||
{
|
||||
nb_coupled_channels++;
|
||||
}
|
||||
}
|
||||
p_ac3dec->total_bits_read += p_ac3dec->bsi.nfchans;
|
||||
|
||||
if (nb_coupled_channels < 2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (p_ac3dec->bsi.acmod == 0x2)
|
||||
{
|
||||
p_ac3dec->audblk.phsflginu = GetBits (&p_ac3dec->bit_stream,1);
|
||||
p_ac3dec->total_bits_read += 1;
|
||||
}
|
||||
p_ac3dec->audblk.cplbegf = GetBits (&p_ac3dec->bit_stream,4);
|
||||
p_ac3dec->audblk.cplendf = GetBits (&p_ac3dec->bit_stream,4);
|
||||
p_ac3dec->total_bits_read += 8;
|
||||
|
||||
if (p_ac3dec->audblk.cplbegf > p_ac3dec->audblk.cplendf + 2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
p_ac3dec->audblk.ncplsubnd = (p_ac3dec->audblk.cplendf + 2) - p_ac3dec->audblk.cplbegf + 1;
|
||||
|
||||
/* Calculate the start and end bins of the coupling channel */
|
||||
p_ac3dec->audblk.cplstrtmant = (p_ac3dec->audblk.cplbegf * 12) + 37 ;
|
||||
p_ac3dec->audblk.cplendmant = ((p_ac3dec->audblk.cplendf + 3) * 12) + 37;
|
||||
|
||||
/* The number of combined subbands is ncplsubnd minus each combined
|
||||
* band */
|
||||
p_ac3dec->audblk.ncplbnd = p_ac3dec->audblk.ncplsubnd;
|
||||
|
||||
for (i=1; i< p_ac3dec->audblk.ncplsubnd; i++)
|
||||
{
|
||||
p_ac3dec->audblk.cplbndstrc[i] = GetBits (&p_ac3dec->bit_stream,1);
|
||||
p_ac3dec->audblk.ncplbnd -= p_ac3dec->audblk.cplbndstrc[i];
|
||||
}
|
||||
p_ac3dec->total_bits_read += p_ac3dec->audblk.ncplsubnd - 1;
|
||||
}
|
||||
p_ac3dec->total_bits_read += 1;
|
||||
}
|
||||
|
||||
if (p_ac3dec->audblk.cplinu)
|
||||
{
|
||||
/* Loop through all the channels and get their coupling co-ords */
|
||||
for (i=0; i < p_ac3dec->bsi.nfchans;i++)
|
||||
{
|
||||
if (!p_ac3dec->audblk.chincpl[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Is there new coupling co-ordinate info? */
|
||||
p_ac3dec->audblk.cplcoe[i] = GetBits (&p_ac3dec->bit_stream,1);
|
||||
|
||||
if ((!blknum) && (!p_ac3dec->audblk.cplcoe[i]))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (p_ac3dec->audblk.cplcoe[i])
|
||||
{
|
||||
p_ac3dec->audblk.mstrcplco[i] = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->total_bits_read += 2;
|
||||
for (j=0;j < p_ac3dec->audblk.ncplbnd; j++)
|
||||
{
|
||||
p_ac3dec->audblk.cplcoexp[i][j] = GetBits (&p_ac3dec->bit_stream,4);
|
||||
p_ac3dec->audblk.cplcomant[i][j] = GetBits (&p_ac3dec->bit_stream,4);
|
||||
}
|
||||
p_ac3dec->total_bits_read += 8 * p_ac3dec->audblk.ncplbnd;
|
||||
}
|
||||
}
|
||||
p_ac3dec->total_bits_read += p_ac3dec->bsi.nfchans;
|
||||
|
||||
/* If we're in dual mono mode, there's going to be some phase info */
|
||||
if ((p_ac3dec->bsi.acmod == 0x2) && p_ac3dec->audblk.phsflginu &&
|
||||
(p_ac3dec->audblk.cplcoe[0] || p_ac3dec->audblk.cplcoe[1]))
|
||||
{
|
||||
for (j=0; j < p_ac3dec->audblk.ncplbnd; j++)
|
||||
{
|
||||
p_ac3dec->audblk.phsflg[j] = GetBits (&p_ac3dec->bit_stream,1);
|
||||
}
|
||||
p_ac3dec->total_bits_read += p_ac3dec->audblk.ncplbnd;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're in dual mono mode, there may be a rematrix strategy */
|
||||
if (p_ac3dec->bsi.acmod == 0x2)
|
||||
{
|
||||
p_ac3dec->audblk.rematstr = GetBits (&p_ac3dec->bit_stream,1);
|
||||
p_ac3dec->total_bits_read += 1;
|
||||
|
||||
if ((!blknum) && (!p_ac3dec->audblk.rematstr))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (p_ac3dec->audblk.rematstr)
|
||||
{
|
||||
if (p_ac3dec->audblk.cplinu == 0)
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
p_ac3dec->audblk.rematflg[i] = GetBits (&p_ac3dec->bit_stream,1);
|
||||
}
|
||||
p_ac3dec->total_bits_read += 4;
|
||||
}
|
||||
if ((p_ac3dec->audblk.cplbegf > 2) && p_ac3dec->audblk.cplinu)
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
p_ac3dec->audblk.rematflg[i] = GetBits (&p_ac3dec->bit_stream,1);
|
||||
}
|
||||
p_ac3dec->total_bits_read += 4;
|
||||
}
|
||||
if ((p_ac3dec->audblk.cplbegf <= 2) && p_ac3dec->audblk.cplinu)
|
||||
{
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
p_ac3dec->audblk.rematflg[i] = GetBits (&p_ac3dec->bit_stream,1);
|
||||
}
|
||||
p_ac3dec->total_bits_read += 3;
|
||||
}
|
||||
if ((p_ac3dec->audblk.cplbegf == 0) && p_ac3dec->audblk.cplinu)
|
||||
{
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
p_ac3dec->audblk.rematflg[i] = GetBits (&p_ac3dec->bit_stream,1);
|
||||
}
|
||||
p_ac3dec->total_bits_read += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_ac3dec->audblk.cplinu)
|
||||
{
|
||||
/* Get the coupling channel exponent strategy */
|
||||
p_ac3dec->audblk.cplexpstr = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->total_bits_read += 2;
|
||||
|
||||
if ((!blknum) && (p_ac3dec->audblk.cplexpstr == EXP_REUSE))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (p_ac3dec->audblk.cplexpstr==0)
|
||||
{
|
||||
p_ac3dec->audblk.ncplgrps = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_ac3dec->audblk.ncplgrps = (p_ac3dec->audblk.cplendmant - p_ac3dec->audblk.cplstrtmant) /
|
||||
(3 << (p_ac3dec->audblk.cplexpstr-1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; i < p_ac3dec->bsi.nfchans; i++)
|
||||
{
|
||||
p_ac3dec->audblk.chexpstr[i] = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->total_bits_read += 2;
|
||||
|
||||
if ((!blknum) && (p_ac3dec->audblk.chexpstr[i] == EXP_REUSE))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the exponent strategy for lfe channel */
|
||||
if (p_ac3dec->bsi.lfeon)
|
||||
{
|
||||
p_ac3dec->audblk.lfeexpstr = GetBits (&p_ac3dec->bit_stream,1);
|
||||
p_ac3dec->total_bits_read += 1;
|
||||
|
||||
if ((!blknum) && (p_ac3dec->audblk.lfeexpstr == EXP_REUSE))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine the bandwidths of all the fbw channels */
|
||||
for (i = 0; i < p_ac3dec->bsi.nfchans; i++)
|
||||
{
|
||||
u16 grp_size;
|
||||
|
||||
if (p_ac3dec->audblk.chexpstr[i] != EXP_REUSE)
|
||||
{
|
||||
if (p_ac3dec->audblk.cplinu && p_ac3dec->audblk.chincpl[i])
|
||||
{
|
||||
p_ac3dec->audblk.endmant[i] = p_ac3dec->audblk.cplstrtmant;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_ac3dec->audblk.chbwcod[i] = GetBits (&p_ac3dec->bit_stream,6);
|
||||
p_ac3dec->total_bits_read += 6;
|
||||
|
||||
if (p_ac3dec->audblk.chbwcod[i] > 60)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
p_ac3dec->audblk.endmant[i] = ((p_ac3dec->audblk.chbwcod[i] + 12) * 3) + 37;
|
||||
}
|
||||
|
||||
/* Calculate the number of exponent groups to fetch */
|
||||
grp_size = 3 * (1 << (p_ac3dec->audblk.chexpstr[i] - 1));
|
||||
p_ac3dec->audblk.nchgrps[i] = (p_ac3dec->audblk.endmant[i] - 1 + (grp_size - 3)) / grp_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the coupling exponents if they exist */
|
||||
if (p_ac3dec->audblk.cplinu && (p_ac3dec->audblk.cplexpstr != EXP_REUSE))
|
||||
{
|
||||
p_ac3dec->audblk.cplabsexp = GetBits (&p_ac3dec->bit_stream,4);
|
||||
p_ac3dec->total_bits_read += 4;
|
||||
for (i=0; i< p_ac3dec->audblk.ncplgrps;i++)
|
||||
{
|
||||
p_ac3dec->audblk.cplexps[i] = GetBits (&p_ac3dec->bit_stream,7);
|
||||
p_ac3dec->total_bits_read += 7;
|
||||
|
||||
if (p_ac3dec->audblk.cplexps[i] >= 125)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the fwb channel exponents */
|
||||
for (i=0; i < p_ac3dec->bsi.nfchans; i++)
|
||||
{
|
||||
if (p_ac3dec->audblk.chexpstr[i] != EXP_REUSE)
|
||||
{
|
||||
p_ac3dec->audblk.exps[i][0] = GetBits (&p_ac3dec->bit_stream,4);
|
||||
p_ac3dec->total_bits_read += 4;
|
||||
for (j=1; j<=p_ac3dec->audblk.nchgrps[i];j++)
|
||||
{
|
||||
p_ac3dec->audblk.exps[i][j] = GetBits (&p_ac3dec->bit_stream,7);
|
||||
p_ac3dec->total_bits_read += 7;
|
||||
if (p_ac3dec->audblk.exps[i][j] >= 125)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
p_ac3dec->audblk.gainrng[i] = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->total_bits_read += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the lfe channel exponents */
|
||||
if (p_ac3dec->bsi.lfeon && (p_ac3dec->audblk.lfeexpstr != EXP_REUSE))
|
||||
{
|
||||
p_ac3dec->audblk.lfeexps[0] = GetBits (&p_ac3dec->bit_stream,4);
|
||||
p_ac3dec->audblk.lfeexps[1] = GetBits (&p_ac3dec->bit_stream,7);
|
||||
p_ac3dec->total_bits_read += 11;
|
||||
if (p_ac3dec->audblk.lfeexps[1] >= 125)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
p_ac3dec->audblk.lfeexps[2] = GetBits (&p_ac3dec->bit_stream,7);
|
||||
p_ac3dec->total_bits_read += 7;
|
||||
if (p_ac3dec->audblk.lfeexps[2] >= 125)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the parametric bit allocation parameters */
|
||||
p_ac3dec->audblk.baie = GetBits (&p_ac3dec->bit_stream,1);
|
||||
p_ac3dec->total_bits_read += 1;
|
||||
|
||||
if ((!blknum) && (!p_ac3dec->audblk.baie))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (p_ac3dec->audblk.baie)
|
||||
{
|
||||
p_ac3dec->audblk.sdcycod = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->audblk.fdcycod = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->audblk.sgaincod = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->audblk.dbpbcod = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->audblk.floorcod = GetBits (&p_ac3dec->bit_stream,3);
|
||||
p_ac3dec->total_bits_read += 11;
|
||||
}
|
||||
|
||||
/* Get the SNR off set info if it exists */
|
||||
p_ac3dec->audblk.snroffste = GetBits (&p_ac3dec->bit_stream,1);
|
||||
if ((!blknum) && (!p_ac3dec->audblk.snroffste))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (p_ac3dec->audblk.snroffste)
|
||||
{
|
||||
p_ac3dec->audblk.csnroffst = GetBits (&p_ac3dec->bit_stream,6);
|
||||
p_ac3dec->total_bits_read += 6;
|
||||
|
||||
if (p_ac3dec->audblk.cplinu)
|
||||
{
|
||||
p_ac3dec->audblk.cplfsnroffst = GetBits (&p_ac3dec->bit_stream,4);
|
||||
p_ac3dec->audblk.cplfgaincod = GetBits (&p_ac3dec->bit_stream,3);
|
||||
p_ac3dec->total_bits_read += 7;
|
||||
}
|
||||
|
||||
for (i = 0;i < p_ac3dec->bsi.nfchans; i++)
|
||||
{
|
||||
p_ac3dec->audblk.fsnroffst[i] = GetBits (&p_ac3dec->bit_stream,4);
|
||||
p_ac3dec->audblk.fgaincod[i] = GetBits (&p_ac3dec->bit_stream,3);
|
||||
}
|
||||
p_ac3dec->total_bits_read += 7 * p_ac3dec->bsi.nfchans;
|
||||
if (p_ac3dec->bsi.lfeon)
|
||||
{
|
||||
p_ac3dec->audblk.lfefsnroffst = GetBits (&p_ac3dec->bit_stream,4);
|
||||
p_ac3dec->audblk.lfefgaincod = GetBits (&p_ac3dec->bit_stream,3);
|
||||
p_ac3dec->total_bits_read += 7;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get coupling leakage info if it exists */
|
||||
if (p_ac3dec->audblk.cplinu)
|
||||
{
|
||||
p_ac3dec->audblk.cplleake = GetBits (&p_ac3dec->bit_stream,1);
|
||||
p_ac3dec->total_bits_read += 1;
|
||||
if ((!blknum) && (!p_ac3dec->audblk.cplleake))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (p_ac3dec->audblk.cplleake)
|
||||
{
|
||||
p_ac3dec->audblk.cplfleak = GetBits (&p_ac3dec->bit_stream,3);
|
||||
p_ac3dec->audblk.cplsleak = GetBits (&p_ac3dec->bit_stream,3);
|
||||
p_ac3dec->total_bits_read += 6;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the delta bit alloaction info */
|
||||
p_ac3dec->audblk.deltbaie = GetBits (&p_ac3dec->bit_stream,1);
|
||||
p_ac3dec->total_bits_read += 1;
|
||||
|
||||
if (p_ac3dec->audblk.deltbaie)
|
||||
{
|
||||
if (p_ac3dec->audblk.cplinu)
|
||||
{
|
||||
p_ac3dec->audblk.cpldeltbae = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->total_bits_read += 2;
|
||||
if (p_ac3dec->audblk.cpldeltbae == 3)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0;i < p_ac3dec->bsi.nfchans; i++)
|
||||
{
|
||||
p_ac3dec->audblk.deltbae[i] = GetBits (&p_ac3dec->bit_stream,2);
|
||||
p_ac3dec->total_bits_read += 2;
|
||||
if (p_ac3dec->audblk.deltbae[i] == 3)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_ac3dec->audblk.cplinu && (p_ac3dec->audblk.cpldeltbae == DELTA_BIT_NEW))
|
||||
{
|
||||
p_ac3dec->audblk.cpldeltnseg = GetBits (&p_ac3dec->bit_stream,3);
|
||||
for (i = 0;i < p_ac3dec->audblk.cpldeltnseg + 1; i++)
|
||||
{
|
||||
p_ac3dec->audblk.cpldeltoffst[i] = GetBits (&p_ac3dec->bit_stream,5);
|
||||
p_ac3dec->audblk.cpldeltlen[i] = GetBits (&p_ac3dec->bit_stream,4);
|
||||
p_ac3dec->audblk.cpldeltba[i] = GetBits (&p_ac3dec->bit_stream,3);
|
||||
}
|
||||
p_ac3dec->total_bits_read += 12 * (p_ac3dec->audblk.cpldeltnseg + 1) + 3;
|
||||
}
|
||||
|
||||
for (i = 0; i < p_ac3dec->bsi.nfchans; i++)
|
||||
{
|
||||
if (p_ac3dec->audblk.deltbae[i] == DELTA_BIT_NEW)
|
||||
{
|
||||
p_ac3dec->audblk.deltnseg[i] = GetBits (&p_ac3dec->bit_stream,3);
|
||||
// if (p_ac3dec->audblk.deltnseg[i] >= 8)
|
||||
// fprintf (stderr, "parse debug: p_ac3dec->audblk.deltnseg[%i] == %i\n", i, p_ac3dec->audblk.deltnseg[i]);
|
||||
for (j = 0; j < p_ac3dec->audblk.deltnseg[i] + 1; j++)
|
||||
{
|
||||
p_ac3dec->audblk.deltoffst[i][j] = GetBits (&p_ac3dec->bit_stream,5);
|
||||
p_ac3dec->audblk.deltlen[i][j] = GetBits (&p_ac3dec->bit_stream,4);
|
||||
p_ac3dec->audblk.deltba[i][j] = GetBits (&p_ac3dec->bit_stream,3);
|
||||
}
|
||||
p_ac3dec->total_bits_read += 12 * (p_ac3dec->audblk.deltnseg[i] + 1) + 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if there's any dummy info to get */
|
||||
p_ac3dec->audblk.skiple = GetBits (&p_ac3dec->bit_stream,1);
|
||||
p_ac3dec->total_bits_read += 1;
|
||||
|
||||
if (p_ac3dec->audblk.skiple)
|
||||
{
|
||||
p_ac3dec->audblk.skipl = GetBits (&p_ac3dec->bit_stream,9);
|
||||
|
||||
for (i = 0; i < p_ac3dec->audblk.skipl ; i++)
|
||||
{
|
||||
GetBits (&p_ac3dec->bit_stream,8);
|
||||
}
|
||||
p_ac3dec->total_bits_read += 8 * p_ac3dec->audblk.skipl + 9;
|
||||
}
|
||||
|
||||
parse_audblk_stats(p_ac3dec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void parse_auxdata (ac3dec_t * p_ac3dec)
|
||||
{
|
||||
int i;
|
||||
int skip_length;
|
||||
|
||||
skip_length = (p_ac3dec->syncinfo.frame_size * 16) - p_ac3dec->total_bits_read - 17 - 1;
|
||||
|
||||
for (i = 0; i < skip_length; i++)
|
||||
{
|
||||
RemoveBits (&p_ac3dec->bit_stream,1);
|
||||
}
|
||||
|
||||
/* get the auxdata exists bit */
|
||||
RemoveBits (&p_ac3dec->bit_stream,1);
|
||||
|
||||
/* Skip the CRC reserved bit */
|
||||
RemoveBits (&p_ac3dec->bit_stream,1);
|
||||
|
||||
/* Get the crc */
|
||||
RemoveBits (&p_ac3dec->bit_stream,16);
|
||||
}
|
||||
|
||||
static void parse_bsi_stats (ac3dec_t * p_ac3dec) /* Some stats */
|
||||
{
|
||||
#if 0
|
||||
struct mixlev_s
|
||||
{
|
||||
float clev;
|
||||
char *desc;
|
||||
};
|
||||
static const char *service_ids[8] =
|
||||
{
|
||||
"CM","ME","VI","HI",
|
||||
"D", "C","E", "VO"
|
||||
};
|
||||
/*
|
||||
static const struct mixlev_s cmixlev_tbl[4] =
|
||||
{
|
||||
{0.707, "(-3.0 dB)"}, {0.595, "(-4.5 dB)"},
|
||||
{0.500, "(-6.0 dB)"}, {1.0, "Invalid"}
|
||||
};
|
||||
static const struct mixlev_s smixlev_tbl[4] =
|
||||
{
|
||||
{0.707, "(-3.0 dB)"}, {0.500, "(-6.0 dB)"},
|
||||
{ 0.0, "off "}, { 1.0, "Invalid"}
|
||||
};
|
||||
*/
|
||||
|
||||
static int i=0;
|
||||
|
||||
if ( !i )
|
||||
{
|
||||
/* if ((p_ac3dec->bsi.acmod & 0x1) && (p_ac3dec->bsi.acmod != 0x1))
|
||||
printf("CentreMixLevel %s ",cmixlev_tbl[p_ac3dec->bsi.cmixlev].desc);
|
||||
if (p_ac3dec->bsi.acmod & 0x4)
|
||||
printf("SurMixLevel %s",smixlev_tbl[p_ac3dec->bsi.cmixlev].desc);
|
||||
*/
|
||||
intf_Msg ( "(ac3dec_parsebsi) %s %d.%d Mode",
|
||||
service_ids[p_ac3dec->bsi.bsmod],
|
||||
p_ac3dec->bsi.nfchans,p_ac3dec->bsi.lfeon);
|
||||
}
|
||||
i++;
|
||||
|
||||
if ( i > 100 )
|
||||
i = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void parse_audblk_stats (ac3dec_t * p_ac3dec)
|
||||
{
|
||||
#if 0
|
||||
char *exp_strat_tbl[4] = {"R ","D15 ","D25 ","D45 "};
|
||||
u32 i;
|
||||
intf_ErrMsg ("(ac3dec_parseaudblk) ");
|
||||
intf_ErrMsg ("%s ",p_ac3dec->audblk.cplinu ? "cpl on" : "cpl off");
|
||||
intf_ErrMsg ("%s ",p_ac3dec->audblk.baie? "bai" : " ");
|
||||
intf_ErrMsg ("%s ",p_ac3dec->audblk.snroffste? "snroffst" : " ");
|
||||
intf_ErrMsg ("%s ",p_ac3dec->audblk.deltbaie? "deltba" : " ");
|
||||
intf_ErrMsg ("%s ",p_ac3dec->audblk.phsflginu? "phsflg" : " ");
|
||||
intf_ErrMsg ("(%s %s %s %s %s) ",exp_strat_tbl[p_ac3dec->audblk.chexpstr[0]],
|
||||
exp_strat_tbl[p_ac3dec->audblk.chexpstr[1]],exp_strat_tbl[p_ac3dec->audblk.chexpstr[2]],
|
||||
exp_strat_tbl[p_ac3dec->audblk.chexpstr[3]],exp_strat_tbl[p_ac3dec->audblk.chexpstr[4]]);
|
||||
intf_ErrMsg ("[");
|
||||
for(i=0;i<p_ac3dec->bsi.nfchans;i++)
|
||||
intf_ErrMsg ("%1d",p_ac3dec->audblk.blksw[i]);
|
||||
intf_ErrMsg ("]");
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_rematrix.c: ac3 audio rematrixing
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: ac3_rematrix.c,v 1.8 2002/06/01 12:31:58 sam Exp $
|
||||
*
|
||||
* Authors: Michel Kaempf <maxx@via.ecp.fr>
|
||||
* Aaron Holtzman <aholtzma@engr.uvic.ca>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/decoder.h>
|
||||
|
||||
#include "ac3_imdct.h"
|
||||
#include "ac3_downmix.h"
|
||||
#include "ac3_adec.h"
|
||||
|
||||
struct rematrix_band_s {
|
||||
u32 start;
|
||||
u32 end;
|
||||
};
|
||||
|
||||
static const struct rematrix_band_s rematrix_band[] = { {13,24}, {25,36}, {37 ,60}, {61,252}};
|
||||
|
||||
static inline u32 min_value (u32 a, u32 b)
|
||||
{
|
||||
return (a < b ? a : b);
|
||||
}
|
||||
|
||||
/* This routine simply does stereo rematixing for the 2 channel
|
||||
* stereo mode */
|
||||
void rematrix (ac3dec_t * p_ac3dec)
|
||||
{
|
||||
u32 num_bands;
|
||||
u32 start;
|
||||
u32 end;
|
||||
u32 i,j;
|
||||
float left,right;
|
||||
|
||||
if (p_ac3dec->audblk.cplinu || p_ac3dec->audblk.cplbegf > 2)
|
||||
num_bands = 4;
|
||||
else if (p_ac3dec->audblk.cplbegf > 0)
|
||||
num_bands = 3;
|
||||
else
|
||||
num_bands = 2;
|
||||
|
||||
for (i=0;i < num_bands; i++) {
|
||||
if (!p_ac3dec->audblk.rematflg[i])
|
||||
continue;
|
||||
|
||||
start = rematrix_band[i].start;
|
||||
end = min_value(rematrix_band[i].end ,12 * p_ac3dec->audblk.cplbegf + 36);
|
||||
|
||||
for (j=start;j < end; j++) {
|
||||
left = 0.5f * ( *(p_ac3dec->samples+j) + *(p_ac3dec->samples+256+j) );
|
||||
right = 0.5f * ( *(p_ac3dec->samples+j) - *(p_ac3dec->samples+256+j) );
|
||||
*(p_ac3dec->samples+j) = left;
|
||||
*(p_ac3dec->samples+256+j) = right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1 +0,0 @@
|
|||
ac3_spdif_SOURCES = ac3_spdif.c
|
|
@ -1,431 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_spdif.c: ac3 pass-through to external decoder with enabled soundcard
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: ac3_spdif.c,v 1.32 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Stéphane Borel <stef@via.ecp.fr>
|
||||
* Juha Yrjola <jyrjola@cc.hut.fi>
|
||||
* German Gomez Garcia <german@piraos.com>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* memcpy() */
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/decoder.h>
|
||||
#include <vlc/aout.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "ac3_spdif.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Local prototypes
|
||||
****************************************************************************/
|
||||
static int OpenDecoder ( vlc_object_t * );
|
||||
static int RunDecoder ( decoder_fifo_t * );
|
||||
|
||||
static int InitThread ( ac3_spdif_thread_t * );
|
||||
static void EndThread ( ac3_spdif_thread_t * );
|
||||
static void BitstreamCallback ( bit_stream_t *, vlc_bool_t );
|
||||
|
||||
int ac3_parse_syncinfo ( struct ac3_spdif_thread_s * );
|
||||
|
||||
/****************************************************************************
|
||||
* Local structures and tables
|
||||
****************************************************************************/
|
||||
static const frame_size_t p_frame_size_code[64] =
|
||||
{
|
||||
{ 32 ,{64 ,69 ,96 } },
|
||||
{ 32 ,{64 ,70 ,96 } },
|
||||
{ 40 ,{80 ,87 ,120 } },
|
||||
{ 40 ,{80 ,88 ,120 } },
|
||||
{ 48 ,{96 ,104 ,144 } },
|
||||
{ 48 ,{96 ,105 ,144 } },
|
||||
{ 56 ,{112 ,121 ,168 } },
|
||||
{ 56 ,{112 ,122 ,168 } },
|
||||
{ 64 ,{128 ,139 ,192 } },
|
||||
{ 64 ,{128 ,140 ,192 } },
|
||||
{ 80 ,{160 ,174 ,240 } },
|
||||
{ 80 ,{160 ,175 ,240 } },
|
||||
{ 96 ,{192 ,208 ,288 } },
|
||||
{ 96 ,{192 ,209 ,288 } },
|
||||
{ 112 ,{224 ,243 ,336 } },
|
||||
{ 112 ,{224 ,244 ,336 } },
|
||||
{ 128 ,{256 ,278 ,384 } },
|
||||
{ 128 ,{256 ,279 ,384 } },
|
||||
{ 160 ,{320 ,348 ,480 } },
|
||||
{ 160 ,{320 ,349 ,480 } },
|
||||
{ 192 ,{384 ,417 ,576 } },
|
||||
{ 192 ,{384 ,418 ,576 } },
|
||||
{ 224 ,{448 ,487 ,672 } },
|
||||
{ 224 ,{448 ,488 ,672 } },
|
||||
{ 256 ,{512 ,557 ,768 } },
|
||||
{ 256 ,{512 ,558 ,768 } },
|
||||
{ 320 ,{640 ,696 ,960 } },
|
||||
{ 320 ,{640 ,697 ,960 } },
|
||||
{ 384 ,{768 ,835 ,1152 } },
|
||||
{ 384 ,{768 ,836 ,1152 } },
|
||||
{ 448 ,{896 ,975 ,1344 } },
|
||||
{ 448 ,{896 ,976 ,1344 } },
|
||||
{ 512 ,{1024 ,1114 ,1536 } },
|
||||
{ 512 ,{1024 ,1115 ,1536 } },
|
||||
{ 576 ,{1152 ,1253 ,1728 } },
|
||||
{ 576 ,{1152 ,1254 ,1728 } },
|
||||
{ 640 ,{1280 ,1393 ,1920 } },
|
||||
{ 640 ,{1280 ,1394 ,1920 } }
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
set_description( _("SPDIF pass-through AC3 decoder") );
|
||||
set_capability( "decoder", 0 );
|
||||
set_callbacks( OpenDecoder, NULL );
|
||||
add_shortcut( "pass_through" );
|
||||
add_shortcut( "pass" );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* OpenDecoder: probe the decoder and return score
|
||||
*****************************************************************************
|
||||
* Tries to launch a decoder and return score so that the interface is able
|
||||
* to chose.
|
||||
*****************************************************************************/
|
||||
static int OpenDecoder( vlc_object_t *p_this )
|
||||
{
|
||||
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
|
||||
|
||||
if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') )
|
||||
{
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
p_fifo->pf_run = RunDecoder;
|
||||
return VLC_SUCCESS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* RunDecoder: the whole thing
|
||||
****************************************************************************
|
||||
* This function is called just after the thread is launched.
|
||||
****************************************************************************/
|
||||
static int RunDecoder( decoder_fifo_t *p_fifo )
|
||||
{
|
||||
ac3_spdif_thread_t * p_spdif;
|
||||
mtime_t i_frame_time;
|
||||
vlc_bool_t b_sync;
|
||||
/* PTS of the current frame */
|
||||
mtime_t i_current_pts = 0;
|
||||
u16 i_length;
|
||||
|
||||
/* Allocate the memory needed to store the thread's structure */
|
||||
p_spdif = malloc( sizeof(ac3_spdif_thread_t) );
|
||||
|
||||
if( p_spdif == NULL )
|
||||
{
|
||||
msg_Err( p_fifo, "out of memory" );
|
||||
DecoderError( p_fifo );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
p_spdif->p_fifo = p_fifo;
|
||||
|
||||
if (InitThread( p_spdif ) )
|
||||
{
|
||||
|
||||
if( p_fifo->b_error )
|
||||
{
|
||||
msg_Err( p_fifo, "could not initialize thread" );
|
||||
}
|
||||
|
||||
DecoderError( p_fifo );
|
||||
free( p_spdif );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Compute the theorical duration of an ac3 frame */
|
||||
i_frame_time = 1000000 * AC3_FRAME_SIZE /
|
||||
p_spdif->ac3_info.i_sample_rate;
|
||||
i_length = p_spdif->ac3_info.i_frame_size;
|
||||
|
||||
while( !p_spdif->p_fifo->b_die && !p_spdif->p_fifo->b_error )
|
||||
{
|
||||
p_spdif->p_ac3[0] = 0x0b;
|
||||
p_spdif->p_ac3[1] = 0x77;
|
||||
|
||||
/* Handle the dates */
|
||||
if( p_spdif->i_real_pts )
|
||||
{
|
||||
mtime_t i_delta = p_spdif->i_real_pts - i_current_pts -
|
||||
i_frame_time;
|
||||
if( i_delta > i_frame_time || i_delta < -i_frame_time )
|
||||
{
|
||||
msg_Warn( p_fifo,
|
||||
"date discontinuity (%d)", i_delta );
|
||||
}
|
||||
i_current_pts = p_spdif->i_real_pts;
|
||||
p_spdif->i_real_pts = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
i_current_pts += i_frame_time;
|
||||
}
|
||||
|
||||
// wait a little to avoid an input flood from the a52 input
|
||||
mwait( i_current_pts - 500000 );
|
||||
|
||||
vlc_mutex_lock (&p_spdif->p_aout_fifo->data_lock);
|
||||
|
||||
p_spdif->p_aout_fifo->date[p_spdif->p_aout_fifo->i_end_frame] =
|
||||
i_current_pts;
|
||||
|
||||
p_spdif->p_aout_fifo->i_end_frame =
|
||||
(p_spdif->p_aout_fifo->i_end_frame + 1 ) & AOUT_FIFO_SIZE;
|
||||
|
||||
p_spdif->p_ac3 = ((u8*)(p_spdif->p_aout_fifo->buffer)) +
|
||||
(p_spdif->p_aout_fifo->i_end_frame * i_length );
|
||||
|
||||
vlc_mutex_unlock (&p_spdif->p_aout_fifo->data_lock);
|
||||
|
||||
/* Find syncword again in case of stream discontinuity */
|
||||
/* Here we have p_spdif->i_pts == 0
|
||||
* Therefore a non-zero value after a call to GetBits() means the PES
|
||||
* has changed. */
|
||||
b_sync = 0;
|
||||
while( !p_spdif->p_fifo->b_die
|
||||
&& !p_spdif->p_fifo->b_error
|
||||
&& !b_sync )
|
||||
{
|
||||
while( !p_spdif->p_fifo->b_die
|
||||
&& !p_spdif->p_fifo->b_error
|
||||
&& GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
|
||||
p_spdif->i_real_pts = p_spdif->i_pts;
|
||||
p_spdif->i_pts = 0;
|
||||
b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
|
||||
}
|
||||
RemoveBits( &p_spdif->bit_stream, 8 );
|
||||
|
||||
/* Read data from bitstream */
|
||||
GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + 2, i_length - 2 );
|
||||
}
|
||||
|
||||
/* If b_error is set, the ac3 spdif thread enters the error loop */
|
||||
if( p_spdif->p_fifo->b_error )
|
||||
{
|
||||
DecoderError( p_spdif->p_fifo );
|
||||
}
|
||||
|
||||
/* End of the ac3 decoder thread */
|
||||
EndThread( p_spdif );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* InitThread: initialize thread data and create output fifo
|
||||
****************************************************************************/
|
||||
static int InitThread( ac3_spdif_thread_t * p_spdif )
|
||||
{
|
||||
vlc_bool_t b_sync = 0;
|
||||
|
||||
/* Temporary buffer to store first ac3 frame */
|
||||
p_spdif->p_ac3 = malloc( SPDIF_FRAME_SIZE );
|
||||
|
||||
if( p_spdif->p_ac3 == NULL )
|
||||
{
|
||||
free( p_spdif->p_ac3 );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the thread properties
|
||||
*/
|
||||
p_spdif->p_fifo = p_spdif->p_fifo;
|
||||
|
||||
InitBitstream( &p_spdif->bit_stream, p_spdif->p_fifo,
|
||||
BitstreamCallback, (void*)p_spdif );
|
||||
|
||||
/* Find syncword */
|
||||
while( !p_spdif->p_fifo->b_die
|
||||
&& !p_spdif->p_fifo->b_error
|
||||
&& !b_sync )
|
||||
{
|
||||
while( !p_spdif->p_fifo->b_die
|
||||
&& !p_spdif->p_fifo->b_error
|
||||
&& GetBits( &p_spdif->bit_stream, 8 ) != 0x0b );
|
||||
p_spdif->i_real_pts = p_spdif->i_pts;
|
||||
p_spdif->i_pts = 0;
|
||||
b_sync = ( ShowBits( &p_spdif->bit_stream, 8 ) == 0x77 );
|
||||
}
|
||||
|
||||
if( p_spdif->p_fifo->b_die || p_spdif->p_fifo->b_error )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
RemoveBits( &p_spdif->bit_stream, 8 );
|
||||
|
||||
/* Check stream properties */
|
||||
if( ac3_parse_syncinfo( p_spdif ) < 0 )
|
||||
{
|
||||
msg_Err( p_spdif->p_fifo, "stream not valid" );
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Check that we can handle the rate
|
||||
* FIXME: we should check that we have the same rate for all fifos
|
||||
* but all rates should be supported by the decoder (32, 44.1, 48) */
|
||||
if( p_spdif->ac3_info.i_sample_rate != 48000 )
|
||||
{
|
||||
msg_Err( p_spdif->p_fifo,
|
||||
"only 48000 Hz streams tested, expect weird things!" );
|
||||
}
|
||||
|
||||
/* The audio output need to be ready for an ac3 stream */
|
||||
p_spdif->i_previous_format = config_GetInt( p_spdif->p_fifo,
|
||||
"audio-format" );
|
||||
config_PutInt( p_spdif->p_fifo, "audio-format", 8 );
|
||||
|
||||
/* Creating the audio output fifo */
|
||||
p_spdif->p_aout_fifo =
|
||||
aout_CreateFifo( p_spdif->p_fifo, AOUT_FIFO_SPDIF,
|
||||
1, p_spdif->ac3_info.i_sample_rate,
|
||||
p_spdif->ac3_info.i_frame_size, NULL );
|
||||
|
||||
if( p_spdif->p_aout_fifo == NULL )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
msg_Dbg( p_spdif->p_fifo, "aout fifo #%d created",
|
||||
p_spdif->p_aout_fifo->i_fifo );
|
||||
|
||||
/* Put read data into fifo */
|
||||
memcpy( (u8*)(p_spdif->p_aout_fifo->buffer) +
|
||||
(p_spdif->p_aout_fifo->i_end_frame *
|
||||
p_spdif->ac3_info.i_frame_size ),
|
||||
p_spdif->p_ac3, sizeof(sync_frame_t) );
|
||||
free( p_spdif->p_ac3 );
|
||||
p_spdif->p_ac3 = ((u8*)(p_spdif->p_aout_fifo->buffer) +
|
||||
(p_spdif->p_aout_fifo->i_end_frame *
|
||||
p_spdif->ac3_info.i_frame_size ));
|
||||
|
||||
GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + sizeof(sync_frame_t),
|
||||
p_spdif->ac3_info.i_frame_size - sizeof(sync_frame_t) );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* EndThread : ac3 spdif thread destruction
|
||||
*****************************************************************************/
|
||||
static void EndThread( ac3_spdif_thread_t * p_spdif )
|
||||
{
|
||||
/* If the audio output fifo was created, we destroy it */
|
||||
if( p_spdif->p_aout_fifo != NULL )
|
||||
{
|
||||
aout_DestroyFifo( p_spdif->p_aout_fifo );
|
||||
|
||||
/* Make sure the output thread leaves the NextFrame() function */
|
||||
vlc_mutex_lock( &(p_spdif->p_aout_fifo->data_lock ) );
|
||||
vlc_cond_signal( &(p_spdif->p_aout_fifo->data_wait ) );
|
||||
vlc_mutex_unlock( &(p_spdif->p_aout_fifo->data_lock ) );
|
||||
|
||||
}
|
||||
|
||||
/* restore previous setting for output format */
|
||||
config_PutInt( p_spdif->p_fifo, "audio-format",
|
||||
p_spdif->i_previous_format );
|
||||
|
||||
/* Destroy descriptor */
|
||||
free( p_spdif );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* BitstreamCallback: Import parameters from the new data/PES packet
|
||||
*****************************************************************************
|
||||
* This function is called by input's NextDataPacket.
|
||||
*****************************************************************************/
|
||||
static void BitstreamCallback( bit_stream_t * p_bit_stream,
|
||||
vlc_bool_t b_new_pes )
|
||||
{
|
||||
ac3_spdif_thread_t * p_spdif;
|
||||
|
||||
if( b_new_pes )
|
||||
{
|
||||
p_spdif = (ac3_spdif_thread_t *)p_bit_stream->p_callback_arg;
|
||||
|
||||
/* p_bit_stream->p_byte += 3; */
|
||||
|
||||
p_spdif->i_pts =
|
||||
p_bit_stream->p_decoder_fifo->p_first->i_pts;
|
||||
p_bit_stream->p_decoder_fifo->p_first->i_pts = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ac3_parse_syncinfo: parse ac3 sync info
|
||||
****************************************************************************/
|
||||
int ac3_parse_syncinfo( ac3_spdif_thread_t *p_spdif )
|
||||
{
|
||||
int p_sample_rates[4] = { 48000, 44100, 32000, -1 };
|
||||
int i_frame_rate_code;
|
||||
int i_frame_size_code;
|
||||
sync_frame_t * p_sync_frame;
|
||||
|
||||
/* Read sync frame */
|
||||
GetChunk( &p_spdif->bit_stream, p_spdif->p_ac3 + 2,
|
||||
sizeof(sync_frame_t) - 2 );
|
||||
if( p_spdif->p_fifo->b_die ) return -1;
|
||||
|
||||
p_sync_frame = (sync_frame_t*)p_spdif->p_ac3;
|
||||
|
||||
/* Compute frame rate */
|
||||
i_frame_rate_code = (p_sync_frame->syncinfo.code >> 6) & 0x03;
|
||||
p_spdif->ac3_info.i_sample_rate = p_sample_rates[i_frame_rate_code];
|
||||
if( p_spdif->ac3_info.i_sample_rate == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Compute frame size */
|
||||
i_frame_size_code = p_sync_frame->syncinfo.code & 0x3f;
|
||||
p_spdif->ac3_info.i_frame_size = 2 *
|
||||
p_frame_size_code[i_frame_size_code].i_frame_size[i_frame_rate_code];
|
||||
p_spdif->ac3_info.i_bit_rate =
|
||||
p_frame_size_code[i_frame_size_code].i_bit_rate;
|
||||
|
||||
if( ( ( p_sync_frame->bsi.bsidmod >> 3 ) & 0x1f ) != 0x08 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
p_spdif->ac3_info.i_bs_mod = p_sync_frame->bsi.bsidmod & 0x7;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_spdif.h: header for ac3 pass-through
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: ac3_spdif.h,v 1.4 2002/06/01 12:31:58 sam Exp $
|
||||
*
|
||||
* Authors: Stéphane Borel <stef@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.
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* information about ac3 frame
|
||||
****************************************************************************/
|
||||
typedef struct sync_frame_s
|
||||
{
|
||||
struct syncinfo
|
||||
{
|
||||
u8 syncword[2];
|
||||
u8 crc1[2];
|
||||
u8 code;
|
||||
} syncinfo;
|
||||
|
||||
struct bsi
|
||||
{
|
||||
u8 bsidmod;
|
||||
u8 acmod;
|
||||
} bsi;
|
||||
} sync_frame_t;
|
||||
|
||||
typedef struct frame_size_s
|
||||
{
|
||||
u16 i_bit_rate;
|
||||
u16 i_frame_size[3];
|
||||
} frame_size_t;
|
||||
|
||||
typedef struct ac3_info_s
|
||||
{
|
||||
int i_bit_rate;
|
||||
int i_frame_size;
|
||||
int i_sample_rate;
|
||||
int i_bs_mod;
|
||||
} ac3_info_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* ac3_spdif_thread_t : ac3 pass-through thread descriptor
|
||||
*****************************************************************************/
|
||||
typedef struct ac3_spdif_thread_s
|
||||
{
|
||||
/*
|
||||
* Thread properties
|
||||
*/
|
||||
vlc_thread_t thread_id; /* id for thread functions */
|
||||
|
||||
/*
|
||||
* Input properties
|
||||
*/
|
||||
decoder_fifo_t * p_fifo; /* stores the PES stream data */
|
||||
|
||||
/* The bit stream structure handles the PES stream at the bit level */
|
||||
bit_stream_t bit_stream;
|
||||
int i_available;
|
||||
|
||||
/*
|
||||
* Decoder properties
|
||||
*/
|
||||
ac3_info_t ac3_info;
|
||||
u8 * p_ac3;
|
||||
|
||||
/* current pes date */
|
||||
mtime_t i_pts;
|
||||
mtime_t i_real_pts;
|
||||
|
||||
/*
|
||||
* Output properties
|
||||
*/
|
||||
int i_previous_format;
|
||||
aout_fifo_t * p_aout_fifo; /* stores the decompressed audio frames */
|
||||
|
||||
} ac3_spdif_thread_t;
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1,3 +0,0 @@
|
|||
file_SOURCES = file.c
|
||||
udp_SOURCES = udp.c
|
||||
http_SOURCES = http.c
|
|
@ -1,151 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* file.c: file input (file: access plug-in)
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001, 2002 VideoLAN
|
||||
* $Id: file.c,v 1.8 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Christophe Massiot <massiot@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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/input.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#elif defined( _MSC_VER ) && defined( _WIN32 )
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Open: open the file
|
||||
*****************************************************************************/
|
||||
static int Open( vlc_object_t *p_this )
|
||||
{
|
||||
input_thread_t * p_input = (input_thread_t *)p_this;
|
||||
char * psz_name = p_input->psz_name;
|
||||
int i_stat;
|
||||
struct stat stat_info;
|
||||
input_socket_t * p_access_data;
|
||||
vlc_bool_t b_stdin;
|
||||
|
||||
p_input->i_mtu = 0;
|
||||
|
||||
b_stdin = psz_name[0] == '-' && psz_name[1] == '\0';
|
||||
|
||||
if( !b_stdin && (i_stat = stat( psz_name, &stat_info )) == (-1) )
|
||||
{
|
||||
msg_Err( p_input, "cannot stat() file `%s' (%s)",
|
||||
psz_name, strerror(errno));
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
p_input->pf_read = input_FDRead;
|
||||
p_input->pf_set_program = input_SetProgram;
|
||||
p_input->pf_set_area = NULL;
|
||||
p_input->pf_seek = input_FDSeek;
|
||||
|
||||
vlc_mutex_lock( &p_input->stream.stream_lock );
|
||||
|
||||
if( *p_input->psz_access && !strncmp( p_input->psz_access, "stream", 7 ) )
|
||||
{
|
||||
/* stream:%s */
|
||||
p_input->stream.b_pace_control = 0;
|
||||
p_input->stream.b_seekable = 0;
|
||||
p_input->stream.p_selected_area->i_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* file:%s or %s */
|
||||
p_input->stream.b_pace_control = 1;
|
||||
|
||||
if( b_stdin )
|
||||
{
|
||||
p_input->stream.b_seekable = 0;
|
||||
p_input->stream.p_selected_area->i_size = 0;
|
||||
}
|
||||
else if( S_ISREG(stat_info.st_mode) || S_ISCHR(stat_info.st_mode)
|
||||
|| S_ISBLK(stat_info.st_mode) )
|
||||
{
|
||||
p_input->stream.b_seekable = 1;
|
||||
p_input->stream.p_selected_area->i_size = stat_info.st_size;
|
||||
}
|
||||
else if( S_ISFIFO(stat_info.st_mode)
|
||||
#if !defined( SYS_BEOS ) && !defined( WIN32 )
|
||||
|| S_ISSOCK(stat_info.st_mode)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
p_input->stream.b_seekable = 0;
|
||||
p_input->stream.p_selected_area->i_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vlc_mutex_unlock( &p_input->stream.stream_lock );
|
||||
msg_Err( p_input, "unknown file type for `%s'", psz_name );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
p_input->stream.p_selected_area->i_tell = 0;
|
||||
p_input->stream.i_method = INPUT_METHOD_FILE;
|
||||
vlc_mutex_unlock( &p_input->stream.stream_lock );
|
||||
|
||||
msg_Dbg( p_input, "opening file `%s'", psz_name );
|
||||
p_access_data = malloc( sizeof(input_socket_t) );
|
||||
p_input->p_access_data = (void *)p_access_data;
|
||||
if( p_access_data == NULL )
|
||||
{
|
||||
msg_Err( p_input, "out of memory" );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( b_stdin )
|
||||
{
|
||||
p_access_data->i_handle = 0;
|
||||
}
|
||||
else if( (p_access_data->i_handle = open( psz_name,
|
||||
/*O_NONBLOCK | O_LARGEFILE*/ 0 )) == (-1) )
|
||||
{
|
||||
msg_Err( p_input, "cannot open file %s (%s)", psz_name,
|
||||
strerror(errno) );
|
||||
free( p_access_data );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
set_description( _("Standard filesystem file reading") );
|
||||
set_capability( "access", 50 );
|
||||
add_shortcut( "stream" );
|
||||
set_callbacks( Open, __input_FDClose );
|
||||
vlc_module_end();
|
||||
|
|
@ -1,500 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* http.c: HTTP access plug-in
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001, 2002 VideoLAN
|
||||
* $Id: http.c,v 1.19 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Christophe Massiot <massiot@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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/input.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#elif defined( _MSC_VER ) && defined( _WIN32 )
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
# ifndef IN_MULTICAST
|
||||
# define IN_MULTICAST(a) IN_CLASSD(a)
|
||||
# endif
|
||||
#else
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include "network.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int Open ( vlc_object_t * );
|
||||
static void Close ( vlc_object_t * );
|
||||
|
||||
static int SetProgram ( input_thread_t *, pgrm_descriptor_t * );
|
||||
static void Seek ( input_thread_t *, off_t );
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
set_description( _("HTTP access module") );
|
||||
set_capability( "access", 0 );
|
||||
add_shortcut( "http4" );
|
||||
add_shortcut( "http6" );
|
||||
set_callbacks( Open, Close );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* _input_socket_t: private access plug-in data, modified to add private
|
||||
* fields
|
||||
*****************************************************************************/
|
||||
typedef struct _input_socket_s
|
||||
{
|
||||
input_socket_t _socket;
|
||||
|
||||
char * psz_network;
|
||||
network_socket_t socket_desc;
|
||||
char psz_buffer[256];
|
||||
char * psz_name;
|
||||
} _input_socket_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* HTTPConnect: connect to the server and seek to i_tell
|
||||
*****************************************************************************/
|
||||
static int HTTPConnect( input_thread_t * p_input, off_t i_tell )
|
||||
{
|
||||
_input_socket_t * p_access_data = p_input->p_access_data;
|
||||
module_t * p_network;
|
||||
char psz_buffer[256];
|
||||
byte_t * psz_parser;
|
||||
int i_returncode, i;
|
||||
char * psz_return_alpha;
|
||||
|
||||
/* Find an appropriate network module */
|
||||
p_input->p_private = (void*) &p_access_data->socket_desc;
|
||||
p_network = module_Need( p_input, "network", p_access_data->psz_network );
|
||||
if( p_network == NULL )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
module_Unneed( p_input, p_network );
|
||||
|
||||
p_access_data->_socket.i_handle = p_access_data->socket_desc.i_handle;
|
||||
|
||||
# define HTTP_USERAGENT "User-Agent: " COPYRIGHT_MESSAGE "\r\n"
|
||||
# define HTTP_END "\r\n"
|
||||
|
||||
if ( p_input->stream.b_seekable )
|
||||
{
|
||||
snprintf( psz_buffer, sizeof(psz_buffer),
|
||||
"%s"
|
||||
"Range: bytes=%lld-\r\n"
|
||||
HTTP_USERAGENT HTTP_END,
|
||||
p_access_data->psz_buffer, i_tell );
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( psz_buffer, sizeof(psz_buffer),
|
||||
"%s"
|
||||
HTTP_USERAGENT HTTP_END,
|
||||
p_access_data->psz_buffer );
|
||||
}
|
||||
psz_buffer[sizeof(psz_buffer) - 1] = '\0';
|
||||
|
||||
/* Send GET ... */
|
||||
if( send( p_access_data->_socket.i_handle, psz_buffer,
|
||||
strlen( psz_buffer ), 0 ) == (-1) )
|
||||
{
|
||||
msg_Err( p_input, "cannot send request (%s)", strerror(errno) );
|
||||
input_FDNetworkClose( p_input );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Prepare the input thread for reading. */
|
||||
p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
|
||||
|
||||
/* FIXME: we shouldn't have to do that ! It's UGLY but mandatory because
|
||||
* input_FillBuffer assumes p_input->pf_read exists */
|
||||
p_input->pf_read = input_FDNetworkRead;
|
||||
|
||||
while( !input_FillBuffer( p_input ) )
|
||||
{
|
||||
if( p_input->b_die || p_input->b_error )
|
||||
{
|
||||
input_FDNetworkClose( p_input );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse HTTP header. */
|
||||
#define MAX_LINE 1024
|
||||
|
||||
/* get the returncode */
|
||||
if( input_Peek( p_input, &psz_parser, MAX_LINE ) <= 0 )
|
||||
{
|
||||
msg_Err( p_input, "not enough data" );
|
||||
input_FDNetworkClose( p_input );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( !strncmp( psz_parser, "HTTP/1.",
|
||||
strlen("HTTP/1.") ) )
|
||||
{
|
||||
psz_parser += strlen("HTTP 1.") + 2;
|
||||
i_returncode = atoi( psz_parser );
|
||||
msg_Dbg( p_input, "HTTP server replied: %i", i_returncode );
|
||||
psz_parser += 4;
|
||||
for ( i = 0; psz_parser[i] != '\r' || psz_parser[i+1] != '\n'; i++ )
|
||||
{
|
||||
;
|
||||
}
|
||||
psz_return_alpha = malloc( i + 1 );
|
||||
memcpy( psz_return_alpha, psz_parser, i );
|
||||
psz_return_alpha[i] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_Err( p_input, "invalid http reply" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( i_returncode >= 400 ) /* something is wrong */
|
||||
{
|
||||
msg_Err( p_input, "%i %s", i_returncode,
|
||||
psz_return_alpha );
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
if( input_Peek( p_input, &psz_parser, MAX_LINE ) <= 0 )
|
||||
{
|
||||
msg_Err( p_input, "not enough data" );
|
||||
input_FDNetworkClose( p_input );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( psz_parser[0] == '\r' && psz_parser[1] == '\n' )
|
||||
{
|
||||
/* End of header. */
|
||||
p_input->p_current_data += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if( !strncmp( psz_parser, "Content-Length: ",
|
||||
strlen("Content-Length: ") ) )
|
||||
{
|
||||
psz_parser += strlen("Content-Length: ");
|
||||
vlc_mutex_lock( &p_input->stream.stream_lock );
|
||||
#ifdef HAVE_ATOLL
|
||||
p_input->stream.p_selected_area->i_size = atoll( psz_parser )
|
||||
+ i_tell;
|
||||
#else
|
||||
/* FIXME : this won't work for 64-bit lengths */
|
||||
p_input->stream.p_selected_area->i_size = atoi( psz_parser )
|
||||
+ i_tell;
|
||||
#endif
|
||||
vlc_mutex_unlock( &p_input->stream.stream_lock );
|
||||
}
|
||||
|
||||
while( *psz_parser != '\r' && psz_parser < p_input->p_last_data )
|
||||
{
|
||||
psz_parser++;
|
||||
}
|
||||
p_input->p_current_data = psz_parser + 2;
|
||||
}
|
||||
|
||||
if( p_input->stream.p_selected_area->i_size )
|
||||
{
|
||||
vlc_mutex_lock( &p_input->stream.stream_lock );
|
||||
p_input->stream.p_selected_area->i_tell = i_tell
|
||||
+ (p_input->p_last_data - p_input->p_current_data);
|
||||
p_input->stream.b_seekable = 1;
|
||||
p_input->stream.b_changed = 1;
|
||||
vlc_mutex_unlock( &p_input->stream.stream_lock );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Open: parse URL and open the remote file at the beginning
|
||||
*****************************************************************************/
|
||||
static int Open( vlc_object_t *p_this )
|
||||
{
|
||||
input_thread_t * p_input = (input_thread_t *)p_this;
|
||||
_input_socket_t * p_access_data;
|
||||
char * psz_name = strdup(p_input->psz_name);
|
||||
char * psz_parser = psz_name;
|
||||
char * psz_server_addr = "";
|
||||
char * psz_server_port = "";
|
||||
char * psz_path = "";
|
||||
char * psz_proxy;
|
||||
int i_server_port = 0;
|
||||
|
||||
p_access_data = p_input->p_access_data = malloc( sizeof(_input_socket_t) );
|
||||
if( p_access_data == NULL )
|
||||
{
|
||||
msg_Err( p_input, "out of memory" );
|
||||
free(psz_name);
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
p_access_data->psz_name = psz_name;
|
||||
p_access_data->psz_network = "";
|
||||
if( config_GetInt( p_input, "ipv4" ) )
|
||||
{
|
||||
p_access_data->psz_network = "ipv4";
|
||||
}
|
||||
if( config_GetInt( p_input, "ipv6" ) )
|
||||
{
|
||||
p_access_data->psz_network = "ipv6";
|
||||
}
|
||||
if( *p_input->psz_access )
|
||||
{
|
||||
/* Find out which shortcut was used */
|
||||
if( !strncmp( p_input->psz_access, "http6", 6 ) )
|
||||
{
|
||||
p_access_data->psz_network = "ipv6";
|
||||
}
|
||||
else if( !strncmp( p_input->psz_access, "http4", 6 ) )
|
||||
{
|
||||
p_access_data->psz_network = "ipv4";
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse psz_name syntax :
|
||||
* //<hostname>[:<port>][/<path>] */
|
||||
while( *psz_parser == '/' )
|
||||
{
|
||||
psz_parser++;
|
||||
}
|
||||
psz_server_addr = psz_parser;
|
||||
|
||||
while( *psz_parser && *psz_parser != ':' && *psz_parser != '/' )
|
||||
{
|
||||
psz_parser++;
|
||||
}
|
||||
|
||||
if ( *psz_parser == ':' )
|
||||
{
|
||||
*psz_parser = '\0';
|
||||
psz_parser++;
|
||||
psz_server_port = psz_parser;
|
||||
|
||||
while( *psz_parser && *psz_parser != '/' )
|
||||
{
|
||||
psz_parser++;
|
||||
}
|
||||
}
|
||||
|
||||
if( *psz_parser == '/' )
|
||||
{
|
||||
*psz_parser = '\0';
|
||||
psz_parser++;
|
||||
psz_path = psz_parser;
|
||||
}
|
||||
|
||||
/* Convert port format */
|
||||
if( *psz_server_port )
|
||||
{
|
||||
i_server_port = strtol( psz_server_port, &psz_parser, 10 );
|
||||
if( *psz_parser )
|
||||
{
|
||||
msg_Err( p_input, "cannot parse server port near %s", psz_parser );
|
||||
free( p_input->p_access_data );
|
||||
free( psz_name );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
if( i_server_port == 0 )
|
||||
{
|
||||
i_server_port = 80;
|
||||
}
|
||||
|
||||
if( !*psz_server_addr )
|
||||
{
|
||||
msg_Err( p_input, "no server given" );
|
||||
free( p_input->p_access_data );
|
||||
free( psz_name );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Check proxy */
|
||||
if( (psz_proxy = getenv( "http_proxy" )) != NULL && *psz_proxy )
|
||||
{
|
||||
/* http://myproxy.mydomain:myport/ */
|
||||
int i_proxy_port = 0;
|
||||
|
||||
/* Skip the protocol name */
|
||||
while( *psz_proxy && *psz_proxy != ':' )
|
||||
{
|
||||
psz_proxy++;
|
||||
}
|
||||
|
||||
/* Skip the "://" part */
|
||||
while( *psz_proxy && (*psz_proxy == ':' || *psz_proxy == '/') )
|
||||
{
|
||||
psz_proxy++;
|
||||
}
|
||||
|
||||
/* Found a proxy name */
|
||||
if( *psz_proxy )
|
||||
{
|
||||
char *psz_port = psz_proxy;
|
||||
|
||||
/* Skip the hostname part */
|
||||
while( *psz_port && *psz_port != ':' && *psz_port != '/' )
|
||||
{
|
||||
psz_port++;
|
||||
}
|
||||
|
||||
/* Found a port name */
|
||||
if( *psz_port )
|
||||
{
|
||||
char * psz_junk;
|
||||
|
||||
/* Replace ':' with '\0' */
|
||||
*psz_port = '\0';
|
||||
psz_port++;
|
||||
|
||||
psz_junk = psz_port;
|
||||
while( *psz_junk && *psz_junk != '/' )
|
||||
{
|
||||
psz_junk++;
|
||||
}
|
||||
|
||||
if( *psz_junk )
|
||||
{
|
||||
*psz_junk = '\0';
|
||||
}
|
||||
|
||||
if( *psz_port != '\0' )
|
||||
{
|
||||
i_proxy_port = atoi( psz_port );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_Err( p_input, "http_proxy environment variable is invalid!" );
|
||||
free( p_input->p_access_data );
|
||||
free( psz_name );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
p_access_data->socket_desc.i_type = NETWORK_TCP;
|
||||
p_access_data->socket_desc.psz_server_addr = psz_proxy;
|
||||
p_access_data->socket_desc.i_server_port = i_proxy_port;
|
||||
|
||||
snprintf( p_access_data->psz_buffer, sizeof(p_access_data->psz_buffer),
|
||||
"GET http://%s:%d/%s\r\n HTTP/1.0\r\n",
|
||||
psz_server_addr, i_server_port, psz_path );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No proxy, direct connection. */
|
||||
p_access_data->socket_desc.i_type = NETWORK_TCP;
|
||||
p_access_data->socket_desc.psz_server_addr = psz_server_addr;
|
||||
p_access_data->socket_desc.i_server_port = i_server_port;
|
||||
|
||||
snprintf( p_access_data->psz_buffer, sizeof(p_access_data->psz_buffer),
|
||||
"GET /%s HTTP/1.1\r\nHost: %s\r\n",
|
||||
psz_path, psz_server_addr );
|
||||
}
|
||||
p_access_data->psz_buffer[sizeof(p_access_data->psz_buffer) - 1] = '\0';
|
||||
|
||||
msg_Dbg( p_input, "opening server=%s port=%d path=%s",
|
||||
psz_server_addr, i_server_port, psz_path );
|
||||
|
||||
p_input->pf_read = input_FDNetworkRead;
|
||||
p_input->pf_set_program = SetProgram;
|
||||
p_input->pf_set_area = NULL;
|
||||
p_input->pf_seek = Seek;
|
||||
|
||||
vlc_mutex_lock( &p_input->stream.stream_lock );
|
||||
p_input->stream.b_pace_control = 1;
|
||||
p_input->stream.b_seekable = 1;
|
||||
p_input->stream.p_selected_area->i_tell = 0;
|
||||
p_input->stream.p_selected_area->i_size = 0;
|
||||
p_input->stream.i_method = INPUT_METHOD_NETWORK;
|
||||
vlc_mutex_unlock( &p_input->stream.stream_lock );
|
||||
p_input->i_mtu = 0;
|
||||
|
||||
if( HTTPConnect( p_input, 0 ) )
|
||||
{
|
||||
char * psz_pos = strstr(p_access_data->psz_buffer, "HTTP/1.1");
|
||||
p_input->stream.b_seekable = 0;
|
||||
psz_pos[7] = '0';
|
||||
if( HTTPConnect( p_input, 0 ) )
|
||||
{
|
||||
free( p_input->p_access_data );
|
||||
free( psz_name );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Close: free unused data structures
|
||||
*****************************************************************************/
|
||||
static void Close( vlc_object_t *p_this )
|
||||
{
|
||||
input_thread_t * p_input = (input_thread_t *)p_this;
|
||||
_input_socket_t * p_access_data =
|
||||
(_input_socket_t *)p_input->p_access_data;
|
||||
|
||||
free( p_access_data->psz_name );
|
||||
input_FDNetworkClose( p_input );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* SetProgram: do nothing
|
||||
*****************************************************************************/
|
||||
static int SetProgram( input_thread_t * p_input,
|
||||
pgrm_descriptor_t * p_program )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Seek: close and re-open a connection at the right place
|
||||
*****************************************************************************/
|
||||
static void Seek( input_thread_t * p_input, off_t i_pos )
|
||||
{
|
||||
_input_socket_t * p_access_data = p_input->p_access_data;
|
||||
close( p_access_data->_socket.i_handle );
|
||||
msg_Dbg( p_input, "seeking to position %lld", i_pos );
|
||||
HTTPConnect( p_input, i_pos );
|
||||
}
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* udp.c: raw UDP access plug-in
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001, 2002 VideoLAN
|
||||
* $Id: udp.c,v 1.12 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Christophe Massiot <massiot@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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/input.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#elif defined( _MSC_VER ) && defined( _WIN32 )
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#include "network.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int Open ( vlc_object_t * );
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
set_description( _("raw UDP access module") );
|
||||
set_capability( "access", 0 );
|
||||
add_shortcut( "udpstream" );
|
||||
add_shortcut( "udp4" );
|
||||
add_shortcut( "udp6" );
|
||||
set_callbacks( Open, __input_FDNetworkClose );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* Open: open the socket
|
||||
*****************************************************************************/
|
||||
static int Open( vlc_object_t *p_this )
|
||||
{
|
||||
input_thread_t * p_input = (input_thread_t *)p_this;
|
||||
input_socket_t * p_access_data;
|
||||
module_t * p_network;
|
||||
char * psz_network = "";
|
||||
char * psz_name = strdup(p_input->psz_name);
|
||||
char * psz_parser = psz_name;
|
||||
char * psz_server_addr = "";
|
||||
char * psz_server_port = "";
|
||||
char * psz_bind_addr = "";
|
||||
char * psz_bind_port = "";
|
||||
int i_bind_port = 0, i_server_port = 0;
|
||||
network_socket_t socket_desc;
|
||||
|
||||
if( config_GetInt( p_input, "ipv4" ) )
|
||||
{
|
||||
psz_network = "ipv4";
|
||||
}
|
||||
if( config_GetInt( p_input, "ipv6" ) )
|
||||
{
|
||||
psz_network = "ipv6";
|
||||
}
|
||||
|
||||
if( *p_input->psz_access )
|
||||
{
|
||||
/* Find out which shortcut was used */
|
||||
if( !strncmp( p_input->psz_access, "udp6", 5 ) )
|
||||
{
|
||||
psz_network = "ipv6";
|
||||
}
|
||||
else if( !strncmp( p_input->psz_access, "udp4", 5 ) )
|
||||
{
|
||||
psz_network = "ipv4";
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse psz_name syntax :
|
||||
* [serveraddr[:serverport]][@[bindaddr]:[bindport]] */
|
||||
|
||||
if( *psz_parser && *psz_parser != '@' )
|
||||
{
|
||||
/* Found server */
|
||||
psz_server_addr = psz_parser;
|
||||
|
||||
while( *psz_parser && *psz_parser != ':' && *psz_parser != '@' )
|
||||
{
|
||||
if( *psz_parser == '[' )
|
||||
{
|
||||
/* IPv6 address */
|
||||
while( *psz_parser && *psz_parser != ']' )
|
||||
{
|
||||
psz_parser++;
|
||||
}
|
||||
}
|
||||
psz_parser++;
|
||||
}
|
||||
|
||||
if( *psz_parser == ':' )
|
||||
{
|
||||
/* Found server port */
|
||||
*psz_parser = '\0'; /* Terminate server name */
|
||||
psz_parser++;
|
||||
psz_server_port = psz_parser;
|
||||
|
||||
while( *psz_parser && *psz_parser != '@' )
|
||||
{
|
||||
psz_parser++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( *psz_parser == '@' )
|
||||
{
|
||||
/* Found bind address or bind port */
|
||||
*psz_parser = '\0'; /* Terminate server port or name if necessary */
|
||||
psz_parser++;
|
||||
|
||||
if( *psz_parser && *psz_parser != ':' )
|
||||
{
|
||||
/* Found bind address */
|
||||
psz_bind_addr = psz_parser;
|
||||
|
||||
while( *psz_parser && *psz_parser != ':' )
|
||||
{
|
||||
if( *psz_parser == '[' )
|
||||
{
|
||||
/* IPv6 address */
|
||||
while( *psz_parser && *psz_parser != ']' )
|
||||
{
|
||||
psz_parser++;
|
||||
}
|
||||
}
|
||||
psz_parser++;
|
||||
}
|
||||
}
|
||||
|
||||
if( *psz_parser == ':' )
|
||||
{
|
||||
/* Found bind port */
|
||||
*psz_parser = '\0'; /* Terminate bind address if necessary */
|
||||
psz_parser++;
|
||||
|
||||
psz_bind_port = psz_parser;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert ports format */
|
||||
if( *psz_server_port )
|
||||
{
|
||||
i_server_port = strtol( psz_server_port, &psz_parser, 10 );
|
||||
if( *psz_parser )
|
||||
{
|
||||
msg_Err( p_input, "cannot parse server port near %s", psz_parser );
|
||||
free(psz_name);
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
if( *psz_bind_port )
|
||||
{
|
||||
i_bind_port = strtol( psz_bind_port, &psz_parser, 10 );
|
||||
if( *psz_parser )
|
||||
{
|
||||
msg_Err( p_input, "cannot parse bind port near %s", psz_parser );
|
||||
free(psz_name);
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
p_input->pf_read = input_FDNetworkRead;
|
||||
p_input->pf_set_program = input_SetProgram;
|
||||
p_input->pf_set_area = NULL;
|
||||
p_input->pf_seek = NULL;
|
||||
|
||||
vlc_mutex_lock( &p_input->stream.stream_lock );
|
||||
p_input->stream.b_pace_control = 0;
|
||||
p_input->stream.b_seekable = 0;
|
||||
p_input->stream.p_selected_area->i_tell = 0;
|
||||
p_input->stream.i_method = INPUT_METHOD_NETWORK;
|
||||
vlc_mutex_unlock( &p_input->stream.stream_lock );
|
||||
|
||||
if( *psz_server_addr || i_server_port )
|
||||
{
|
||||
msg_Err( p_input, "this UDP syntax is deprecated; the server argument will be");
|
||||
msg_Err( p_input, "ignored (%s:%d). If you wanted to enter a multicast address",
|
||||
psz_server_addr, i_server_port);
|
||||
msg_Err( p_input, "or local port, type : %s:@%s:%d",
|
||||
*p_input->psz_access ? p_input->psz_access : "udp",
|
||||
psz_server_addr, i_server_port );
|
||||
|
||||
i_server_port = 0;
|
||||
psz_server_addr = "";
|
||||
}
|
||||
|
||||
msg_Dbg( p_input, "opening server=%s:%d local=%s:%d",
|
||||
psz_server_addr, i_server_port, psz_bind_addr, i_bind_port );
|
||||
|
||||
/* Prepare the network_socket_t structure */
|
||||
socket_desc.i_type = NETWORK_UDP;
|
||||
socket_desc.psz_bind_addr = psz_bind_addr;
|
||||
socket_desc.i_bind_port = i_bind_port;
|
||||
socket_desc.psz_server_addr = psz_server_addr;
|
||||
socket_desc.i_server_port = i_server_port;
|
||||
|
||||
/* Find an appropriate network module */
|
||||
p_input->p_private = (void*) &socket_desc;
|
||||
p_network = module_Need( p_input, "network", psz_network );
|
||||
free(psz_name);
|
||||
if( p_network == NULL )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
module_Unneed( p_input, p_network );
|
||||
|
||||
p_access_data = p_input->p_access_data = malloc( sizeof(input_socket_t) );
|
||||
if( p_access_data == NULL )
|
||||
{
|
||||
msg_Err( p_input, "out of memory" );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
p_access_data->i_handle = socket_desc.i_handle;
|
||||
p_input->i_mtu = socket_desc.i_mtu;
|
||||
|
||||
return( 0 );
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1 +0,0 @@
|
|||
alsa_SOURCES = alsa.c
|
|
@ -1,420 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* alsa.c : alsa plugin for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000-2001 VideoLAN
|
||||
* $Id: alsa.c,v 1.21 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Henri Fallon <henri@videolan.org> - Original Author
|
||||
* Jeffrey Baker <jwbaker@acm.org> - Port to ALSA 1.0 API
|
||||
* John Paul Lorenti <jpl31@columbia.edu> - Device selection
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <string.h> /* strerror() */
|
||||
#include <stdlib.h> /* calloc(), malloc(), free() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/aout.h>
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int Open ( vlc_object_t * );
|
||||
static void Close ( vlc_object_t * );
|
||||
|
||||
static int SetFormat ( aout_thread_t * );
|
||||
static int GetBufInfo ( aout_thread_t *, int );
|
||||
static void Play ( aout_thread_t *, byte_t *, int );
|
||||
|
||||
static void HandleXrun ( aout_thread_t *);
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
add_category_hint( N_("Device"), NULL );
|
||||
add_string( "alsa-device", NULL, NULL, N_("Name"), NULL );
|
||||
set_description( _("ALSA audio module") );
|
||||
set_capability( "audio output", 50 );
|
||||
set_callbacks( Open, Close );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
typedef struct alsa_device_t
|
||||
{
|
||||
int i_num;
|
||||
} alsa_device_t;
|
||||
|
||||
typedef struct alsa_card_t
|
||||
{
|
||||
int i_num;
|
||||
} alsa_card_t;
|
||||
|
||||
/* here we store plugin dependant informations */
|
||||
|
||||
struct aout_sys_t
|
||||
{
|
||||
snd_pcm_t * p_alsa_handle;
|
||||
unsigned long buffer_time;
|
||||
unsigned long period_time;
|
||||
unsigned long chunk_size;
|
||||
unsigned long buffer_size;
|
||||
unsigned long rate;
|
||||
unsigned int bytes_per_sample;
|
||||
unsigned int samples_per_frame;
|
||||
unsigned int bytes_per_frame;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Open: create a handle and open an alsa device
|
||||
*****************************************************************************
|
||||
* This function opens an alsa device, through the alsa API
|
||||
*****************************************************************************/
|
||||
static int Open( vlc_object_t *p_this )
|
||||
{
|
||||
aout_thread_t *p_aout = (aout_thread_t *)p_this;
|
||||
|
||||
/* Allows user to choose which ALSA device to use */
|
||||
char psz_alsadev[128];
|
||||
char *psz_device, *psz_userdev;
|
||||
int i_ret;
|
||||
|
||||
/* Allocate structures */
|
||||
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
|
||||
if( p_aout->p_sys == NULL )
|
||||
{
|
||||
msg_Err( p_aout, "out of memory" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
p_aout->pf_setformat = SetFormat;
|
||||
p_aout->pf_getbufinfo = GetBufInfo;
|
||||
p_aout->pf_play = Play;
|
||||
|
||||
/* Read in ALSA device preferences from configuration */
|
||||
psz_userdev = config_GetPsz( p_aout, "alsa-device" );
|
||||
|
||||
if( psz_userdev )
|
||||
{
|
||||
psz_device = psz_userdev;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the internal logic to decide on the device name */
|
||||
if( p_aout->i_format != AOUT_FMT_AC3 )
|
||||
{
|
||||
psz_device = "default";
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char s[4];
|
||||
s[0] = IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO;
|
||||
s[1] = IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER;
|
||||
s[2] = 0;
|
||||
s[3] = IEC958_AES3_CON_FS_48000;
|
||||
sprintf( psz_alsadev,
|
||||
"iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
|
||||
s[0], s[1], s[2], s[3] );
|
||||
psz_device = psz_alsadev;
|
||||
}
|
||||
}
|
||||
|
||||
/* Open device */
|
||||
i_ret = snd_pcm_open( &(p_aout->p_sys->p_alsa_handle),
|
||||
psz_device, SND_PCM_STREAM_PLAYBACK, 0);
|
||||
if( i_ret != 0 )
|
||||
{
|
||||
msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
|
||||
psz_device, snd_strerror(i_ret) );
|
||||
if( psz_userdev )
|
||||
{
|
||||
free( psz_userdev );
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( psz_userdev )
|
||||
{
|
||||
free( psz_userdev );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* SetFormat : sets the alsa output format
|
||||
*****************************************************************************
|
||||
* This function prepares the device, sets the rate, format, the mode
|
||||
* ( "play as soon as you have data" ), and buffer information.
|
||||
*****************************************************************************/
|
||||
static int SetFormat( aout_thread_t *p_aout )
|
||||
{
|
||||
int i_rv;
|
||||
int i_format;
|
||||
|
||||
snd_pcm_hw_params_t *p_hw;
|
||||
snd_pcm_sw_params_t *p_sw;
|
||||
|
||||
snd_pcm_hw_params_alloca(&p_hw);
|
||||
snd_pcm_sw_params_alloca(&p_sw);
|
||||
|
||||
/* default value for snd_pcm_hw_params_set_buffer_time_near() */
|
||||
p_aout->p_sys->buffer_time = AOUT_BUFFER_DURATION;
|
||||
|
||||
switch (p_aout->i_format)
|
||||
{
|
||||
case AOUT_FMT_S16_LE:
|
||||
i_format = SND_PCM_FORMAT_S16_LE;
|
||||
p_aout->p_sys->bytes_per_sample = 2;
|
||||
break;
|
||||
|
||||
case AOUT_FMT_AC3:
|
||||
i_format = SND_PCM_FORMAT_S16_LE;
|
||||
p_aout->p_sys->bytes_per_sample = 2;
|
||||
/* buffer_time must be 500000 to avoid a system crash */
|
||||
p_aout->p_sys->buffer_time = 500000;
|
||||
break;
|
||||
|
||||
default:
|
||||
i_format = SND_PCM_FORMAT_S16_BE;
|
||||
p_aout->p_sys->bytes_per_sample = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
p_aout->p_sys->samples_per_frame = p_aout->i_channels;
|
||||
p_aout->p_sys->bytes_per_frame = p_aout->p_sys->samples_per_frame *
|
||||
p_aout->p_sys->bytes_per_sample;
|
||||
|
||||
i_rv = snd_pcm_hw_params_any( p_aout->p_sys->p_alsa_handle, p_hw );
|
||||
if( i_rv < 0 )
|
||||
{
|
||||
msg_Err( p_aout, "unable to retrieve initial parameters" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
i_rv = snd_pcm_hw_params_set_access( p_aout->p_sys->p_alsa_handle, p_hw,
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED );
|
||||
if( i_rv < 0 )
|
||||
{
|
||||
msg_Err( p_aout, "unable to set interleaved stream format" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
i_rv = snd_pcm_hw_params_set_format( p_aout->p_sys->p_alsa_handle,
|
||||
p_hw, i_format );
|
||||
if( i_rv < 0 )
|
||||
{
|
||||
msg_Err( p_aout, "unable to set stream sample size and word order" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
i_rv = snd_pcm_hw_params_set_channels( p_aout->p_sys->p_alsa_handle, p_hw,
|
||||
p_aout->i_channels );
|
||||
if( i_rv < 0 )
|
||||
{
|
||||
msg_Err( p_aout, "unable to set number of output channels" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
i_rv = snd_pcm_hw_params_set_rate_near( p_aout->p_sys->p_alsa_handle, p_hw,
|
||||
p_aout->i_rate, 0 );
|
||||
if( i_rv < 0 )
|
||||
{
|
||||
msg_Err( p_aout, "unable to set sample rate" );
|
||||
return -1;
|
||||
}
|
||||
p_aout->p_sys->rate = i_rv;
|
||||
|
||||
i_rv = snd_pcm_hw_params_set_buffer_time_near( p_aout->p_sys->p_alsa_handle,
|
||||
p_hw,
|
||||
p_aout->p_sys->buffer_time,
|
||||
0 );
|
||||
if( i_rv < 0 )
|
||||
{
|
||||
msg_Err( p_aout, "unable to set buffer time" );
|
||||
return -1;
|
||||
}
|
||||
p_aout->p_sys->buffer_time = i_rv;
|
||||
|
||||
i_rv = snd_pcm_hw_params_set_period_time_near( p_aout->p_sys->p_alsa_handle,
|
||||
p_hw, p_aout->p_sys->buffer_time / p_aout->p_sys->bytes_per_frame, 0 );
|
||||
if( i_rv < 0 )
|
||||
{
|
||||
msg_Err( p_aout, "unable to set period time" );
|
||||
return -1;
|
||||
}
|
||||
p_aout->p_sys->period_time = i_rv;
|
||||
|
||||
i_rv = snd_pcm_hw_params(p_aout->p_sys->p_alsa_handle, p_hw);
|
||||
if (i_rv < 0)
|
||||
{
|
||||
msg_Err( p_aout, "unable to set hardware configuration" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
p_aout->p_sys->chunk_size = snd_pcm_hw_params_get_period_size( p_hw, 0 );
|
||||
p_aout->p_sys->buffer_size = snd_pcm_hw_params_get_buffer_size( p_hw );
|
||||
|
||||
snd_pcm_sw_params_current( p_aout->p_sys->p_alsa_handle, p_sw );
|
||||
i_rv = snd_pcm_sw_params_set_sleep_min( p_aout->p_sys->p_alsa_handle, p_sw,
|
||||
0 );
|
||||
|
||||
i_rv = snd_pcm_sw_params_set_avail_min( p_aout->p_sys->p_alsa_handle, p_sw,
|
||||
p_aout->p_sys->chunk_size );
|
||||
|
||||
/* Worked with the CVS version but not with 0.9beta3
|
||||
i_rv = snd_pcm_sw_params_set_start_threshold( p_aout->p_sys->p_alsa_handle,
|
||||
p_sw, p_aout->p_sys->buffer_size );
|
||||
|
||||
i_rv = snd_pcm_sw_params_set_stop_threshold( p_aout->p_sys->p_alsa_handle,
|
||||
p_sw, p_aout->p_sys->buffer_size);
|
||||
*/
|
||||
i_rv = snd_pcm_sw_params( p_aout->p_sys->p_alsa_handle, p_sw );
|
||||
if( i_rv < 0 )
|
||||
{
|
||||
msg_Err( p_aout, "unable to set software configuration" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* HandleXrun : reprepare the output
|
||||
*****************************************************************************
|
||||
* When buffer gets empty, the driver goes in "Xrun" state, where it needs
|
||||
* to be reprepared before playing again
|
||||
*****************************************************************************/
|
||||
static void HandleXrun(aout_thread_t *p_aout)
|
||||
{
|
||||
int i_rv;
|
||||
|
||||
msg_Err( p_aout, "resetting output after buffer underrun" );
|
||||
|
||||
// i_rv = snd_pcm_reset( p_aout->p_sys->p_alsa_handle );
|
||||
i_rv = snd_pcm_prepare( p_aout->p_sys->p_alsa_handle );
|
||||
if( i_rv < 0 )
|
||||
{
|
||||
msg_Err( p_aout, "unable to recover from buffer underrun (%s)",
|
||||
snd_strerror( i_rv ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* BufInfo: buffer status query
|
||||
*****************************************************************************
|
||||
* This function returns the number of used byte in the queue.
|
||||
* It also deals with errors : indeed if the device comes to run out
|
||||
* of data to play, it switches to the "underrun" status. It has to
|
||||
* be flushed and re-prepared
|
||||
*****************************************************************************/
|
||||
static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
|
||||
{
|
||||
snd_pcm_status_t *p_status;
|
||||
int i_alsa_get_status_returns;
|
||||
|
||||
snd_pcm_status_alloca( &p_status );
|
||||
|
||||
i_alsa_get_status_returns = snd_pcm_status( p_aout->p_sys->p_alsa_handle,
|
||||
p_status );
|
||||
|
||||
if( i_alsa_get_status_returns )
|
||||
{
|
||||
msg_Err( p_aout, "failed getting alsa buffer info (%s)",
|
||||
snd_strerror ( i_alsa_get_status_returns ) );
|
||||
return ( -1 );
|
||||
}
|
||||
|
||||
switch( snd_pcm_status_get_state( p_status ) )
|
||||
{
|
||||
case SND_PCM_STATE_XRUN :
|
||||
HandleXrun( p_aout );
|
||||
break;
|
||||
|
||||
case SND_PCM_STATE_OPEN:
|
||||
case SND_PCM_STATE_PREPARED:
|
||||
case SND_PCM_STATE_RUNNING:
|
||||
break;
|
||||
|
||||
default:
|
||||
msg_Err( p_aout, "unhandled condition %i",
|
||||
snd_pcm_status_get_state( p_status ) );
|
||||
break;
|
||||
}
|
||||
|
||||
return snd_pcm_status_get_avail(p_status) * p_aout->p_sys->bytes_per_frame;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Play : plays a sample
|
||||
*****************************************************************************
|
||||
* Plays a sample using the snd_pcm_writei function from the alsa API
|
||||
*****************************************************************************/
|
||||
static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
|
||||
{
|
||||
snd_pcm_uframes_t tot_frames;
|
||||
snd_pcm_uframes_t frames_left;
|
||||
snd_pcm_uframes_t rv;
|
||||
|
||||
tot_frames = i_size / p_aout->p_sys->bytes_per_frame;
|
||||
frames_left = tot_frames;
|
||||
|
||||
while( frames_left > 0 )
|
||||
{
|
||||
rv = snd_pcm_writei( p_aout->p_sys->p_alsa_handle, buffer +
|
||||
(tot_frames - frames_left) *
|
||||
p_aout->p_sys->bytes_per_frame, frames_left );
|
||||
|
||||
if( (signed int) rv < 0 )
|
||||
{
|
||||
msg_Err( p_aout, "failed writing to output (%s)",
|
||||
snd_strerror( rv ) );
|
||||
return;
|
||||
}
|
||||
|
||||
frames_left -= rv;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Close: close the Alsa device
|
||||
*****************************************************************************/
|
||||
static void Close( vlc_object_t *p_this )
|
||||
{
|
||||
aout_thread_t *p_aout = (aout_thread_t *)p_this;
|
||||
int i_close_returns;
|
||||
|
||||
i_close_returns = snd_pcm_close( p_aout->p_sys->p_alsa_handle );
|
||||
|
||||
if( i_close_returns )
|
||||
{
|
||||
msg_Err( p_aout, "failed closing ALSA device (%s)",
|
||||
snd_strerror( i_close_returns ) );
|
||||
}
|
||||
|
||||
free( p_aout->p_sys );
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1 +0,0 @@
|
|||
arts_SOURCES = arts.c
|
|
@ -1,150 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* arts.c : aRts module
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
*
|
||||
* Authors: Emmanuel Blindauer <manu@agat.net>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <fcntl.h> /* open(), O_WRONLY */
|
||||
#include <string.h> /* strerror() */
|
||||
#include <unistd.h> /* write(), close() */
|
||||
#include <stdlib.h> /* calloc(), malloc(), free() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/aout.h>
|
||||
|
||||
#include <artsc.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* aout_sys_t: arts audio output method descriptor
|
||||
*****************************************************************************
|
||||
* This structure is part of the audio output thread descriptor.
|
||||
* It describes some arts specific variables.
|
||||
*****************************************************************************/
|
||||
struct aout_sys_t
|
||||
{
|
||||
arts_stream_t stream;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int Open ( vlc_object_t * );
|
||||
static void Close ( vlc_object_t * );
|
||||
|
||||
static int SetFormat ( aout_thread_t * );
|
||||
static int GetBufInfo ( aout_thread_t *, int );
|
||||
static void Play ( aout_thread_t *, byte_t *, int );
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
set_description( _("aRts audio module") );
|
||||
set_capability( "audio output", 50 );
|
||||
set_callbacks( Open, Close );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* Open: initialize arts connection to server
|
||||
*****************************************************************************/
|
||||
static int Open( vlc_object_t *p_this )
|
||||
{
|
||||
aout_thread_t *p_aout = (aout_thread_t *)p_this;
|
||||
int i_err = 0;
|
||||
|
||||
/* Allocate structure */
|
||||
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
|
||||
if( p_aout->p_sys == NULL )
|
||||
{
|
||||
msg_Err( p_aout, "out of memory" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
i_err = arts_init();
|
||||
|
||||
if (i_err < 0)
|
||||
{
|
||||
msg_Err( p_aout, "arts_init failed (%s)", arts_error_text(i_err) );
|
||||
free( p_aout->p_sys );
|
||||
return(-1);
|
||||
}
|
||||
|
||||
p_aout->pf_setformat = SetFormat;
|
||||
p_aout->pf_getbufinfo = GetBufInfo;
|
||||
p_aout->pf_play = Play;
|
||||
|
||||
p_aout->p_sys->stream =
|
||||
arts_play_stream( p_aout->i_rate, 16, p_aout->i_channels, "vlc" );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* SetFormat: set the output format
|
||||
*****************************************************************************/
|
||||
static int SetFormat( aout_thread_t *p_aout )
|
||||
{
|
||||
/*Not ready*/
|
||||
/* p_aout->i_latency = esd_get_latency(i_fd);*/
|
||||
p_aout->i_latency = 0;
|
||||
|
||||
//msg_Dbg( p_aout, "aout_arts_latency: %d", p_aout->i_latency );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* GetBufInfo: buffer status query
|
||||
*****************************************************************************/
|
||||
static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
|
||||
{
|
||||
/* arbitrary value that should be changed */
|
||||
return( i_buffer_limit );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Play: play a sound samples buffer
|
||||
*****************************************************************************
|
||||
* This function writes a buffer of i_length bytes in the socket
|
||||
*****************************************************************************/
|
||||
static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
|
||||
{
|
||||
int i_err = arts_write( p_aout->p_sys->stream, buffer, i_size );
|
||||
|
||||
if( i_err < 0 )
|
||||
{
|
||||
msg_Err( p_aout, "arts_write failed (%s)", arts_error_text(i_err) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Close: close the Esound socket
|
||||
*****************************************************************************/
|
||||
static void Close( vlc_object_t *p_this )
|
||||
{
|
||||
aout_thread_t *p_aout = (aout_thread_t *)p_this;
|
||||
|
||||
arts_close_stream( p_aout->p_sys->stream );
|
||||
free( p_aout->p_sys );
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
*.bak
|
||||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1,2 +0,0 @@
|
|||
avi_SOURCES = avi.c libioRIFF.c
|
||||
|
2228
plugins/avi/avi.c
2228
plugins/avi/avi.c
File diff suppressed because it is too large
Load Diff
|
@ -1,263 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* avi.h : AVI file Stream input module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: avi.h,v 1.10 2002/07/23 00:39:16 sam 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 MAX_PACKETS_IN_FIFO 2
|
||||
|
||||
/* flags for use in <dwFlags> in AVIFileHdr */
|
||||
#define AVIF_HASINDEX 0x00000010 /* Index at end of file? */
|
||||
#define AVIF_MUSTUSEINDEX 0x00000020
|
||||
#define AVIF_ISINTERLEAVED 0x00000100
|
||||
#define AVIF_TRUSTCKTYPE 0x00000800 /* Use CKType to find key frames? */
|
||||
#define AVIF_WASCAPTUREFILE 0x00010000
|
||||
#define AVIF_COPYRIGHTED 0x00020000
|
||||
|
||||
/* Flags for index */
|
||||
#define AVIIF_LIST 0x00000001L /* chunk is a 'LIST' */
|
||||
#define AVIIF_KEYFRAME 0x00000010L /* this frame is a key frame.*/
|
||||
#define AVIIF_NOTIME 0x00000100L /* this frame doesn't take any time */
|
||||
#define AVIIF_COMPUSE 0x0FFF0000L /* these bits are for compressor use */
|
||||
|
||||
#define AVIIF_FIXKEYFRAME 0x00001000L /* invented; used to say that
|
||||
the keyframe flag isn't a true flag
|
||||
but have to be verified */
|
||||
|
||||
/* AVI stuff */
|
||||
#define FOURCC_RIFF VLC_FOURCC('R','I','F','F')
|
||||
#define FOURCC_LIST VLC_FOURCC('L','I','S','T')
|
||||
#define FOURCC_JUNK VLC_FOURCC('J','U','N','K')
|
||||
#define FOURCC_AVI VLC_FOURCC('A','V','I',' ')
|
||||
#define FOURCC_WAVE VLC_FOURCC('W','A','V','E')
|
||||
|
||||
#define FOURCC_avih VLC_FOURCC('a','v','i','h')
|
||||
#define FOURCC_hdrl VLC_FOURCC('h','d','r','l')
|
||||
#define FOURCC_movi VLC_FOURCC('m','o','v','i')
|
||||
#define FOURCC_idx1 VLC_FOURCC('i','d','x','1')
|
||||
|
||||
#define FOURCC_strl VLC_FOURCC('s','t','r','l')
|
||||
#define FOURCC_strh VLC_FOURCC('s','t','r','h')
|
||||
#define FOURCC_strf VLC_FOURCC('s','t','r','f')
|
||||
#define FOURCC_strd VLC_FOURCC('s','t','r','d')
|
||||
|
||||
#define FOURCC_rec VLC_FOURCC('r','e','c',' ')
|
||||
#define FOURCC_auds VLC_FOURCC('a','u','d','s')
|
||||
#define FOURCC_vids VLC_FOURCC('v','i','d','s')
|
||||
|
||||
#define TWOCC_wb VLC_TWOCC('w','b')
|
||||
#define TWOCC_db VLC_TWOCC('d','b')
|
||||
#define TWOCC_dc VLC_TWOCC('d','c')
|
||||
#define TWOCC_pc VLC_TWOCC('p','c')
|
||||
|
||||
/* MPEG4 video */
|
||||
#define FOURCC_DIVX VLC_FOURCC('D','I','V','X')
|
||||
#define FOURCC_divx VLC_FOURCC('d','i','v','x')
|
||||
#define FOURCC_DIV1 VLC_FOURCC('D','I','V','1')
|
||||
#define FOURCC_div1 VLC_FOURCC('d','i','v','1')
|
||||
#define FOURCC_MP4S VLC_FOURCC('M','P','4','S')
|
||||
#define FOURCC_mp4s VLC_FOURCC('m','p','4','s')
|
||||
#define FOURCC_M4S2 VLC_FOURCC('M','4','S','2')
|
||||
#define FOURCC_m4s2 VLC_FOURCC('m','4','s','2')
|
||||
#define FOURCC_xvid VLC_FOURCC('x','v','i','d')
|
||||
#define FOURCC_XVID VLC_FOURCC('X','V','I','D')
|
||||
#define FOURCC_XviD VLC_FOURCC('X','v','i','D')
|
||||
#define FOURCC_DX50 VLC_FOURCC('D','X','5','0')
|
||||
#define FOURCC_mp4v VLC_FOURCC('m','p','4','v')
|
||||
#define FOURCC_4 VLC_FOURCC( 4, 0, 0, 0 )
|
||||
|
||||
/* MSMPEG4 v2 */
|
||||
#define FOURCC_MPG4 VLC_FOURCC('M','P','G','4')
|
||||
#define FOURCC_mpg4 VLC_FOURCC('m','p','g','4')
|
||||
#define FOURCC_DIV2 VLC_FOURCC('D','I','V','2')
|
||||
#define FOURCC_div2 VLC_FOURCC('d','i','v','2')
|
||||
#define FOURCC_MP42 VLC_FOURCC('M','P','4','2')
|
||||
#define FOURCC_mp42 VLC_FOURCC('m','p','4','2')
|
||||
|
||||
/* MSMPEG4 v3 / M$ mpeg4 v3 */
|
||||
#define FOURCC_MPG3 VLC_FOURCC('M','P','G','3')
|
||||
#define FOURCC_mpg3 VLC_FOURCC('m','p','g','3')
|
||||
#define FOURCC_div3 VLC_FOURCC('d','i','v','3')
|
||||
#define FOURCC_MP43 VLC_FOURCC('M','P','4','3')
|
||||
#define FOURCC_mp43 VLC_FOURCC('m','p','4','3')
|
||||
|
||||
/* DivX 3.20 */
|
||||
#define FOURCC_DIV3 VLC_FOURCC('D','I','V','3')
|
||||
#define FOURCC_DIV4 VLC_FOURCC('D','I','V','4')
|
||||
#define FOURCC_div4 VLC_FOURCC('d','i','v','4')
|
||||
#define FOURCC_DIV5 VLC_FOURCC('D','I','V','5')
|
||||
#define FOURCC_div5 VLC_FOURCC('d','i','v','5')
|
||||
#define FOURCC_DIV6 VLC_FOURCC('D','I','V','6')
|
||||
#define FOURCC_div6 VLC_FOURCC('d','i','v','6')
|
||||
|
||||
/* AngelPotion stuff */
|
||||
#define FOURCC_AP41 VLC_FOURCC('A','P','4','1')
|
||||
|
||||
/* ?? */
|
||||
#define FOURCC_3IV1 VLC_FOURCC('3','I','V','1')
|
||||
/* H263 and H263i */
|
||||
#define FOURCC_H263 VLC_FOURCC('H','2','6','3')
|
||||
#define FOURCC_h263 VLC_FOURCC('h','2','6','3')
|
||||
#define FOURCC_U263 VLC_FOURCC('U','2','6','3')
|
||||
#define FOURCC_I263 VLC_FOURCC('I','2','6','3')
|
||||
#define FOURCC_i263 VLC_FOURCC('i','2','6','3')
|
||||
|
||||
/* Sound formats */
|
||||
#define WAVE_FORMAT_UNKNOWN 0x0000
|
||||
#define WAVE_FORMAT_PCM 0x0001
|
||||
#define WAVE_FORMAT_MPEG 0x0050
|
||||
#define WAVE_FORMAT_MPEGLAYER3 0x0055
|
||||
#define WAVE_FORMAT_AC3 0x2000
|
||||
|
||||
typedef struct bitmapinfoheader_s
|
||||
{
|
||||
u32 i_size; /* size of header */
|
||||
u32 i_width;
|
||||
u32 i_height;
|
||||
u16 i_planes;
|
||||
u16 i_bitcount;
|
||||
u32 i_compression;
|
||||
u32 i_sizeimage;
|
||||
u32 i_xpelspermeter;
|
||||
u32 i_ypelspermeter;
|
||||
u32 i_clrused;
|
||||
u32 i_clrimportant;
|
||||
} bitmapinfoheader_t;
|
||||
|
||||
typedef struct waveformatex_s
|
||||
{
|
||||
u16 i_formattag;
|
||||
u16 i_channels;
|
||||
u32 i_samplespersec;
|
||||
u32 i_avgbytespersec;
|
||||
u16 i_blockalign;
|
||||
u16 i_bitspersample;
|
||||
u16 i_size; /* the extra size in bytes */
|
||||
} waveformatex_t;
|
||||
|
||||
|
||||
typedef struct MainAVIHeader_s
|
||||
{
|
||||
u32 i_microsecperframe;
|
||||
u32 i_maxbytespersec;
|
||||
u32 i_reserved1; /* dwPaddingGranularity; pad to multiples of this
|
||||
size; normally 2K */
|
||||
u32 i_flags;
|
||||
u32 i_totalframes;
|
||||
u32 i_initialframes;
|
||||
u32 i_streams;
|
||||
u32 i_suggestedbuffersize;
|
||||
u32 i_width;
|
||||
u32 i_height;
|
||||
u32 i_scale;
|
||||
u32 i_rate;
|
||||
u32 i_start;
|
||||
u32 i_length;
|
||||
|
||||
} MainAVIHeader_t;
|
||||
|
||||
typedef struct AVIStreamHeader_s
|
||||
{
|
||||
u32 i_type;
|
||||
u32 i_handler;
|
||||
u32 i_flags;
|
||||
u32 i_reserved1; /* wPriority wLanguage */
|
||||
u32 i_initialframes;
|
||||
u32 i_scale;
|
||||
u32 i_rate;
|
||||
u32 i_start;
|
||||
u32 i_length; /* In units above... */
|
||||
u32 i_suggestedbuffersize;
|
||||
u32 i_quality;
|
||||
u32 i_samplesize;
|
||||
|
||||
} AVIStreamHeader_t;
|
||||
|
||||
typedef struct AVIIndexEntry_s
|
||||
{
|
||||
u32 i_id;
|
||||
u32 i_flags;
|
||||
u32 i_pos;
|
||||
u32 i_length;
|
||||
u32 i_lengthtotal;
|
||||
} AVIIndexEntry_t;
|
||||
|
||||
typedef struct AVIESBuffer_s
|
||||
{
|
||||
struct AVIESBuffer_s *p_next;
|
||||
|
||||
pes_packet_t *p_pes;
|
||||
int i_posc;
|
||||
int i_posb;
|
||||
} AVIESBuffer_t;
|
||||
|
||||
|
||||
typedef struct AVIStreamInfo_s
|
||||
{
|
||||
|
||||
riffchunk_t *p_strl;
|
||||
riffchunk_t *p_strh;
|
||||
riffchunk_t *p_strf;
|
||||
riffchunk_t *p_strd; /* not used */
|
||||
|
||||
AVIStreamHeader_t header;
|
||||
|
||||
u8 i_cat; /* AUDIO_ES, VIDEO_ES */
|
||||
bitmapinfoheader_t video_format;
|
||||
waveformatex_t audio_format;
|
||||
es_descriptor_t *p_es;
|
||||
int b_selected; /* newly selected */
|
||||
AVIIndexEntry_t *p_index;
|
||||
int i_idxnb;
|
||||
int i_idxmax;
|
||||
|
||||
int i_idxposc; /* numero of chunk */
|
||||
int i_idxposb; /* byte in the current chunk */
|
||||
|
||||
/* add some buffering */
|
||||
AVIESBuffer_t *p_pes_first;
|
||||
AVIESBuffer_t *p_pes_last;
|
||||
int i_pes_count;
|
||||
int i_pes_totalsize;
|
||||
} AVIStreamInfo_t;
|
||||
|
||||
typedef struct demux_data_avi_file_s
|
||||
{
|
||||
mtime_t i_pcr;
|
||||
int i_rate;
|
||||
riffchunk_t *p_riff;
|
||||
riffchunk_t *p_hdrl;
|
||||
riffchunk_t *p_movi;
|
||||
riffchunk_t *p_idx1;
|
||||
|
||||
int b_seekable;
|
||||
|
||||
/* Info extrated from avih */
|
||||
MainAVIHeader_t avih;
|
||||
|
||||
/* number of stream and informations*/
|
||||
int i_streams;
|
||||
AVIStreamInfo_t **pp_info;
|
||||
|
||||
/* current audio and video es */
|
||||
AVIStreamInfo_t *p_info_video;
|
||||
AVIStreamInfo_t *p_info_audio;
|
||||
|
||||
} demux_data_avi_file_t;
|
||||
|
|
@ -1,442 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* libioRIFF.c : AVI file Stream input module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: libioRIFF.c,v 1.13 2002/07/23 00:39:16 sam 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/input.h>
|
||||
|
||||
#include "video.h"
|
||||
|
||||
#include "libioRIFF.h"
|
||||
|
||||
static inline u16 __GetWLE( byte_t *p_buff )
|
||||
{
|
||||
return( (*p_buff) + ( *(p_buff+1) <<8 ) );
|
||||
}
|
||||
|
||||
static inline u32 __GetDWLE( byte_t *p_buff )
|
||||
{
|
||||
return( *(p_buff) + ( *(p_buff+1) <<8 ) +
|
||||
( *(p_buff+2) <<16 ) + ( *(p_buff+3) <<24 ) );
|
||||
}
|
||||
|
||||
static inline u32 __EVEN( u32 i )
|
||||
{
|
||||
return( (i & 1) ? ++i : i );
|
||||
}
|
||||
|
||||
int __RIFF_TellPos( input_thread_t *p_input, u32 *pos )
|
||||
{
|
||||
vlc_mutex_lock( &p_input->stream.stream_lock );
|
||||
*pos= p_input->stream.p_selected_area->i_tell -
|
||||
( p_input->p_last_data - p_input->p_current_data );
|
||||
vlc_mutex_unlock( &p_input->stream.stream_lock );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __RIFF_SkipBytes(input_thread_t * p_input,int nb)
|
||||
{
|
||||
data_packet_t *p_pack;
|
||||
int i;
|
||||
int i_rest;
|
||||
if( ( p_input->stream.b_seekable )&&( p_input->stream.i_method == INPUT_METHOD_FILE ) )
|
||||
{
|
||||
u32 i_pos;
|
||||
__RIFF_TellPos( p_input, &i_pos);
|
||||
p_input->pf_seek( p_input, (off_t)(i_pos + nb) );
|
||||
input_AccessReinit( p_input );
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_Warn( p_input, "cannot seek, it will take times" );
|
||||
if( nb < 0 ) { return( -1 ); }
|
||||
i_rest = nb;
|
||||
while (i_rest != 0 )
|
||||
{
|
||||
if ( i_rest >= 4096 )
|
||||
{
|
||||
i = input_SplitBuffer( p_input, &p_pack, 4096);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = input_SplitBuffer( p_input, &p_pack, i_rest);
|
||||
}
|
||||
|
||||
if ( i < 0 ) { return ( -1 ); }
|
||||
i_rest-=i;
|
||||
input_DeletePacket( p_input->p_method_data, p_pack);
|
||||
if( ( i == 0 )&&( i_rest != 0 )) { return( -1 ); }
|
||||
}
|
||||
}
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
|
||||
void RIFF_DeleteChunk( input_thread_t *p_input, riffchunk_t *p_chunk )
|
||||
{
|
||||
if( p_chunk != NULL)
|
||||
{
|
||||
if( p_chunk->p_data != NULL )
|
||||
{
|
||||
input_DeletePacket( p_input->p_method_data, p_chunk->p_data );
|
||||
}
|
||||
free( p_chunk );
|
||||
}
|
||||
}
|
||||
|
||||
riffchunk_t * RIFF_ReadChunk(input_thread_t * p_input)
|
||||
{
|
||||
riffchunk_t * p_riff;
|
||||
int count;
|
||||
byte_t * p_peek;
|
||||
|
||||
if( !(p_riff = malloc( sizeof(riffchunk_t))) )
|
||||
{
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
p_riff->p_data = NULL;
|
||||
/* peek to have the begining, 8+8 get i_8bytes */
|
||||
|
||||
if( ( count = input_Peek( p_input, &p_peek, 16 ) ) < 8 )
|
||||
{
|
||||
msg_Err( p_input, "cannot peek()" );
|
||||
free(p_riff);
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
p_riff->i_id = __GetDWLE( p_peek );
|
||||
p_riff->i_size =__GetDWLE( p_peek + 4 );
|
||||
p_riff->i_type = ( count >= 12 ) ? __GetDWLE( p_peek + 8 ) : 0 ;
|
||||
memset( &p_riff->i_8bytes, 0, 8 );
|
||||
if( count >= 12 )
|
||||
{
|
||||
memcpy( &p_riff->i_8bytes, p_peek + 8, count - 8 );
|
||||
}
|
||||
__RIFF_TellPos(p_input, &(p_riff->i_pos) );
|
||||
|
||||
return( p_riff );
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Va au chunk juste d'apres si il en a encore *
|
||||
* -1 si erreur , 1 si y'en a plus *
|
||||
**************************************************/
|
||||
int RIFF_NextChunk( input_thread_t * p_input,riffchunk_t *p_rifffather)
|
||||
{
|
||||
int i_len;
|
||||
int i_lenfather;
|
||||
riffchunk_t *p_riff;
|
||||
|
||||
if( ( p_riff = RIFF_ReadChunk( p_input ) ) == NULL )
|
||||
{
|
||||
msg_Err( p_input, "cannot read chunk" );
|
||||
return( -1 );
|
||||
}
|
||||
i_len = __EVEN( p_riff->i_size );
|
||||
|
||||
if ( p_rifffather != NULL )
|
||||
{
|
||||
i_lenfather = __EVEN( p_rifffather->i_size );
|
||||
if ( p_rifffather->i_pos + i_lenfather <= p_riff->i_pos + i_len + 8 )
|
||||
{
|
||||
msg_Err( p_input, "next chunk out of bounds" );
|
||||
free( p_riff );
|
||||
return( 1 ); /* pas dans nos frontiere */
|
||||
}
|
||||
}
|
||||
if ( __RIFF_SkipBytes( p_input,i_len + 8 ) != 0 )
|
||||
{
|
||||
free( p_riff );
|
||||
msg_Err( p_input, "cannot go to the next chunk" );
|
||||
return( -1 );
|
||||
}
|
||||
free( p_riff );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Permet de rentrer dans un ck RIFF ou LIST *
|
||||
****************************************************************/
|
||||
int RIFF_DescendChunk(input_thread_t * p_input)
|
||||
{
|
||||
return( __RIFF_SkipBytes(p_input,12) != 0 ? -1 : 0 );
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* Permet de sortir d'un sous chunk et d'aller sur le suivant *
|
||||
* chunk *
|
||||
***************************************************************/
|
||||
|
||||
int RIFF_AscendChunk(input_thread_t * p_input ,riffchunk_t *p_riff)
|
||||
{
|
||||
int i_skip;
|
||||
u32 i_posactu;
|
||||
|
||||
__RIFF_TellPos(p_input, &i_posactu);
|
||||
i_skip = __EVEN( p_riff->i_pos + p_riff->i_size + 8 ) - i_posactu;
|
||||
return( (( __RIFF_SkipBytes(p_input,i_skip)) != 0) ? -1 : 0 );
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* Permet de se deplacer jusqu'au premier chunk avec le bon id *
|
||||
* *************************************************************/
|
||||
int RIFF_FindChunk(input_thread_t * p_input ,u32 i_id,riffchunk_t *p_rifffather)
|
||||
{
|
||||
riffchunk_t *p_riff = NULL;
|
||||
do
|
||||
{
|
||||
if ( p_riff )
|
||||
{
|
||||
free(p_riff);
|
||||
if ( RIFF_NextChunk(p_input ,p_rifffather) != 0 )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
p_riff=RIFF_ReadChunk(p_input);
|
||||
} while ( ( p_riff )&&( p_riff->i_id != i_id ) );
|
||||
|
||||
if ( ( !p_riff )||( p_riff->i_id != i_id ) )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
free( p_riff );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
* Permet de pointer sur la zone de donné du chunk courant *
|
||||
*****************************************************************/
|
||||
int RIFF_GoToChunkData(input_thread_t * p_input)
|
||||
{
|
||||
return( ( __RIFF_SkipBytes(p_input,8) != 0 ) ? -1 : 0 );
|
||||
}
|
||||
|
||||
int RIFF_LoadChunkData(input_thread_t * p_input,riffchunk_t *p_riff )
|
||||
{
|
||||
off_t i_read = __EVEN( p_riff->i_size );
|
||||
|
||||
RIFF_GoToChunkData(p_input);
|
||||
if ( input_SplitBuffer( p_input,
|
||||
&p_riff->p_data,
|
||||
i_read ) != i_read )
|
||||
{
|
||||
msg_Err( p_input, "cannot read enough data " );
|
||||
return ( -1 );
|
||||
}
|
||||
|
||||
if( p_riff->i_size&1 )
|
||||
{
|
||||
p_riff->p_data->p_payload_end--;
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int RIFF_LoadChunkDataInPES(input_thread_t * p_input,
|
||||
pes_packet_t **pp_pes,
|
||||
int i_size_index)
|
||||
{
|
||||
u32 i_read;
|
||||
data_packet_t *p_data;
|
||||
riffchunk_t *p_riff;
|
||||
int i_size;
|
||||
int b_pad = 0;
|
||||
|
||||
if( (p_riff = RIFF_ReadChunk( p_input )) == NULL )
|
||||
{
|
||||
*pp_pes = NULL;
|
||||
return( -1 );
|
||||
}
|
||||
RIFF_GoToChunkData(p_input);
|
||||
*pp_pes = input_NewPES( p_input->p_method_data );
|
||||
|
||||
if( *pp_pes == NULL )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( (!p_riff->i_size) || (!i_size_index ) )
|
||||
{
|
||||
i_size = __MAX( i_size_index, p_riff->i_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
i_size = __MIN( p_riff->i_size, i_size_index );
|
||||
}
|
||||
|
||||
if( !p_riff->i_size )
|
||||
{
|
||||
p_data = input_NewPacket( p_input->p_method_data, 0 );
|
||||
(*pp_pes)->p_first = p_data;
|
||||
(*pp_pes)->p_last = p_data;
|
||||
(*pp_pes)->i_nb_data = 1;
|
||||
(*pp_pes)->i_pes_size = 0;
|
||||
return( 0 );
|
||||
}
|
||||
if( i_size&1 )
|
||||
{
|
||||
i_size++;
|
||||
b_pad = 1;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
i_read = input_SplitBuffer(p_input, &p_data, i_size -
|
||||
(*pp_pes)->i_pes_size );
|
||||
if( i_read < 0 )
|
||||
{
|
||||
/* FIXME free on all packets */
|
||||
return( -1 );
|
||||
}
|
||||
if( (*pp_pes)->p_first == NULL )
|
||||
{
|
||||
(*pp_pes)->p_first = p_data;
|
||||
(*pp_pes)->p_last = p_data;
|
||||
(*pp_pes)->i_nb_data = 1;
|
||||
(*pp_pes)->i_pes_size = ( p_data->p_payload_end -
|
||||
p_data->p_payload_start );
|
||||
}
|
||||
else
|
||||
{
|
||||
(*pp_pes)->p_last->p_next = p_data;
|
||||
(*pp_pes)->p_last = p_data;
|
||||
(*pp_pes)->i_nb_data++;
|
||||
(*pp_pes)->i_pes_size += ( p_data->p_payload_end -
|
||||
p_data->p_payload_start );
|
||||
}
|
||||
} while( ((*pp_pes)->i_pes_size < i_size)&&(i_read != 0) );
|
||||
|
||||
if( b_pad )
|
||||
{
|
||||
(*pp_pes)->i_pes_size--;
|
||||
(*pp_pes)->p_last->p_payload_end--;
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int RIFF_GoToChunk(input_thread_t * p_input, riffchunk_t *p_riff)
|
||||
{
|
||||
if( p_input->stream.b_seekable )
|
||||
{
|
||||
p_input->pf_seek( p_input, (off_t)p_riff->i_pos );
|
||||
input_AccessReinit( p_input );
|
||||
return( 0 );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
int RIFF_TestFileHeader( input_thread_t * p_input, riffchunk_t ** pp_riff, u32 i_type )
|
||||
{
|
||||
if( !( *pp_riff = RIFF_ReadChunk( p_input ) ) )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
if( (*pp_riff)->i_id != VLC_FOURCC('R','I','F','F')
|
||||
|| (*pp_riff)->i_type != i_type )
|
||||
{
|
||||
free( *pp_riff );
|
||||
return( -1 );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
int RIFF_FindAndLoadChunk( input_thread_t * p_input, riffchunk_t *p_riff, riffchunk_t **pp_fmt, u32 i_type )
|
||||
{
|
||||
*pp_fmt = NULL;
|
||||
if ( RIFF_FindChunk( p_input, i_type, p_riff ) != 0)
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
if ( ( (*pp_fmt = RIFF_ReadChunk( p_input )) == NULL)
|
||||
|| ( RIFF_LoadChunkData( p_input, *pp_fmt ) != 0 ) )
|
||||
{
|
||||
if( *pp_fmt != NULL )
|
||||
{
|
||||
RIFF_DeleteChunk( p_input, *pp_fmt );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int RIFF_FindAndGotoDataChunk( input_thread_t * p_input, riffchunk_t *p_riff, riffchunk_t **pp_data, u32 i_type )
|
||||
{
|
||||
*pp_data = NULL;
|
||||
if ( RIFF_FindChunk( p_input, i_type, p_riff ) != 0)
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
if ( ( *pp_data = RIFF_ReadChunk( p_input ) ) == NULL )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
if ( RIFF_GoToChunkData( p_input ) != 0 )
|
||||
{
|
||||
RIFF_DeleteChunk( p_input, *pp_data );
|
||||
return( -1 );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int RIFF_FindListChunk( input_thread_t *p_input, riffchunk_t **pp_riff, riffchunk_t *p_rifffather, u32 i_type )
|
||||
{
|
||||
int i_ok;
|
||||
|
||||
*pp_riff = NULL;
|
||||
i_ok = 0;
|
||||
while( i_ok == 0 )
|
||||
{
|
||||
if( *pp_riff != NULL )
|
||||
{
|
||||
free( *pp_riff );
|
||||
}
|
||||
if( RIFF_FindChunk( p_input,
|
||||
VLC_FOURCC('L','I','S','T'), p_rifffather ) != 0 )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
*pp_riff = RIFF_ReadChunk( p_input );
|
||||
|
||||
if( *pp_riff == NULL )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
if( (*pp_riff)->i_type != i_type )
|
||||
{
|
||||
if( RIFF_NextChunk( p_input, p_rifffather ) != 0 )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i_ok = 1;
|
||||
}
|
||||
}
|
||||
return( 0 );
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* libioRIFF.h : AVI file Stream input module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: libioRIFF.h,v 1.2 2002/06/30 15:07:57 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.
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct riffchunk_s
|
||||
{
|
||||
u32 i_id;
|
||||
u32 i_size;
|
||||
u32 i_type;
|
||||
u32 i_pos;
|
||||
data_packet_t *p_data;
|
||||
u64 i_8bytes; /* it's the first 8 bytes after header
|
||||
used for key frame generation */
|
||||
} riffchunk_t;
|
||||
|
||||
int __RIFF_TellPos( input_thread_t *p_input, u32 *pos );
|
||||
int __RIFF_SkipBytes(input_thread_t * p_input,int nb);
|
||||
void RIFF_DeleteChunk( input_thread_t *p_input, riffchunk_t *p_chunk );
|
||||
riffchunk_t *RIFF_ReadChunk(input_thread_t * p_input);
|
||||
int RIFF_NextChunk( input_thread_t * p_input,riffchunk_t *p_rifffather);
|
||||
int RIFF_DescendChunk(input_thread_t * p_input);
|
||||
int RIFF_AscendChunk(input_thread_t * p_input ,riffchunk_t *p_riff);
|
||||
int RIFF_FindChunk(input_thread_t * p_input,
|
||||
u32 i_id,riffchunk_t *p_rifffather);
|
||||
int RIFF_GoToChunkData(input_thread_t * p_input);
|
||||
int RIFF_LoadChunkData(input_thread_t * p_input,
|
||||
riffchunk_t *p_riff );
|
||||
int RIFF_LoadChunkDataInPES(input_thread_t * p_input,
|
||||
pes_packet_t **pp_pes,
|
||||
int i_size_index);
|
||||
|
||||
int RIFF_GoToChunk(input_thread_t * p_input,
|
||||
riffchunk_t *p_riff);
|
||||
int RIFF_TestFileHeader( input_thread_t * p_input,
|
||||
riffchunk_t ** pp_riff,
|
||||
u32 i_type );
|
||||
int RIFF_FindAndLoadChunk( input_thread_t * p_input,
|
||||
riffchunk_t *p_riff,
|
||||
riffchunk_t **pp_fmt,
|
||||
u32 i_type );
|
||||
int RIFF_FindAndGotoDataChunk( input_thread_t * p_input,
|
||||
riffchunk_t *p_riff,
|
||||
riffchunk_t **pp_data,
|
||||
u32 i_type );
|
||||
int RIFF_FindListChunk( input_thread_t *p_input,
|
||||
riffchunk_t **pp_riff,
|
||||
riffchunk_t *p_rifffather,
|
||||
u32 i_type );
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
File diff suppressed because it is too large
Load Diff
|
@ -1,105 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* DrawingTidbits.cpp
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: DrawingTidbits.cpp,v 1.2 2001/03/21 13:42:33 sam Exp $
|
||||
*
|
||||
* Authors: Tony Castley <tcastley@mail.powerup.com.au>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <Debug.h>
|
||||
#include <Screen.h>
|
||||
|
||||
#include "DrawingTidbits.h"
|
||||
|
||||
inline uchar
|
||||
ShiftComponent(uchar component, float percent)
|
||||
{
|
||||
// change the color by <percent>, make sure we aren't rounding
|
||||
// off significant bits
|
||||
if (percent >= 1)
|
||||
return (uchar)(component * (2 - percent));
|
||||
else
|
||||
return (uchar)(255 - percent * (255 - component));
|
||||
}
|
||||
|
||||
rgb_color
|
||||
ShiftColor(rgb_color color, float percent)
|
||||
{
|
||||
rgb_color result = {
|
||||
ShiftComponent(color.red, percent),
|
||||
ShiftComponent(color.green, percent),
|
||||
ShiftComponent(color.blue, percent),
|
||||
0
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
CompareColors(const rgb_color a, const rgb_color b)
|
||||
{
|
||||
return a.red == b.red
|
||||
&& a.green == b.green
|
||||
&& a.blue == b.blue
|
||||
&& a.alpha == b.alpha;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const rgb_color &a, const rgb_color &b)
|
||||
{
|
||||
return CompareColors(a, b);
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const rgb_color &a, const rgb_color &b)
|
||||
{
|
||||
return !CompareColors(a, b);
|
||||
}
|
||||
|
||||
void
|
||||
ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to)
|
||||
{
|
||||
ASSERT(bitmap->ColorSpace() == B_COLOR_8_BIT); // other color spaces not implemented yet
|
||||
|
||||
BScreen screen(B_MAIN_SCREEN_ID);
|
||||
uint32 fromIndex = screen.IndexForColor(from);
|
||||
uint32 toIndex = screen.IndexForColor(to);
|
||||
|
||||
uchar *bits = (uchar *)bitmap->Bits();
|
||||
int32 bitsLength = bitmap->BitsLength();
|
||||
for (int32 index = 0; index < bitsLength; index++)
|
||||
if (bits[index] == fromIndex)
|
||||
bits[index] = toIndex;
|
||||
}
|
||||
|
||||
void
|
||||
ReplaceTransparentColor(BBitmap *bitmap, rgb_color with)
|
||||
{
|
||||
ASSERT(bitmap->ColorSpace() == B_COLOR_8_BIT); // other color spaces not implemented yet
|
||||
|
||||
BScreen screen(B_MAIN_SCREEN_ID);
|
||||
uint32 withIndex = screen.IndexForColor(with);
|
||||
|
||||
uchar *bits = (uchar *)bitmap->Bits();
|
||||
int32 bitsLength = bitmap->BitsLength();
|
||||
for (int32 index = 0; index < bitsLength; index++)
|
||||
if (bits[index] == B_TRANSPARENT_8_BIT)
|
||||
bits[index] = withIndex;
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* DrawingTidbits.h
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: DrawingTidbits.h,v 1.2 2001/03/21 13:42:33 sam Exp $
|
||||
*
|
||||
* Authors: Tony Castley <tcastley@mail.powerup.com.au>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __DRAWING_TIBITS__
|
||||
#define __DRAWING_TIBITS__
|
||||
|
||||
#include <GraphicsDefs.h>
|
||||
|
||||
rgb_color ShiftColor(rgb_color , float );
|
||||
|
||||
bool operator==(const rgb_color &, const rgb_color &);
|
||||
bool operator!=(const rgb_color &, const rgb_color &);
|
||||
|
||||
inline rgb_color
|
||||
Color(int32 r, int32 g, int32 b, int32 alpha = 255)
|
||||
{
|
||||
rgb_color result;
|
||||
result.red = r;
|
||||
result.green = g;
|
||||
result.blue = b;
|
||||
result.alpha = alpha;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const rgb_color kWhite = { 255, 255, 255, 255};
|
||||
const rgb_color kBlack = { 0, 0, 0, 255};
|
||||
|
||||
const float kDarkness = 1.06;
|
||||
const float kDimLevel = 0.6;
|
||||
|
||||
void ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to);
|
||||
void ReplaceTransparentColor(BBitmap *bitmap, rgb_color with);
|
||||
|
||||
#endif
|
|
@ -1,591 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* InterfaceWindow.cpp: beos interface
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: InterfaceWindow.cpp,v 1.22 2002/07/23 13:16:51 tcastley Exp $
|
||||
*
|
||||
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
|
||||
* Samuel Hocevar <sam@zoy.org>
|
||||
* Tony Castley <tony@castley.net>
|
||||
* Richard Shepherd <richard@rshepherd.demon.co.uk>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/* System headers */
|
||||
#include <kernel/OS.h>
|
||||
#include <InterfaceKit.h>
|
||||
#include <AppKit.h>
|
||||
#include <StorageKit.h>
|
||||
#include <SupportKit.h>
|
||||
#include <malloc.h>
|
||||
#include <scsi.h>
|
||||
#include <scsiprobe_driver.h>
|
||||
#include <fs_info.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* VLC headers */
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/aout.h>
|
||||
#include <vlc/intf.h>
|
||||
|
||||
/* BeOS interface headers */
|
||||
#include "MsgVals.h"
|
||||
#include "MediaControlView.h"
|
||||
#include "PlayListWindow.h"
|
||||
#include "intf_vlc_wrapper.h"
|
||||
#include "InterfaceWindow.h"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* InterfaceWindow
|
||||
*****************************************************************************/
|
||||
|
||||
InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
|
||||
intf_thread_t *p_interface )
|
||||
: BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
|
||||
B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK
|
||||
| B_ASYNCHRONOUS_CONTROLS )
|
||||
{
|
||||
file_panel = NULL;
|
||||
playlist_window = NULL;
|
||||
p_intf = p_interface;
|
||||
p_vlc_wrapper = Intf_VLCWrapper::getVLCWrapper(p_intf);
|
||||
BRect controlRect(0,0,0,0);
|
||||
|
||||
playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
b_empty_playlist = (p_playlist->i_size < 0);
|
||||
b_mute = false;
|
||||
|
||||
/* set the title bar */
|
||||
SetName( "interface" );
|
||||
SetTitle(VOUT_TITLE);
|
||||
|
||||
/* set up the main menu */
|
||||
BMenuBar *menu_bar;
|
||||
menu_bar = new BMenuBar(controlRect, "main menu");
|
||||
AddChild( menu_bar );
|
||||
|
||||
BMenu *mFile;
|
||||
BMenu *mAudio;
|
||||
CDMenu *cd_menu;
|
||||
BMenu *mNavigation;
|
||||
|
||||
/* Add the file Menu */
|
||||
BMenuItem *mItem;
|
||||
menu_bar->AddItem( mFile = new BMenu( "File" ) );
|
||||
menu_bar->ResizeToPreferred();
|
||||
mFile->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
|
||||
new BMessage(OPEN_FILE), 'O') );
|
||||
|
||||
cd_menu = new CDMenu( "Open Disc" );
|
||||
mFile->AddItem( cd_menu );
|
||||
|
||||
mFile->AddSeparatorItem();
|
||||
mFile->AddItem( mItem = new BMenuItem( "Play List" B_UTF8_ELLIPSIS,
|
||||
new BMessage(OPEN_PLAYLIST), 'P') );
|
||||
|
||||
mFile->AddSeparatorItem();
|
||||
mFile->AddItem( mItem = new BMenuItem( "About" B_UTF8_ELLIPSIS,
|
||||
new BMessage(B_ABOUT_REQUESTED), 'A') );
|
||||
mItem->SetTarget( be_app );
|
||||
mFile->AddItem(mItem = new BMenuItem( "Quit",
|
||||
new BMessage(B_QUIT_REQUESTED), 'Q') );
|
||||
|
||||
/* Add the Audio menu */
|
||||
menu_bar->AddItem ( mAudio = new BMenu( "Audio" ) );
|
||||
menu_bar->ResizeToPreferred();
|
||||
mAudio->AddItem( new LanguageMenu( "Language", AUDIO_ES, p_intf ) );
|
||||
mAudio->AddItem( new LanguageMenu( "Subtitles", SPU_ES, p_intf ) );
|
||||
|
||||
/* Add the Navigation menu */
|
||||
menu_bar->AddItem( mNavigation = new BMenu( "Navigation" ) );
|
||||
menu_bar->ResizeToPreferred();
|
||||
mNavigation->AddItem( new BMenuItem( "Prev Title",
|
||||
new BMessage(PREV_TITLE)) );
|
||||
mNavigation->AddItem( new BMenuItem( "Next Title",
|
||||
new BMessage(NEXT_TITLE)) );
|
||||
mNavigation->AddItem( new BMenuItem( "Prev Chapter",
|
||||
new BMessage(PREV_CHAPTER)) );
|
||||
mNavigation->AddItem( new BMenuItem( "Next Chapter",
|
||||
new BMessage(NEXT_CHAPTER)) );
|
||||
|
||||
ResizeTo(260,50 + menu_bar->Bounds().IntegerHeight()+1);
|
||||
controlRect = Bounds();
|
||||
controlRect.top += menu_bar->Bounds().IntegerHeight() + 1;
|
||||
|
||||
p_mediaControl = new MediaControlView( controlRect );
|
||||
p_mediaControl->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) );
|
||||
b_empty_playlist = true;
|
||||
p_mediaControl->SetEnabled( !b_empty_playlist );
|
||||
|
||||
/* Show */
|
||||
AddChild( p_mediaControl );
|
||||
Show();
|
||||
|
||||
}
|
||||
|
||||
InterfaceWindow::~InterfaceWindow()
|
||||
{
|
||||
if (playlist_window) playlist_window->ReallyQuit();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* InterfaceWindow::MessageReceived
|
||||
*****************************************************************************/
|
||||
void InterfaceWindow::MessageReceived( BMessage * p_message )
|
||||
{
|
||||
int vol_val = p_mediaControl->GetVolume(); // remember the current volume
|
||||
int playback_status; // remember playback state
|
||||
int i_index;
|
||||
BAlert *alert;
|
||||
|
||||
Activate();
|
||||
playback_status = p_vlc_wrapper->inputGetStatus();
|
||||
|
||||
switch( p_message->what )
|
||||
{
|
||||
case B_ABOUT_REQUESTED:
|
||||
alert = new BAlert(VOUT_TITLE, "BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
|
||||
alert->Go();
|
||||
break;
|
||||
|
||||
case TOGGLE_ON_TOP:
|
||||
break;
|
||||
|
||||
case OPEN_FILE:
|
||||
if( file_panel )
|
||||
{
|
||||
file_panel->Show();
|
||||
break;
|
||||
}
|
||||
file_panel = new BFilePanel();
|
||||
file_panel->SetTarget( this );
|
||||
file_panel->Show();
|
||||
b_empty_playlist = false;
|
||||
p_mediaControl->SetEnabled( !b_empty_playlist );
|
||||
break;
|
||||
|
||||
case OPEN_PLAYLIST:
|
||||
{
|
||||
BRect rect(20,20,320,420);
|
||||
playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
|
||||
playlist_window = PlayListWindow::getPlayList(rect,
|
||||
"Playlist", p_playlist);
|
||||
playlist_window->Show();
|
||||
}
|
||||
break;
|
||||
case OPEN_DVD:
|
||||
{
|
||||
const char *psz_device;
|
||||
BString type("dvd");
|
||||
if( p_message->FindString("device", &psz_device) != B_ERROR )
|
||||
{
|
||||
BString device(psz_device);
|
||||
p_vlc_wrapper->openDisc(type, device, 0,0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STOP_PLAYBACK:
|
||||
// this currently stops playback not nicely
|
||||
//p_vlc_wrapper->volume_mute();
|
||||
//snooze( 400000 );
|
||||
p_vlc_wrapper->playlistStop();
|
||||
p_mediaControl->SetStatus(NOT_STARTED_S,DEFAULT_RATE);
|
||||
break;
|
||||
|
||||
case START_PLAYBACK:
|
||||
/* starts playing in normal mode */
|
||||
|
||||
case PAUSE_PLAYBACK:
|
||||
/* toggle between pause and play */
|
||||
if( p_intf->p_sys->p_input != NULL )
|
||||
{
|
||||
/* pause if currently playing */
|
||||
if ( playback_status == PLAYING_S )
|
||||
{
|
||||
//p_vlc_wrapper->volume_mute();
|
||||
//snooze( 400000 );
|
||||
p_vlc_wrapper->playlistPause();
|
||||
}
|
||||
else
|
||||
{
|
||||
//p_vlc_wrapper->volume_restore();
|
||||
p_vlc_wrapper->playlistPlay();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Play a new file */
|
||||
p_vlc_wrapper->playlistPlay();
|
||||
}
|
||||
break;
|
||||
|
||||
case FASTER_PLAY:
|
||||
/* cycle the fast playback modes */
|
||||
//p_vlc_wrapper->volume_mute();
|
||||
//snooze( 400000 );
|
||||
p_vlc_wrapper->playFaster();
|
||||
break;
|
||||
|
||||
case SLOWER_PLAY:
|
||||
/* cycle the slow playback modes */
|
||||
//p_vlc_wrapper->volume_mute();
|
||||
//snooze( 400000 );
|
||||
p_vlc_wrapper->playSlower();
|
||||
break;
|
||||
|
||||
case SEEK_PLAYBACK:
|
||||
/* handled by semaphores */
|
||||
break;
|
||||
|
||||
case VOLUME_CHG:
|
||||
/* adjust the volume */
|
||||
// vlc_mutex_lock( &p_intf->p_sys->p_input->lock );
|
||||
// for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
|
||||
// {
|
||||
// if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
|
||||
// {
|
||||
// p_aout_bank->pp_aout[i_index]->i_savedvolume = vol_val;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// p_aout_bank->pp_aout[i_index]->i_volume = vol_val;
|
||||
// }
|
||||
// }
|
||||
// vlc_mutex_unlock( &p_aout_bank->lock );
|
||||
break;
|
||||
|
||||
case VOLUME_MUTE:
|
||||
/* toggle muting */
|
||||
p_vlc_wrapper->toggleMute( );
|
||||
break;
|
||||
|
||||
case SELECT_AUDIO:
|
||||
{
|
||||
int32 i = p_message->FindInt32( "audio" );
|
||||
p_vlc_wrapper->toggleLanguage( i );
|
||||
}
|
||||
break;
|
||||
|
||||
case SELECT_SUBTITLE:
|
||||
{
|
||||
int32 i = p_message->FindInt32( "subtitle" );
|
||||
p_vlc_wrapper->toggleSubtitle( i );
|
||||
}
|
||||
break;
|
||||
case PREV_TITLE:
|
||||
{
|
||||
int i_id;
|
||||
i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id - 1;
|
||||
|
||||
/* Disallow area 0 since it is used for video_ts.vob */
|
||||
if( i_id > 0 )
|
||||
{
|
||||
p_vlc_wrapper->toggleTitle(i_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NEXT_TITLE:
|
||||
{
|
||||
int i_id;
|
||||
|
||||
i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id + 1;
|
||||
|
||||
if( i_id < p_intf->p_sys->p_input->stream.i_area_nb )
|
||||
{
|
||||
p_vlc_wrapper->toggleTitle(i_id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PREV_CHAPTER:
|
||||
{
|
||||
int i_id;
|
||||
|
||||
i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_part - 1;
|
||||
|
||||
if( i_id >= 0 )
|
||||
{
|
||||
p_vlc_wrapper->toggleChapter(i_id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NEXT_CHAPTER:
|
||||
{
|
||||
int i_id;
|
||||
|
||||
i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_part + 1;
|
||||
|
||||
if( i_id >= 0 )
|
||||
{
|
||||
p_vlc_wrapper->toggleChapter(i_id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case B_REFS_RECEIVED:
|
||||
case B_SIMPLE_DATA:
|
||||
{
|
||||
entry_ref ref;
|
||||
BList* files = new BList();
|
||||
|
||||
int i = 0;
|
||||
while( p_message->FindRef( "refs", i, &ref ) == B_OK )
|
||||
{
|
||||
BPath path( &ref );
|
||||
|
||||
files->AddItem(new BString((char*)path.Path()) );
|
||||
i++;
|
||||
}
|
||||
p_vlc_wrapper->openFiles(files);
|
||||
delete files;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BWindow::MessageReceived( p_message );
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* InterfaceWindow::updateInterface
|
||||
*****************************************************************************/
|
||||
void InterfaceWindow::updateInterface()
|
||||
{
|
||||
|
||||
if ( p_intf->p_sys->p_input != NULL )
|
||||
{
|
||||
if ( acquire_sem(p_mediaControl->fScrubSem) == B_OK )
|
||||
{
|
||||
p_vlc_wrapper->setTimeAsFloat(p_mediaControl->GetSeekTo());
|
||||
}
|
||||
else if( Lock() )
|
||||
{
|
||||
p_mediaControl->SetStatus(p_intf->p_sys->p_input->stream.control.i_status,
|
||||
p_intf->p_sys->p_input->stream.control.i_rate);
|
||||
p_mediaControl->SetProgress(p_intf->p_sys->p_input->stream.p_selected_area->i_tell,
|
||||
p_intf->p_sys->p_input->stream.p_selected_area->i_size);
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
|
||||
if ( b_empty_playlist != (p_playlist->i_size < 1) )
|
||||
{
|
||||
if (Lock())
|
||||
{
|
||||
b_empty_playlist = !b_empty_playlist;
|
||||
p_mediaControl->SetEnabled( !b_empty_playlist );
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* InterfaceWindow::QuitRequested
|
||||
*****************************************************************************/
|
||||
bool InterfaceWindow::QuitRequested()
|
||||
{
|
||||
p_intf->p_vlc->b_die = VLC_TRUE;
|
||||
|
||||
return( true );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* CDMenu::CDMenu
|
||||
*****************************************************************************/
|
||||
CDMenu::CDMenu(const char *name)
|
||||
: BMenu(name)
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* CDMenu::~CDMenu
|
||||
*****************************************************************************/
|
||||
CDMenu::~CDMenu()
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* CDMenu::AttachedToWindow
|
||||
*****************************************************************************/
|
||||
void CDMenu::AttachedToWindow(void)
|
||||
{
|
||||
while (RemoveItem((long int)0) != NULL); // remove all items
|
||||
GetCD("/dev/disk");
|
||||
BMenu::AttachedToWindow();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* CDMenu::GetCD
|
||||
*****************************************************************************/
|
||||
int CDMenu::GetCD( const char *directory )
|
||||
{
|
||||
BVolumeRoster *volRoster;
|
||||
BVolume *vol;
|
||||
BDirectory *dir;
|
||||
int status;
|
||||
int mounted;
|
||||
char name[B_FILE_NAME_LENGTH];
|
||||
fs_info info;
|
||||
dev_t dev;
|
||||
|
||||
volRoster = new BVolumeRoster();
|
||||
vol = new BVolume();
|
||||
dir = new BDirectory();
|
||||
status = volRoster->GetNextVolume(vol);
|
||||
status = vol->GetRootDirectory(dir);
|
||||
while (status == B_NO_ERROR)
|
||||
{
|
||||
mounted = vol->GetName(name);
|
||||
if ((mounted == B_OK) && /* Disk is currently Mounted */
|
||||
(vol->IsReadOnly()) ) /* Disk is read-only */
|
||||
{
|
||||
dev = vol->Device();
|
||||
fs_stat_dev(dev, &info);
|
||||
|
||||
device_geometry g;
|
||||
int i_dev;
|
||||
i_dev = open( info.device_name, O_RDONLY );
|
||||
|
||||
if( i_dev >= 0 )
|
||||
{
|
||||
if( ioctl(i_dev, B_GET_GEOMETRY, &g, sizeof(g)) >= 0 )
|
||||
{
|
||||
if( g.device_type == B_CD ) //ensure the drive is a CD-ROM
|
||||
{
|
||||
BMessage *msg;
|
||||
msg = new BMessage( OPEN_DVD );
|
||||
msg->AddString( "device", info.device_name );
|
||||
BMenuItem *menu_item;
|
||||
menu_item = new BMenuItem( name, msg );
|
||||
AddItem( menu_item );
|
||||
}
|
||||
close(i_dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
vol->Unset();
|
||||
status = volRoster->GetNextVolume(vol);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* LanguageMenu::LanguageMenu
|
||||
*****************************************************************************/
|
||||
LanguageMenu::LanguageMenu(const char *name, int menu_kind,
|
||||
intf_thread_t *p_interface)
|
||||
:BMenu(name)
|
||||
{
|
||||
kind = menu_kind;
|
||||
p_intf = p_interface;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* LanguageMenu::~LanguageMenu
|
||||
*****************************************************************************/
|
||||
LanguageMenu::~LanguageMenu()
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* LanguageMenu::AttachedToWindow
|
||||
*****************************************************************************/
|
||||
void LanguageMenu::AttachedToWindow(void)
|
||||
{
|
||||
while( RemoveItem((long int)0) != NULL )
|
||||
{
|
||||
; // remove all items
|
||||
}
|
||||
|
||||
SetRadioMode(true);
|
||||
GetChannels();
|
||||
BMenu::AttachedToWindow();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* LanguageMenu::GetChannels
|
||||
*****************************************************************************/
|
||||
int LanguageMenu::GetChannels()
|
||||
{
|
||||
char *psz_name;
|
||||
bool b_active;
|
||||
BMessage *msg;
|
||||
int i;
|
||||
es_descriptor_t *p_es = NULL;
|
||||
|
||||
/* Insert the null */
|
||||
if( kind == SPU_ES ) //audio
|
||||
{
|
||||
msg = new BMessage(SELECT_SUBTITLE);
|
||||
msg->AddInt32("subtitle", -1);
|
||||
BMenuItem *menu_item;
|
||||
menu_item = new BMenuItem("None", msg);
|
||||
AddItem(menu_item);
|
||||
menu_item->SetMarked(TRUE);
|
||||
|
||||
}
|
||||
|
||||
if( p_intf->p_sys->p_input == NULL )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
|
||||
for( i = 0; i < p_intf->p_sys->p_input->stream.i_selected_es_number; i++ )
|
||||
{
|
||||
if( kind == p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat )
|
||||
{
|
||||
p_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
|
||||
}
|
||||
}
|
||||
|
||||
for( i = 0; i < p_intf->p_sys->p_input->stream.i_es_number; i++ )
|
||||
{
|
||||
if( kind == p_intf->p_sys->p_input->stream.pp_es[i]->i_cat )
|
||||
{
|
||||
psz_name = p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc;
|
||||
if( kind == AUDIO_ES ) //audio
|
||||
{
|
||||
msg = new BMessage(SELECT_AUDIO);
|
||||
msg->AddInt32("audio", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = new BMessage(SELECT_SUBTITLE);
|
||||
msg->AddInt32("subtitle", i);
|
||||
}
|
||||
BMenuItem *menu_item;
|
||||
menu_item = new BMenuItem(psz_name, msg);
|
||||
AddItem(menu_item);
|
||||
b_active = (p_es == p_intf->p_sys->p_input->stream.pp_es[i]);
|
||||
menu_item->SetMarked(b_active);
|
||||
}
|
||||
}
|
||||
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* InterfaceWindow.h: BeOS interface window class prototype
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: InterfaceWindow.h,v 1.15 2002/07/23 12:42:17 tcastley Exp $
|
||||
*
|
||||
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
|
||||
* Tony Castley <tcastley@mail.powerup.com.au>
|
||||
* Richard Shepherd <richard@rshepherd.demon.co.uk>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*****************************************************************************
|
||||
* intf_sys_t: description and status of FB interface
|
||||
*****************************************************************************/
|
||||
class MediaControlView;
|
||||
class PlayListWindow;
|
||||
|
||||
class CDMenu : public BMenu
|
||||
{
|
||||
public:
|
||||
CDMenu(const char *name);
|
||||
~CDMenu();
|
||||
void AttachedToWindow(void);
|
||||
private:
|
||||
int GetCD(const char *directory);
|
||||
};
|
||||
|
||||
class LanguageMenu : public BMenu
|
||||
{
|
||||
public:
|
||||
LanguageMenu(const char *name, int menu_kind,
|
||||
intf_thread_t *p_interface);
|
||||
~LanguageMenu();
|
||||
void AttachedToWindow(void);
|
||||
private:
|
||||
intf_thread_t *p_intf;
|
||||
int kind;
|
||||
int GetChannels();
|
||||
};
|
||||
|
||||
class InterfaceWindow : public BWindow
|
||||
{
|
||||
public:
|
||||
InterfaceWindow( BRect frame, const char *name,
|
||||
intf_thread_t *p_interface );
|
||||
~InterfaceWindow();
|
||||
|
||||
// standard window member
|
||||
virtual bool QuitRequested();
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
void updateInterface();
|
||||
|
||||
MediaControlView *p_mediaControl;
|
||||
|
||||
private:
|
||||
intf_thread_t *p_intf;
|
||||
bool b_empty_playlist;
|
||||
bool b_mute;
|
||||
BFilePanel *file_panel;
|
||||
PlayListWindow* playlist_window;
|
||||
BMenuItem *miOnTop;
|
||||
Intf_VLCWrapper * p_vlc_wrapper;
|
||||
};
|
||||
|
|
@ -1 +0,0 @@
|
|||
beos_SOURCES = beos.cpp aout_beos.cpp vout_beos.cpp intf_beos.cpp InterfaceWindow.cpp DrawingTidbits.cpp TransportButton.cpp PlayListWindow.cpp MediaControlView.cpp intf_vlc_wrapper.cpp
|
|
@ -1,287 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* MediaControlView.cpp: beos interface
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: MediaControlView.cpp,v 1.8 2002/06/01 12:31:58 sam Exp $
|
||||
*
|
||||
* Authors: Tony Castley <tony@castley.net>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/* System headers */
|
||||
#include <InterfaceKit.h>
|
||||
#include <AppKit.h>
|
||||
#include <string.h>
|
||||
|
||||
/* VLC headers */
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/intf.h>
|
||||
|
||||
/* BeOS interface headers */
|
||||
#include "MsgVals.h"
|
||||
#include "Bitmaps.h"
|
||||
#include "TransportButton.h"
|
||||
#include "MediaControlView.h"
|
||||
|
||||
|
||||
MediaControlView::MediaControlView( BRect frame )
|
||||
: BBox( frame, NULL, B_FOLLOW_ALL, B_WILL_DRAW, B_PLAIN_BORDER )
|
||||
{
|
||||
float xStart = HORZ_SPACE;
|
||||
float yStart = VERT_SPACE;
|
||||
fScrubSem = B_ERROR;
|
||||
|
||||
BRect controlRect = BRect(xStart,yStart,
|
||||
frame.Width() - (HORZ_SPACE * 2), 15);
|
||||
|
||||
/* Seek Status */
|
||||
rgb_color fill_color = {0,255,0};
|
||||
p_seek = new SeekSlider(controlRect, this, 0, 100, B_TRIANGLE_THUMB);
|
||||
p_seek->SetValue(0);
|
||||
p_seek->UseFillColor(true, &fill_color);
|
||||
AddChild( p_seek );
|
||||
yStart += 15 + VERT_SPACE;
|
||||
|
||||
|
||||
/* Buttons */
|
||||
/* Slow play */
|
||||
controlRect.SetLeftTop(BPoint(xStart, yStart));
|
||||
controlRect.SetRightBottom(controlRect.LeftTop() + kSkipButtonSize);
|
||||
xStart += kRewindBitmapWidth;
|
||||
p_slow = new TransportButton(controlRect, B_EMPTY_STRING,
|
||||
kSkipBackBitmapBits,
|
||||
kPressedSkipBackBitmapBits,
|
||||
kDisabledSkipBackBitmapBits,
|
||||
new BMessage(SLOWER_PLAY));
|
||||
AddChild( p_slow );
|
||||
|
||||
/* Play Pause */
|
||||
controlRect.SetLeftTop(BPoint(xStart, yStart));
|
||||
controlRect.SetRightBottom(controlRect.LeftTop() + kPlayButtonSize);
|
||||
xStart += kPlayPauseBitmapWidth + 1.0;
|
||||
p_play = new PlayPauseButton(controlRect, B_EMPTY_STRING,
|
||||
kPlayButtonBitmapBits,
|
||||
kPressedPlayButtonBitmapBits,
|
||||
kDisabledPlayButtonBitmapBits,
|
||||
kPlayingPlayButtonBitmapBits,
|
||||
kPressedPlayingPlayButtonBitmapBits,
|
||||
kPausedPlayButtonBitmapBits,
|
||||
kPressedPausedPlayButtonBitmapBits,
|
||||
new BMessage(START_PLAYBACK));
|
||||
|
||||
AddChild( p_play );
|
||||
|
||||
/* Fast Foward */
|
||||
controlRect.SetLeftTop(BPoint(xStart, yStart));
|
||||
controlRect.SetRightBottom(controlRect.LeftTop() + kSkipButtonSize);
|
||||
xStart += kRewindBitmapWidth;
|
||||
p_fast = new TransportButton(controlRect, B_EMPTY_STRING,
|
||||
kSkipForwardBitmapBits,
|
||||
kPressedSkipForwardBitmapBits,
|
||||
kDisabledSkipForwardBitmapBits,
|
||||
new BMessage(FASTER_PLAY));
|
||||
AddChild( p_fast );
|
||||
|
||||
/* Stop */
|
||||
controlRect.SetLeftTop(BPoint(xStart, yStart));
|
||||
controlRect.SetRightBottom(controlRect.LeftTop() + kStopButtonSize);
|
||||
xStart += kStopBitmapWidth;
|
||||
p_stop = new TransportButton(controlRect, B_EMPTY_STRING,
|
||||
kStopButtonBitmapBits,
|
||||
kPressedStopButtonBitmapBits,
|
||||
kDisabledStopButtonBitmapBits,
|
||||
new BMessage(STOP_PLAYBACK));
|
||||
AddChild( p_stop );
|
||||
|
||||
controlRect.SetLeftTop(BPoint(xStart + 5, yStart + 6));
|
||||
controlRect.SetRightBottom(controlRect.LeftTop() + kSpeakerButtonSize);
|
||||
xStart += kSpeakerIconBitmapWidth;
|
||||
|
||||
p_mute = new TransportButton(controlRect, B_EMPTY_STRING,
|
||||
kSpeakerIconBits,
|
||||
kPressedSpeakerIconBits,
|
||||
kSpeakerIconBits,
|
||||
new BMessage(VOLUME_MUTE));
|
||||
|
||||
AddChild( p_mute );
|
||||
|
||||
/* Volume Slider */
|
||||
p_vol = new MediaSlider(BRect(xStart,20,255,30), new BMessage(VOLUME_CHG),
|
||||
0, VOLUME_MAX);
|
||||
p_vol->SetValue(VOLUME_DEFAULT);
|
||||
p_vol->UseFillColor(true, &fill_color);
|
||||
AddChild( p_vol );
|
||||
|
||||
}
|
||||
|
||||
MediaControlView::~MediaControlView()
|
||||
{
|
||||
}
|
||||
|
||||
void MediaControlView::MessageReceived(BMessage *message)
|
||||
{
|
||||
}
|
||||
|
||||
void MediaControlView::SetProgress(uint64 seek, uint64 size)
|
||||
{
|
||||
p_seek->SetPosition((float)seek/size);
|
||||
}
|
||||
|
||||
void MediaControlView::SetStatus(int status, int rate)
|
||||
{
|
||||
switch( status )
|
||||
{
|
||||
case PLAYING_S:
|
||||
case FORWARD_S:
|
||||
case BACKWARD_S:
|
||||
case START_S:
|
||||
p_play->SetPlaying();
|
||||
break;
|
||||
case PAUSE_S:
|
||||
p_play->SetPaused();
|
||||
break;
|
||||
case UNDEF_S:
|
||||
case NOT_STARTED_S:
|
||||
default:
|
||||
p_play->SetStopped();
|
||||
break;
|
||||
}
|
||||
if ( rate < DEFAULT_RATE )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void MediaControlView::SetEnabled(bool enabled)
|
||||
{
|
||||
p_slow->SetEnabled(enabled);
|
||||
p_play->SetEnabled(enabled);
|
||||
p_fast->SetEnabled(enabled);
|
||||
p_stop->SetEnabled(enabled);
|
||||
p_mute->SetEnabled(enabled);
|
||||
p_vol->SetEnabled(enabled);
|
||||
p_seek->SetEnabled(enabled);
|
||||
}
|
||||
|
||||
uint32 MediaControlView::GetSeekTo()
|
||||
{
|
||||
return p_seek->seekTo;
|
||||
}
|
||||
|
||||
uint32 MediaControlView::GetVolume()
|
||||
{
|
||||
return p_vol->Value();
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* MediaSlider
|
||||
*****************************************************************************/
|
||||
MediaSlider::MediaSlider( BRect frame, BMessage *p_message,
|
||||
int32 i_min, int32 i_max )
|
||||
:BSlider(frame, NULL, NULL, p_message, i_min, i_max )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MediaSlider::~MediaSlider()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MediaSlider::DrawThumb(void)
|
||||
{
|
||||
BRect r;
|
||||
BView *v;
|
||||
|
||||
rgb_color black = {0,0,0};
|
||||
r = ThumbFrame();
|
||||
v = OffscreenView();
|
||||
|
||||
if(IsEnabled())
|
||||
{
|
||||
v->SetHighColor(black);
|
||||
}
|
||||
else
|
||||
{
|
||||
v->SetHighColor(tint_color(black, B_LIGHTEN_2_TINT));
|
||||
}
|
||||
|
||||
r.InsetBy(r.IntegerWidth()/4, r.IntegerHeight()/(4 * r.IntegerWidth() / r.IntegerHeight()));
|
||||
v->StrokeEllipse(r);
|
||||
|
||||
if(IsEnabled())
|
||||
{
|
||||
v->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
}
|
||||
else
|
||||
{
|
||||
v->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT));
|
||||
}
|
||||
|
||||
r.InsetBy(1,1);
|
||||
v->FillEllipse(r);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* SeekSlider
|
||||
*****************************************************************************/
|
||||
SeekSlider::SeekSlider( BRect frame, MediaControlView *p_owner, int32 i_min,
|
||||
int32 i_max, thumb_style thumbType = B_TRIANGLE_THUMB )
|
||||
:MediaSlider( frame, NULL, i_min, i_max )
|
||||
{
|
||||
fOwner = p_owner;
|
||||
fMouseDown = false;
|
||||
}
|
||||
|
||||
SeekSlider::~SeekSlider()
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* SeekSlider::MouseDown
|
||||
*****************************************************************************/
|
||||
void SeekSlider::MouseDown(BPoint where)
|
||||
{
|
||||
BSlider::MouseDown(where);
|
||||
seekTo = ValueForPoint(where);
|
||||
fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
|
||||
release_sem(fOwner->fScrubSem);
|
||||
fMouseDown = true;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* SeekSlider::MouseUp
|
||||
*****************************************************************************/
|
||||
void SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage *message)
|
||||
{
|
||||
BSlider::MouseMoved(where, code, message);
|
||||
if (!fMouseDown)
|
||||
return;
|
||||
seekTo = ValueForPoint(where);
|
||||
release_sem(fOwner->fScrubSem);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* SeekSlider::MouseUp
|
||||
*****************************************************************************/
|
||||
void SeekSlider::MouseUp(BPoint where)
|
||||
{
|
||||
BSlider::MouseUp(where);
|
||||
seekTo = ValueForPoint(where);
|
||||
delete_sem(fOwner->fScrubSem);
|
||||
fOwner->fScrubSem = B_ERROR;
|
||||
fMouseDown = false;
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* MediaControlView.h: beos interface
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: MediaControlView.h,v 1.2 2001/09/12 01:31:37 tcastley Exp $
|
||||
*
|
||||
* Authors: Tony Castley <tony@castley.net>
|
||||
*
|
||||
* 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 HORZ_SPACE 5.0
|
||||
#define VERT_SPACE 5.0
|
||||
|
||||
|
||||
class TransportButton;
|
||||
class PlayPauseButton;
|
||||
class MediaSlider;
|
||||
class SeekSlider;
|
||||
|
||||
class MediaControlView : public BBox
|
||||
{
|
||||
public:
|
||||
MediaControlView( BRect frame );
|
||||
~MediaControlView();
|
||||
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
void SetProgress(uint64 seek, uint64 size);
|
||||
|
||||
void SetStatus(int status, int rate);
|
||||
void SetEnabled(bool);
|
||||
uint32 GetSeekTo();
|
||||
uint32 GetVolume();
|
||||
sem_id fScrubSem;
|
||||
bool fSeeking;
|
||||
|
||||
private:
|
||||
MediaSlider * p_vol;
|
||||
SeekSlider * p_seek;
|
||||
TransportButton* p_slow;
|
||||
PlayPauseButton* p_play;
|
||||
TransportButton* p_fast;
|
||||
TransportButton* p_stop;
|
||||
TransportButton* p_mute;
|
||||
|
||||
int current_rate;
|
||||
int current_status;
|
||||
};
|
||||
|
||||
class MediaSlider : public BSlider
|
||||
{
|
||||
public:
|
||||
MediaSlider(BRect frame,
|
||||
BMessage *message,
|
||||
int32 minValue,
|
||||
int32 maxValue);
|
||||
~MediaSlider();
|
||||
virtual void DrawThumb(void);
|
||||
};
|
||||
|
||||
|
||||
class SeekSlider : public MediaSlider
|
||||
{
|
||||
public:
|
||||
SeekSlider(BRect frame,
|
||||
MediaControlView *owner,
|
||||
int32 minValue,
|
||||
int32 maxValue,
|
||||
thumb_style thumbType = B_TRIANGLE_THUMB);
|
||||
|
||||
~SeekSlider();
|
||||
uint32 seekTo;
|
||||
virtual void MouseDown(BPoint);
|
||||
virtual void MouseUp(BPoint pt);
|
||||
virtual void MouseMoved(BPoint pt, uint32 c, const BMessage *m);
|
||||
private:
|
||||
MediaControlView* fOwner;
|
||||
bool fMouseDown;
|
||||
};
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* MsgVals.h
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: MsgVals.h,v 1.11 2002/07/23 12:42:17 tcastley Exp $
|
||||
*
|
||||
* Authors: Tony Castley <tcastley@mail.powerup.com.au>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/* MsgVals.h */
|
||||
#define PLAYING 0
|
||||
#define PAUSED 1
|
||||
|
||||
const uint32 OPEN_FILE = 'OPFL';
|
||||
const uint32 OPEN_DVD = 'OPDV';
|
||||
const uint32 OPEN_PLAYLIST = 'OPPL';
|
||||
const uint32 STOP_PLAYBACK = 'STPL';
|
||||
const uint32 START_PLAYBACK = 'PLAY';
|
||||
const uint32 PAUSE_PLAYBACK = 'PAPL';
|
||||
const uint32 FASTER_PLAY = 'FAPL';
|
||||
const uint32 SLOWER_PLAY = 'SLPL';
|
||||
const uint32 SEEK_PLAYBACK = 'SEEK';
|
||||
const uint32 VOLUME_CHG = 'VOCH';
|
||||
const uint32 VOLUME_MUTE = 'MUTE';
|
||||
const uint32 SELECT_AUDIO = 'AUDI';
|
||||
const uint32 SELECT_SUBTITLE = 'SUBT';
|
||||
const uint32 PREV_TITLE = 'PRTI';
|
||||
const uint32 NEXT_TITLE = 'NXTI';
|
||||
const uint32 PREV_CHAPTER = 'PRCH';
|
||||
const uint32 NEXT_CHAPTER = 'NXCH';
|
||||
const uint32 TOGGLE_ON_TOP = 'ONTP';
|
||||
const uint32 TOGGLE_FULL_SCREEN = 'TGFS';
|
||||
const uint32 RESIZE_100 = 'RSOR';
|
||||
const uint32 RESIZE_200 = 'RSDB';
|
||||
const uint32 ASPECT_CORRECT = 'ASCO';
|
||||
const uint32 VERT_SYNC = 'VSYN';
|
||||
const uint32 WINDOW_FEEL = 'WFEL';
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* PlayListWindow.cpp: beos interface
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: PlayListWindow.cpp,v 1.8 2002/08/01 12:36:26 tcastley Exp $
|
||||
*
|
||||
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
|
||||
* Samuel Hocevar <sam@zoy.org>
|
||||
* Tony Castley <tony@castley.net>
|
||||
* Richard Shepherd <richard@rshepherd.demon.co.uk>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/* System headers */
|
||||
#include <InterfaceKit.h>
|
||||
#include <StorageKit.h>
|
||||
#include <SupportKit.h>
|
||||
#include <string.h>
|
||||
|
||||
/* VLC headers */
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/intf.h>
|
||||
|
||||
/* BeOS interface headers */
|
||||
#include "intf_vlc_wrapper.h"
|
||||
#include "InterfaceWindow.h"
|
||||
#include "MsgVals.h"
|
||||
#include "PlayListWindow.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* PlayListWindow
|
||||
*****************************************************************************/
|
||||
PlayListWindow *PlayListWindow::getPlayList( BRect frame, const char *name,
|
||||
playlist_t *p_pl)
|
||||
{
|
||||
static PlayListWindow *one_playlist;
|
||||
if (one_playlist == NULL)
|
||||
{
|
||||
one_playlist = new PlayListWindow(frame, name, p_pl);
|
||||
}
|
||||
return one_playlist;
|
||||
}
|
||||
|
||||
PlayListWindow::PlayListWindow( BRect frame, const char *name,
|
||||
playlist_t *p_pl)
|
||||
: BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
|
||||
B_WILL_ACCEPT_FIRST_CLICK | B_ASYNCHRONOUS_CONTROLS )
|
||||
{
|
||||
SetName( "playlist" );
|
||||
SetTitle(name);
|
||||
p_playlist = p_pl;
|
||||
|
||||
/* set up the main menu */
|
||||
BMenuBar *menu_bar;
|
||||
menu_bar = new BMenuBar(BRect(0,0,0,0), "main menu");
|
||||
AddChild( menu_bar );
|
||||
|
||||
BMenu *mFile;
|
||||
/* Add the file Menu */
|
||||
BMenuItem *mItem;
|
||||
menu_bar->AddItem( mFile = new BMenu( "File" ) );
|
||||
menu_bar->ResizeToPreferred();
|
||||
mFile->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
|
||||
new BMessage(OPEN_FILE), 'O') );
|
||||
|
||||
CDMenu *cd_menu = new CDMenu( "Open Disc" );
|
||||
mFile->AddItem( cd_menu );
|
||||
|
||||
BRect rect = Bounds();
|
||||
rect.top += menu_bar->Bounds().IntegerHeight() + 1;
|
||||
BView *p_view = new BView(rect, NULL, B_FOLLOW_ALL_SIDES, B_WILL_DRAW);
|
||||
|
||||
p_listview = new BListView(rect, "PlayList",
|
||||
B_MULTIPLE_SELECTION_LIST);
|
||||
for (int i=0; i < p_playlist->i_size; i++)
|
||||
{
|
||||
p_listview->AddItem(new BStringItem(p_playlist->pp_items[i]->psz_name));
|
||||
}
|
||||
p_view->AddChild(new BScrollView("scroll_playlist", p_listview,
|
||||
B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true));
|
||||
|
||||
AddChild(p_view);
|
||||
}
|
||||
|
||||
PlayListWindow::~PlayListWindow()
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* PlayListWindow::MessageReceived
|
||||
*****************************************************************************/
|
||||
void PlayListWindow::MessageReceived( BMessage * p_message )
|
||||
{
|
||||
Activate();
|
||||
|
||||
switch( p_message->what )
|
||||
{
|
||||
case OPEN_FILE:
|
||||
if( file_panel )
|
||||
{
|
||||
file_panel->Show();
|
||||
break;
|
||||
}
|
||||
file_panel = new BFilePanel();
|
||||
file_panel->SetTarget( this );
|
||||
file_panel->Show();
|
||||
break;
|
||||
|
||||
case OPEN_DVD:
|
||||
{
|
||||
const char *psz_device;
|
||||
BString type("dvd");
|
||||
if( p_message->FindString("device", &psz_device) != B_ERROR )
|
||||
{
|
||||
BString device(psz_device);
|
||||
// p_vlc_wrapper->openDisc(type, device, 0,0);
|
||||
p_listview->AddItem(new BStringItem(psz_device));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case B_REFS_RECEIVED:
|
||||
case B_SIMPLE_DATA:
|
||||
{
|
||||
entry_ref ref;
|
||||
BList* files = new BList();
|
||||
|
||||
int i = 0;
|
||||
while( p_message->FindRef( "refs", i, &ref ) == B_OK )
|
||||
{
|
||||
BPath path( &ref );
|
||||
|
||||
files->AddItem(new BString((char*)path.Path()) );
|
||||
p_listview->AddItem(new BStringItem((char*)path.Path()));
|
||||
i++;
|
||||
}
|
||||
// p_vlc_wrapper->openFiles(files);
|
||||
delete files;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BWindow::MessageReceived( p_message );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool PlayListWindow::QuitRequested()
|
||||
{
|
||||
Hide();
|
||||
return false;
|
||||
}
|
||||
|
||||
void PlayListWindow::ReallyQuit()
|
||||
{
|
||||
Hide();
|
||||
Lock();
|
||||
Quit();
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* PlayListWindow.h: BeOS interface window class prototype
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: PlayListWindow.h,v 1.2 2002/06/01 08:54:48 tcastley Exp $
|
||||
*
|
||||
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
|
||||
* Tony Castley <tcastley@mail.powerup.com.au>
|
||||
* Richard Shepherd <richard@rshepherd.demon.co.uk>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
class CDMenu;
|
||||
class PlayListWindow : public BWindow
|
||||
{
|
||||
public:
|
||||
static PlayListWindow *getPlayList(BRect frame, const char *name,
|
||||
playlist_t *p_pl);
|
||||
~PlayListWindow();
|
||||
bool QuitRequested();
|
||||
void ReallyQuit();
|
||||
|
||||
// standard window member
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
|
||||
private:
|
||||
PlayListWindow( BRect frame, const char *name, playlist_t *p_pl);
|
||||
playlist_t *p_playlist;
|
||||
BListView *p_listview;
|
||||
BFilePanel *file_panel;
|
||||
};
|
||||
|
||||
|
|
@ -1,622 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* TransportButton.cpp
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: TransportButton.cpp,v 1.3 2001/03/21 13:42:33 sam Exp $
|
||||
*
|
||||
* Authors: Tony Castley <tcastley@mail.powerup.com.au>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <Debug.h>
|
||||
#include <MessageFilter.h>
|
||||
#include <Screen.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "TransportButton.h"
|
||||
#include "DrawingTidbits.h"
|
||||
|
||||
class BitmapStash {
|
||||
// Bitmap stash is a simple class to hold all the lazily-allocated
|
||||
// bitmaps that the TransportButton needs when rendering itself.
|
||||
// signature is a combination of the different enabled, pressed, playing, etc.
|
||||
// flavors of a bitmap. If the stash does not have a particular bitmap,
|
||||
// it turns around to ask the button to create one and stores it for next time.
|
||||
public:
|
||||
BitmapStash(TransportButton *);
|
||||
~BitmapStash();
|
||||
BBitmap *GetBitmap(uint32 signature);
|
||||
|
||||
private:
|
||||
TransportButton *owner;
|
||||
map<uint32, BBitmap *> stash;
|
||||
};
|
||||
|
||||
BitmapStash::BitmapStash(TransportButton *owner)
|
||||
: owner(owner)
|
||||
{
|
||||
}
|
||||
|
||||
BBitmap *
|
||||
BitmapStash::GetBitmap(uint32 signature)
|
||||
{
|
||||
if (stash.find(signature) == stash.end()) {
|
||||
BBitmap *newBits = owner->MakeBitmap(signature);
|
||||
ASSERT(newBits);
|
||||
stash[signature] = newBits;
|
||||
}
|
||||
|
||||
return stash[signature];
|
||||
}
|
||||
|
||||
BitmapStash::~BitmapStash()
|
||||
{
|
||||
// delete all the bitmaps
|
||||
for (map<uint32, BBitmap *>::iterator i = stash.begin(); i != stash.end(); i++)
|
||||
delete (*i).second;
|
||||
}
|
||||
|
||||
|
||||
class PeriodicMessageSender {
|
||||
// used to send a specified message repeatedly when holding down a button
|
||||
public:
|
||||
static PeriodicMessageSender *Launch(BMessenger target,
|
||||
const BMessage *message, bigtime_t period);
|
||||
void Quit();
|
||||
|
||||
private:
|
||||
PeriodicMessageSender(BMessenger target, const BMessage *message,
|
||||
bigtime_t period);
|
||||
~PeriodicMessageSender() {}
|
||||
// use quit
|
||||
|
||||
static status_t TrackBinder(void *);
|
||||
void Run();
|
||||
|
||||
BMessenger target;
|
||||
BMessage message;
|
||||
|
||||
bigtime_t period;
|
||||
|
||||
bool requestToQuit;
|
||||
};
|
||||
|
||||
|
||||
PeriodicMessageSender::PeriodicMessageSender(BMessenger target,
|
||||
const BMessage *message, bigtime_t period)
|
||||
: target(target),
|
||||
message(*message),
|
||||
period(period),
|
||||
requestToQuit(false)
|
||||
{
|
||||
}
|
||||
|
||||
PeriodicMessageSender *
|
||||
PeriodicMessageSender::Launch(BMessenger target, const BMessage *message,
|
||||
bigtime_t period)
|
||||
{
|
||||
PeriodicMessageSender *result = new PeriodicMessageSender(target, message, period);
|
||||
thread_id thread = spawn_thread(&PeriodicMessageSender::TrackBinder,
|
||||
"ButtonRepeatingThread", B_NORMAL_PRIORITY, result);
|
||||
|
||||
if (thread <= 0 || resume_thread(thread) != B_OK) {
|
||||
// didn't start, don't leak self
|
||||
delete result;
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
PeriodicMessageSender::Quit()
|
||||
{
|
||||
requestToQuit = true;
|
||||
}
|
||||
|
||||
status_t
|
||||
PeriodicMessageSender::TrackBinder(void *castToThis)
|
||||
{
|
||||
((PeriodicMessageSender *)castToThis)->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
PeriodicMessageSender::Run()
|
||||
{
|
||||
for (;;) {
|
||||
snooze(period);
|
||||
if (requestToQuit)
|
||||
break;
|
||||
target.SendMessage(&message);
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
|
||||
class SkipButtonKeypressFilter : public BMessageFilter {
|
||||
public:
|
||||
SkipButtonKeypressFilter(uint32 shortcutKey, uint32 shortcutModifier,
|
||||
TransportButton *target);
|
||||
|
||||
protected:
|
||||
filter_result Filter(BMessage *message, BHandler **handler);
|
||||
|
||||
private:
|
||||
uint32 shortcutKey;
|
||||
uint32 shortcutModifier;
|
||||
TransportButton *target;
|
||||
};
|
||||
|
||||
SkipButtonKeypressFilter::SkipButtonKeypressFilter(uint32 shortcutKey,
|
||||
uint32 shortcutModifier, TransportButton *target)
|
||||
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
|
||||
shortcutKey(shortcutKey),
|
||||
shortcutModifier(shortcutModifier),
|
||||
target(target)
|
||||
{
|
||||
}
|
||||
|
||||
filter_result
|
||||
SkipButtonKeypressFilter::Filter(BMessage *message, BHandler **handler)
|
||||
{
|
||||
if (target->IsEnabled()
|
||||
&& (message->what == B_KEY_DOWN || message->what == B_KEY_UP)) {
|
||||
uint32 modifiers;
|
||||
uint32 rawKeyChar = 0;
|
||||
uint8 byte = 0;
|
||||
int32 key = 0;
|
||||
|
||||
if (message->FindInt32("modifiers", (int32 *)&modifiers) != B_OK
|
||||
|| message->FindInt32("raw_char", (int32 *)&rawKeyChar) != B_OK
|
||||
|| message->FindInt8("byte", (int8 *)&byte) != B_OK
|
||||
|| message->FindInt32("key", &key) != B_OK)
|
||||
return B_DISPATCH_MESSAGE;
|
||||
|
||||
modifiers &= B_SHIFT_KEY | B_COMMAND_KEY | B_CONTROL_KEY
|
||||
| B_OPTION_KEY | B_MENU_KEY;
|
||||
// strip caps lock, etc.
|
||||
|
||||
if (modifiers == shortcutModifier && rawKeyChar == shortcutKey) {
|
||||
if (message->what == B_KEY_DOWN)
|
||||
target->ShortcutKeyDown();
|
||||
else
|
||||
target->ShortcutKeyUp();
|
||||
|
||||
return B_SKIP_MESSAGE;
|
||||
}
|
||||
}
|
||||
|
||||
// let others deal with this
|
||||
return B_DISPATCH_MESSAGE;
|
||||
}
|
||||
|
||||
TransportButton::TransportButton(BRect frame, const char *name,
|
||||
const unsigned char *normalBits,
|
||||
const unsigned char *pressedBits,
|
||||
const unsigned char *disabledBits,
|
||||
BMessage *invokeMessage, BMessage *startPressingMessage,
|
||||
BMessage *pressingMessage, BMessage *donePressingMessage, bigtime_t period,
|
||||
uint32 key, uint32 modifiers, uint32 resizeFlags)
|
||||
: BControl(frame, name, "", invokeMessage, resizeFlags, B_WILL_DRAW | B_NAVIGABLE),
|
||||
bitmaps(new BitmapStash(this)),
|
||||
normalBits(normalBits),
|
||||
pressedBits(pressedBits),
|
||||
disabledBits(disabledBits),
|
||||
startPressingMessage(startPressingMessage),
|
||||
pressingMessage(pressingMessage),
|
||||
donePressingMessage(donePressingMessage),
|
||||
pressingPeriod(period),
|
||||
mouseDown(false),
|
||||
keyDown(false),
|
||||
messageSender(0),
|
||||
keyPressFilter(0)
|
||||
{
|
||||
if (key)
|
||||
keyPressFilter = new SkipButtonKeypressFilter(key, modifiers, this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TransportButton::AttachedToWindow()
|
||||
{
|
||||
_inherited::AttachedToWindow();
|
||||
if (keyPressFilter)
|
||||
Window()->AddCommonFilter(keyPressFilter);
|
||||
|
||||
// transparent to reduce flicker
|
||||
SetViewColor(B_TRANSPARENT_COLOR);
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::DetachedFromWindow()
|
||||
{
|
||||
if (keyPressFilter) {
|
||||
Window()->RemoveCommonFilter(keyPressFilter);
|
||||
delete keyPressFilter;
|
||||
}
|
||||
_inherited::DetachedFromWindow();
|
||||
}
|
||||
|
||||
|
||||
TransportButton::~TransportButton()
|
||||
{
|
||||
delete startPressingMessage;
|
||||
delete pressingMessage;
|
||||
delete donePressingMessage;
|
||||
delete bitmaps;
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::WindowActivated(bool state)
|
||||
{
|
||||
if (!state)
|
||||
ShortcutKeyUp();
|
||||
|
||||
_inherited::WindowActivated(state);
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::SetEnabled(bool on)
|
||||
{
|
||||
_inherited::SetEnabled(on);
|
||||
if (!on)
|
||||
ShortcutKeyUp();
|
||||
}
|
||||
|
||||
const unsigned char *
|
||||
TransportButton::BitsForMask(uint32 mask) const
|
||||
{
|
||||
switch (mask) {
|
||||
case 0:
|
||||
return normalBits;
|
||||
case kDisabledMask:
|
||||
return disabledBits;
|
||||
case kPressedMask:
|
||||
return pressedBits;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
TRESPASS();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BBitmap *
|
||||
TransportButton::MakeBitmap(uint32 mask)
|
||||
{
|
||||
BBitmap *result = new BBitmap(Bounds(), B_COLOR_8_BIT);
|
||||
result->SetBits(BitsForMask(mask), (Bounds().Width() + 1) * (Bounds().Height() + 1),
|
||||
0, B_COLOR_8_BIT);
|
||||
|
||||
ReplaceTransparentColor(result, Parent()->ViewColor());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32
|
||||
TransportButton::ModeMask() const
|
||||
{
|
||||
return (IsEnabled() ? 0 : kDisabledMask)
|
||||
| (Value() ? kPressedMask : 0);
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::Draw(BRect)
|
||||
{
|
||||
DrawBitmapAsync(bitmaps->GetBitmap(ModeMask()));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TransportButton::StartPressing()
|
||||
{
|
||||
SetValue(1);
|
||||
if (startPressingMessage)
|
||||
Invoke(startPressingMessage);
|
||||
|
||||
if (pressingMessage) {
|
||||
ASSERT(pressingMessage);
|
||||
messageSender = PeriodicMessageSender::Launch(Messenger(),
|
||||
pressingMessage, pressingPeriod);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::MouseCancelPressing()
|
||||
{
|
||||
if (!mouseDown || keyDown)
|
||||
return;
|
||||
|
||||
mouseDown = false;
|
||||
|
||||
if (pressingMessage) {
|
||||
ASSERT(messageSender);
|
||||
PeriodicMessageSender *sender = messageSender;
|
||||
messageSender = 0;
|
||||
sender->Quit();
|
||||
}
|
||||
|
||||
if (donePressingMessage)
|
||||
Invoke(donePressingMessage);
|
||||
SetValue(0);
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::DonePressing()
|
||||
{
|
||||
if (pressingMessage) {
|
||||
ASSERT(messageSender);
|
||||
PeriodicMessageSender *sender = messageSender;
|
||||
messageSender = 0;
|
||||
sender->Quit();
|
||||
}
|
||||
|
||||
Invoke();
|
||||
SetValue(0);
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::MouseStartPressing()
|
||||
{
|
||||
if (mouseDown)
|
||||
return;
|
||||
|
||||
mouseDown = true;
|
||||
if (!keyDown)
|
||||
StartPressing();
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::MouseDonePressing()
|
||||
{
|
||||
if (!mouseDown)
|
||||
return;
|
||||
|
||||
mouseDown = false;
|
||||
if (!keyDown)
|
||||
DonePressing();
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::ShortcutKeyDown()
|
||||
{
|
||||
if (!IsEnabled())
|
||||
return;
|
||||
|
||||
if (keyDown)
|
||||
return;
|
||||
|
||||
keyDown = true;
|
||||
if (!mouseDown)
|
||||
StartPressing();
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::ShortcutKeyUp()
|
||||
{
|
||||
if (!keyDown)
|
||||
return;
|
||||
|
||||
keyDown = false;
|
||||
if (!mouseDown)
|
||||
DonePressing();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TransportButton::MouseDown(BPoint)
|
||||
{
|
||||
if (!IsEnabled())
|
||||
return;
|
||||
|
||||
ASSERT(Window()->Flags() & B_ASYNCHRONOUS_CONTROLS);
|
||||
SetTracking(true);
|
||||
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
|
||||
MouseStartPressing();
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::MouseMoved(BPoint point, uint32 code, const BMessage *)
|
||||
{
|
||||
if (IsTracking() && Bounds().Contains(point) != Value()) {
|
||||
if (!Value())
|
||||
MouseStartPressing();
|
||||
else
|
||||
MouseCancelPressing();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::MouseUp(BPoint point)
|
||||
{
|
||||
if (IsTracking()) {
|
||||
if (Bounds().Contains(point))
|
||||
MouseDonePressing();
|
||||
else
|
||||
MouseCancelPressing();
|
||||
SetTracking(false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::SetStartPressingMessage(BMessage *message)
|
||||
{
|
||||
delete startPressingMessage;
|
||||
startPressingMessage = message;
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::SetPressingMessage(BMessage *message)
|
||||
{
|
||||
delete pressingMessage;
|
||||
pressingMessage = message;
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::SetDonePressingMessage(BMessage *message)
|
||||
{
|
||||
delete donePressingMessage;
|
||||
donePressingMessage = message;
|
||||
}
|
||||
|
||||
void
|
||||
TransportButton::SetPressingPeriod(bigtime_t newTime)
|
||||
{
|
||||
pressingPeriod = newTime;
|
||||
}
|
||||
|
||||
|
||||
PlayPauseButton::PlayPauseButton(BRect frame, const char *name,
|
||||
const unsigned char *normalBits, const unsigned char *pressedBits,
|
||||
const unsigned char *disabledBits, const unsigned char *normalPlayingBits,
|
||||
const unsigned char *pressedPlayingBits, const unsigned char *normalPausedBits,
|
||||
const unsigned char *pressedPausedBits,
|
||||
BMessage *invokeMessage, uint32 key, uint32 modifiers, uint32 resizeFlags)
|
||||
: TransportButton(frame, name, normalBits, pressedBits,
|
||||
disabledBits, invokeMessage, 0,
|
||||
0, 0, 0, key, modifiers, resizeFlags),
|
||||
normalPlayingBits(normalPlayingBits),
|
||||
pressedPlayingBits(pressedPlayingBits),
|
||||
normalPausedBits(normalPausedBits),
|
||||
pressedPausedBits(pressedPausedBits),
|
||||
state(PlayPauseButton::kStopped),
|
||||
lastPauseBlinkTime(0),
|
||||
lastModeMask(0)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PlayPauseButton::SetStopped()
|
||||
{
|
||||
if (state == kStopped || state == kAboutToPlay)
|
||||
return;
|
||||
|
||||
state = kStopped;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void
|
||||
PlayPauseButton::SetPlaying()
|
||||
{
|
||||
if (state == kPlaying || state == kAboutToPause)
|
||||
return;
|
||||
|
||||
state = kPlaying;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
const bigtime_t kPauseBlinkPeriod = 600000;
|
||||
|
||||
void
|
||||
PlayPauseButton::SetPaused()
|
||||
{
|
||||
if (state == kAboutToPlay)
|
||||
return;
|
||||
|
||||
// in paused state blink the LED on and off
|
||||
bigtime_t now = system_time();
|
||||
if (state == kPausedLedOn || state == kPausedLedOff) {
|
||||
if (now - lastPauseBlinkTime < kPauseBlinkPeriod)
|
||||
return;
|
||||
|
||||
if (state == kPausedLedOn)
|
||||
state = kPausedLedOff;
|
||||
else
|
||||
state = kPausedLedOn;
|
||||
} else
|
||||
state = kPausedLedOn;
|
||||
|
||||
lastPauseBlinkTime = now;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
uint32
|
||||
PlayPauseButton::ModeMask() const
|
||||
{
|
||||
if (!IsEnabled())
|
||||
return kDisabledMask;
|
||||
|
||||
uint32 result = 0;
|
||||
|
||||
if (Value())
|
||||
result = kPressedMask;
|
||||
|
||||
if (state == kPlaying || state == kAboutToPlay)
|
||||
result |= kPlayingMask;
|
||||
else if (state == kAboutToPause || state == kPausedLedOn)
|
||||
result |= kPausedMask;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const unsigned char *
|
||||
PlayPauseButton::BitsForMask(uint32 mask) const
|
||||
{
|
||||
switch (mask) {
|
||||
case kPlayingMask:
|
||||
return normalPlayingBits;
|
||||
case kPlayingMask | kPressedMask:
|
||||
return pressedPlayingBits;
|
||||
case kPausedMask:
|
||||
return normalPausedBits;
|
||||
case kPausedMask | kPressedMask:
|
||||
return pressedPausedBits;
|
||||
default:
|
||||
return _inherited::BitsForMask(mask);
|
||||
}
|
||||
TRESPASS();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayPauseButton::StartPressing()
|
||||
{
|
||||
if (state == kPlaying)
|
||||
state = kAboutToPause;
|
||||
else
|
||||
state = kAboutToPlay;
|
||||
|
||||
_inherited::StartPressing();
|
||||
}
|
||||
|
||||
void
|
||||
PlayPauseButton::MouseCancelPressing()
|
||||
{
|
||||
if (state == kAboutToPause)
|
||||
state = kPlaying;
|
||||
else
|
||||
state = kStopped;
|
||||
|
||||
_inherited::MouseCancelPressing();
|
||||
}
|
||||
|
||||
void
|
||||
PlayPauseButton::DonePressing()
|
||||
{
|
||||
if (state == kAboutToPause) {
|
||||
state = kPausedLedOn;
|
||||
lastPauseBlinkTime = system_time();
|
||||
} else if (state == kAboutToPlay)
|
||||
state = kPlaying;
|
||||
|
||||
_inherited::DonePressing();
|
||||
}
|
||||
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* TransportButton.h
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: TransportButton.h,v 1.3 2001/03/21 13:42:33 sam Exp $
|
||||
*
|
||||
* Authors: Tony Castley <tcastley@mail.powerup.com.au>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __MEDIA_BUTTON__
|
||||
#define __MEDIA_BUTTON__
|
||||
|
||||
#include <Control.h>
|
||||
|
||||
class BMessage;
|
||||
class BBitmap;
|
||||
class PeriodicMessageSender;
|
||||
class BitmapStash;
|
||||
|
||||
// TransportButton must be installed into a window with B_ASYNCHRONOUS_CONTROLS on
|
||||
// currently no button focus drawing
|
||||
|
||||
class TransportButton : public BControl {
|
||||
public:
|
||||
|
||||
TransportButton(BRect frame, const char *name,
|
||||
const unsigned char *normalBits,
|
||||
const unsigned char *pressedBits,
|
||||
const unsigned char *disabledBits,
|
||||
BMessage *invokeMessage, // done pressing over button
|
||||
BMessage *startPressingMessage = 0, // just clicked button
|
||||
BMessage *pressingMessage = 0, // periodical still pressing
|
||||
BMessage *donePressing = 0, // tracked out of button/didn't invoke
|
||||
bigtime_t period = 0, // pressing message period
|
||||
uint32 key = 0, // optional shortcut key
|
||||
uint32 modifiers = 0, // optional shortcut key modifier
|
||||
uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP);
|
||||
|
||||
virtual ~TransportButton();
|
||||
|
||||
void SetStartPressingMessage(BMessage *);
|
||||
void SetPressingMessage(BMessage *);
|
||||
void SetDonePressingMessage(BMessage *);
|
||||
void SetPressingPeriod(bigtime_t);
|
||||
|
||||
virtual void SetEnabled(bool);
|
||||
|
||||
protected:
|
||||
|
||||
enum {
|
||||
kDisabledMask = 0x1,
|
||||
kPressedMask = 0x2
|
||||
};
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
virtual void DetachedFromWindow();
|
||||
virtual void Draw(BRect);
|
||||
virtual void MouseDown(BPoint);
|
||||
virtual void MouseMoved(BPoint, uint32 code, const BMessage *);
|
||||
virtual void MouseUp(BPoint);
|
||||
virtual void WindowActivated(bool);
|
||||
|
||||
virtual BBitmap *MakeBitmap(uint32);
|
||||
// lazy bitmap builder
|
||||
|
||||
virtual uint32 ModeMask() const;
|
||||
// mode mask corresponding to the current button state
|
||||
// - determines which bitmap will be used
|
||||
virtual const unsigned char *BitsForMask(uint32) const;
|
||||
// pick the right bits based on a mode mask
|
||||
|
||||
// overriding class can add swapping between two pairs of bitmaps, etc.
|
||||
virtual void StartPressing();
|
||||
virtual void MouseCancelPressing();
|
||||
virtual void DonePressing();
|
||||
|
||||
private:
|
||||
void ShortcutKeyDown();
|
||||
void ShortcutKeyUp();
|
||||
|
||||
void MouseStartPressing();
|
||||
void MouseDonePressing();
|
||||
|
||||
BitmapStash *bitmaps;
|
||||
// using BitmapStash * here instead of a direct member so that the class can be private in
|
||||
// the .cpp file
|
||||
|
||||
// bitmap bits used to build bitmaps for the different states
|
||||
const unsigned char *normalBits;
|
||||
const unsigned char *pressedBits;
|
||||
const unsigned char *disabledBits;
|
||||
|
||||
BMessage *startPressingMessage;
|
||||
BMessage *pressingMessage;
|
||||
BMessage *donePressingMessage;
|
||||
bigtime_t pressingPeriod;
|
||||
|
||||
bool mouseDown;
|
||||
bool keyDown;
|
||||
PeriodicMessageSender *messageSender;
|
||||
BMessageFilter *keyPressFilter;
|
||||
|
||||
typedef BControl _inherited;
|
||||
|
||||
friend class SkipButtonKeypressFilter;
|
||||
friend class BitmapStash;
|
||||
};
|
||||
|
||||
class PlayPauseButton : public TransportButton {
|
||||
// Knows about playing and paused states, blinks
|
||||
// the pause LED during paused state
|
||||
public:
|
||||
PlayPauseButton(BRect frame, const char *name,
|
||||
const unsigned char *normalBits,
|
||||
const unsigned char *pressedBits,
|
||||
const unsigned char *disabledBits,
|
||||
const unsigned char *normalPlayingBits,
|
||||
const unsigned char *pressedPlayingBits,
|
||||
const unsigned char *normalPausedBits,
|
||||
const unsigned char *pressedPausedBits,
|
||||
BMessage *invokeMessage, // done pressing over button
|
||||
uint32 key = 0, // optional shortcut key
|
||||
uint32 modifiers = 0, // optional shortcut key modifier
|
||||
uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP);
|
||||
|
||||
// These need get called periodically to update the button state
|
||||
// OK to call them over and over - once the state is correct, the call
|
||||
// is very low overhead
|
||||
void SetStopped();
|
||||
void SetPlaying();
|
||||
void SetPaused();
|
||||
|
||||
protected:
|
||||
|
||||
virtual uint32 ModeMask() const;
|
||||
virtual const unsigned char *BitsForMask(uint32) const;
|
||||
|
||||
virtual void StartPressing();
|
||||
virtual void MouseCancelPressing();
|
||||
virtual void DonePressing();
|
||||
|
||||
private:
|
||||
const unsigned char *normalPlayingBits;
|
||||
const unsigned char *pressedPlayingBits;
|
||||
const unsigned char *normalPausedBits;
|
||||
const unsigned char *pressedPausedBits;
|
||||
|
||||
enum PlayState {
|
||||
kStopped,
|
||||
kAboutToPlay,
|
||||
kPlaying,
|
||||
kAboutToPause,
|
||||
kPausedLedOn,
|
||||
kPausedLedOff
|
||||
};
|
||||
|
||||
enum {
|
||||
kPlayingMask = 0x4,
|
||||
kPausedMask = 0x8
|
||||
};
|
||||
|
||||
PlayState state;
|
||||
bigtime_t lastPauseBlinkTime;
|
||||
uint32 lastModeMask;
|
||||
|
||||
typedef TransportButton _inherited;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,97 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* VideoWindow.h: BeOS video window class prototype
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: VideoWindow.h,v 1.23 2002/07/23 12:42:17 tcastley Exp $
|
||||
*
|
||||
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
|
||||
* Tony Castley <tcastley@mail.powerup.com.au>
|
||||
* Richard Shepherd <richard@rshepherd.demon.co.uk>
|
||||
*
|
||||
* 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 BITMAP 0
|
||||
#define OVERLAY 1
|
||||
#define OPENGL 2
|
||||
|
||||
typedef struct colorcombo
|
||||
{
|
||||
color_space colspace;
|
||||
const char *name;
|
||||
u32 chroma;
|
||||
int planes;
|
||||
int pixel_bytes;
|
||||
} colorcombo;
|
||||
|
||||
colorcombo colspace[]=
|
||||
{
|
||||
{B_YCbCr420, "B_YCbCr420", VLC_FOURCC('I','4','2','0'), 3, 2},
|
||||
{B_YUV422, "B_YUV422", VLC_FOURCC('Y','4','2','2'), 3, 2},
|
||||
{B_YCbCr422, "B_YCbCr422", VLC_FOURCC('Y','U','Y','2'), 3, 2},
|
||||
{B_RGB32, "B_RGB32", VLC_FOURCC('R','V','3','2'), 1, 4},
|
||||
{B_RGB16, "B_RGB16", VLC_FOURCC('R','V','1','6'), 1, 2}
|
||||
};
|
||||
|
||||
#define COLOR_COUNT 5
|
||||
#define DEFAULT_COL 4
|
||||
|
||||
|
||||
class VLCView : public BView
|
||||
{
|
||||
public:
|
||||
VLCView( BRect bounds);
|
||||
~VLCView();
|
||||
|
||||
void MouseDown(BPoint point);
|
||||
void Draw(BRect updateRect);
|
||||
};
|
||||
|
||||
|
||||
class VideoWindow : public BWindow
|
||||
{
|
||||
public:
|
||||
// standard constructor and destructor
|
||||
VideoWindow( int v_width, int v_height,
|
||||
BRect frame);
|
||||
~VideoWindow();
|
||||
|
||||
void Zoom(BPoint origin, float width, float height);
|
||||
void FrameResized(float width, float height);
|
||||
void FrameMoved(BPoint origin);
|
||||
void ScreenChanged(BRect frame, color_space mode);
|
||||
void drawBuffer(int bufferIndex);
|
||||
void WindowActivated(bool active);
|
||||
int SelectDrawingMode(int width, int height);
|
||||
void MessageReceived(BMessage *message);
|
||||
|
||||
// this is the hook controling direct screen connection
|
||||
int32 i_width; // incomming bitmap size
|
||||
int32 i_height;
|
||||
BRect winSize; // current window size
|
||||
bool is_zoomed, vsync;
|
||||
BBitmap *bitmap[3];
|
||||
VLCView *view;
|
||||
int i_buffer;
|
||||
bool teardownwindow;
|
||||
thread_id fDrawThreadID;
|
||||
int mode;
|
||||
int colspace_index;
|
||||
|
||||
private:
|
||||
vout_thread_t *p_vout;
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -1,201 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* aout_beos.cpp: BeOS audio output
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: aout_beos.cpp,v 1.26 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
|
||||
* Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
#include <kernel/OS.h>
|
||||
#include <View.h>
|
||||
#include <Application.h>
|
||||
#include <Message.h>
|
||||
#include <Locker.h>
|
||||
#include <media/MediaDefs.h>
|
||||
#include <game/PushGameSound.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/aout.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* aout_sys_t: BeOS audio output method descriptor
|
||||
*****************************************************************************
|
||||
* This structure is part of the audio output thread descriptor.
|
||||
* It describes some BeOS specific variables.
|
||||
*****************************************************************************/
|
||||
struct aout_sys_t
|
||||
{
|
||||
BPushGameSound * p_sound;
|
||||
gs_audio_format * p_format;
|
||||
void * p_buffer;
|
||||
int i_buffer_size;
|
||||
int i_buffer_pos;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes.
|
||||
*****************************************************************************/
|
||||
static int SetFormat ( aout_thread_t * );
|
||||
static int GetBufInfo ( aout_thread_t *, int );
|
||||
static void Play ( aout_thread_t *, byte_t *, int );
|
||||
|
||||
/*****************************************************************************
|
||||
* OpenAudio: opens a BPushGameSound
|
||||
*****************************************************************************/
|
||||
int E_(OpenAudio) ( vlc_object_t *p_this )
|
||||
{
|
||||
aout_thread_t * p_aout = (aout_thread_t *)p_this;
|
||||
|
||||
/* Allocate structure */
|
||||
p_aout->p_sys = (aout_sys_t*) malloc( sizeof( aout_sys_t ) );
|
||||
if( p_aout->p_sys == NULL )
|
||||
{
|
||||
msg_Err( p_aout, "out of memory" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* Allocate gs_audio_format */
|
||||
p_aout->p_sys->p_format = (gs_audio_format *) malloc( sizeof( gs_audio_format ) );
|
||||
if( p_aout->p_sys->p_format == NULL )
|
||||
{
|
||||
free( p_aout->p_sys );
|
||||
msg_Err( p_aout, "out of memory" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* Initialize some variables */
|
||||
p_aout->p_sys->p_format->frame_rate = 44100.0;
|
||||
p_aout->p_sys->p_format->channel_count = p_aout->i_channels;
|
||||
p_aout->p_sys->p_format->format = gs_audio_format::B_GS_S16;
|
||||
p_aout->p_sys->p_format->byte_order = B_MEDIA_LITTLE_ENDIAN;
|
||||
p_aout->p_sys->p_format->buffer_size = 4*8192;
|
||||
p_aout->p_sys->i_buffer_pos = 0;
|
||||
|
||||
p_aout->pf_setformat = SetFormat;
|
||||
p_aout->pf_getbufinfo = GetBufInfo;
|
||||
p_aout->pf_play = Play;
|
||||
|
||||
/* Allocate BPushGameSound */
|
||||
p_aout->p_sys->p_sound = new BPushGameSound( 8192,
|
||||
p_aout->p_sys->p_format,
|
||||
2, NULL );
|
||||
if( p_aout->p_sys->p_sound == NULL )
|
||||
{
|
||||
free( p_aout->p_sys->p_format );
|
||||
free( p_aout->p_sys );
|
||||
msg_Err( p_aout, "cannot allocate BPushGameSound" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( p_aout->p_sys->p_sound->InitCheck() != B_OK )
|
||||
{
|
||||
free( p_aout->p_sys->p_format );
|
||||
free( p_aout->p_sys );
|
||||
msg_Err( p_aout, "cannot initialize BPushGameSound" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
p_aout->p_sys->p_sound->StartPlaying( );
|
||||
|
||||
p_aout->p_sys->p_sound->LockForCyclic( &p_aout->p_sys->p_buffer,
|
||||
(size_t *)&p_aout->p_sys->i_buffer_size );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* SetFormat: sets the dsp output format
|
||||
*****************************************************************************/
|
||||
static int SetFormat( aout_thread_t *p_aout )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* GetBufInfo: buffer status query
|
||||
*****************************************************************************/
|
||||
static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
|
||||
{
|
||||
/* Each value is 4 bytes long (stereo signed 16 bits) */
|
||||
int i_hard_pos = 4 * p_aout->p_sys->p_sound->CurrentPosition();
|
||||
|
||||
i_hard_pos = p_aout->p_sys->i_buffer_pos - i_hard_pos;
|
||||
if( i_hard_pos < 0 )
|
||||
{
|
||||
i_hard_pos += p_aout->p_sys->i_buffer_size;
|
||||
}
|
||||
|
||||
return( i_hard_pos );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Play: plays a sound samples buffer
|
||||
*****************************************************************************
|
||||
* This function writes a buffer of i_length bytes in the dsp
|
||||
*****************************************************************************/
|
||||
static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
|
||||
{
|
||||
int i_newbuf_pos;
|
||||
|
||||
if( (i_newbuf_pos = p_aout->p_sys->i_buffer_pos + i_size)
|
||||
> p_aout->p_sys->i_buffer_size )
|
||||
{
|
||||
memcpy( (void *)((int)p_aout->p_sys->p_buffer
|
||||
+ p_aout->p_sys->i_buffer_pos),
|
||||
buffer,
|
||||
p_aout->p_sys->i_buffer_size - p_aout->p_sys->i_buffer_pos );
|
||||
|
||||
memcpy( (void *)((int)p_aout->p_sys->p_buffer),
|
||||
buffer + p_aout->p_sys->i_buffer_size - p_aout->p_sys->i_buffer_pos,
|
||||
i_size - ( p_aout->p_sys->i_buffer_size
|
||||
- p_aout->p_sys->i_buffer_pos ) );
|
||||
|
||||
p_aout->p_sys->i_buffer_pos = i_newbuf_pos - p_aout->p_sys->i_buffer_size;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( (void *)((int)p_aout->p_sys->p_buffer + p_aout->p_sys->i_buffer_pos),
|
||||
buffer, i_size );
|
||||
|
||||
p_aout->p_sys->i_buffer_pos = i_newbuf_pos;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* CloseAudio: closes the dsp audio device
|
||||
*****************************************************************************/
|
||||
void E_(CloseAudio) ( vlc_object_t *p_this )
|
||||
{
|
||||
aout_thread_t * p_aout = (aout_thread_t *)p_this;
|
||||
|
||||
p_aout->p_sys->p_sound->UnlockCyclic();
|
||||
p_aout->p_sys->p_sound->StopPlaying( );
|
||||
delete p_aout->p_sys->p_sound;
|
||||
free( p_aout->p_sys->p_format );
|
||||
free( p_aout->p_sys );
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* beos.cpp : BeOS plugin for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000, 2001 VideoLAN
|
||||
* $Id: beos.cpp,v 1.20 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
|
||||
* Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
#include <string.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* External prototypes
|
||||
*****************************************************************************/
|
||||
int E_(OpenIntf) ( vlc_object_t * );
|
||||
void E_(CloseIntf) ( vlc_object_t * );
|
||||
|
||||
int E_(OpenAudio) ( vlc_object_t * );
|
||||
void E_(CloseAudio) ( vlc_object_t * );
|
||||
|
||||
int E_(OpenVideo) ( vlc_object_t * );
|
||||
void E_(CloseVideo) ( vlc_object_t * );
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
set_description( _("BeOS standard API module") );
|
||||
add_submodule();
|
||||
set_capability( "interface", 100 );
|
||||
set_callbacks( E_(OpenIntf), E_(CloseIntf) );
|
||||
add_submodule();
|
||||
set_capability( "video output", 100 );
|
||||
set_callbacks( E_(OpenVideo), E_(CloseVideo) );
|
||||
add_submodule();
|
||||
set_capability( "audio output", 100 );
|
||||
set_callbacks( E_(OpenAudio), E_(CloseAudio) );
|
||||
vlc_module_end();
|
||||
|
|
@ -1,143 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* intf_beos.cpp: beos interface
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: intf_beos.cpp,v 1.44 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
|
||||
* Samuel Hocevar <sam@zoy.org>
|
||||
* Tony Castley <tony@castley.net>
|
||||
* Richard Shepherd <richard@rshepherd.demon.co.uk>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
#include <InterfaceKit.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/intf.h>
|
||||
|
||||
#include "intf_vlc_wrapper.h"
|
||||
#include "InterfaceWindow.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototype
|
||||
*****************************************************************************/
|
||||
static void Run ( intf_thread_t *p_intf );
|
||||
|
||||
/*****************************************************************************
|
||||
* OpenIntf: initialize interface
|
||||
*****************************************************************************/
|
||||
int E_(OpenIntf) ( vlc_object_t *p_this )
|
||||
{
|
||||
intf_thread_t *p_intf = (intf_thread_t*) p_this;
|
||||
BScreen *screen;
|
||||
screen = new BScreen();
|
||||
BRect rect = screen->Frame();
|
||||
rect.top = rect.bottom-100;
|
||||
rect.bottom -= 50;
|
||||
rect.left += 50;
|
||||
rect.right = rect.left + 350;
|
||||
delete screen;
|
||||
|
||||
/* Allocate instance and initialize some members */
|
||||
p_intf->p_sys = (intf_sys_t*) malloc( sizeof( intf_sys_t ) );
|
||||
if( p_intf->p_sys == NULL )
|
||||
{
|
||||
msg_Err( p_intf, "out of memory" );
|
||||
return( 1 );
|
||||
}
|
||||
// p_intf->p_sys->p_sub = msg_Subscribe( p_intf );
|
||||
p_intf->p_sys->p_input = NULL;
|
||||
|
||||
p_intf->pf_run = Run;
|
||||
|
||||
/* Create the interface window */
|
||||
p_intf->p_sys->p_window =
|
||||
new InterfaceWindow( rect,
|
||||
VOUT_TITLE " (BeOS interface)", p_intf );
|
||||
if( p_intf->p_sys->p_window == 0 )
|
||||
{
|
||||
free( p_intf->p_sys );
|
||||
msg_Err( p_intf, "cannot allocate InterfaceWindow" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* CloseIntf: destroy interface
|
||||
*****************************************************************************/
|
||||
void E_(CloseIntf) ( vlc_object_t *p_this )
|
||||
{
|
||||
intf_thread_t *p_intf = (intf_thread_t*) p_this;
|
||||
|
||||
if( p_intf->p_sys->p_input )
|
||||
{
|
||||
vlc_object_release( p_intf->p_sys->p_input );
|
||||
}
|
||||
|
||||
// msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );
|
||||
|
||||
/* Destroy the interface window */
|
||||
p_intf->p_sys->p_window->Lock();
|
||||
p_intf->p_sys->p_window->Quit();
|
||||
|
||||
/* Destroy structure */
|
||||
free( p_intf->p_sys );
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Run: event loop
|
||||
*****************************************************************************/
|
||||
static void Run( intf_thread_t *p_intf )
|
||||
{
|
||||
while( !p_intf->b_die )
|
||||
{
|
||||
/* Update the input */
|
||||
if( p_intf->p_sys->p_input != NULL )
|
||||
{
|
||||
if( p_intf->p_sys->p_input->b_dead )
|
||||
{
|
||||
vlc_object_release( p_intf->p_sys->p_input );
|
||||
p_intf->p_sys->p_input = NULL;
|
||||
}
|
||||
/* Manage the slider */
|
||||
p_intf->p_sys->p_window->updateInterface();
|
||||
}
|
||||
|
||||
if( p_intf->p_sys->p_input == NULL )
|
||||
{
|
||||
p_intf->p_sys->p_input =
|
||||
(input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
|
||||
FIND_ANYWHERE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Wait a bit */
|
||||
msleep( INTF_IDLE_SLEEP );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,459 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* intf_vlc_wrapper.h: BeOS plugin for vlc (derived from MacOS X port )
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: intf_vlc_wrapper.cpp,v 1.3 2002/07/23 13:16:51 tcastley Exp $
|
||||
*
|
||||
* Authors: Florian G. Pflug <fgp@phlo.org>
|
||||
* Jon Lech Johansen <jon-vl@nanocrew.net>
|
||||
* Tony Casltey <tony@castley.net>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/* VLC headers */
|
||||
#include <SupportKit.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/intf.h>
|
||||
|
||||
#include "intf_vlc_wrapper.h"
|
||||
|
||||
Intf_VLCWrapper *Intf_VLCWrapper::getVLCWrapper(intf_thread_t *p_if)
|
||||
{
|
||||
static Intf_VLCWrapper *one_wrapper;
|
||||
if (one_wrapper == NULL )
|
||||
{
|
||||
one_wrapper = new Intf_VLCWrapper(p_if);
|
||||
}
|
||||
return one_wrapper;
|
||||
}
|
||||
|
||||
Intf_VLCWrapper::Intf_VLCWrapper(intf_thread_t *p_if)
|
||||
{
|
||||
p_intf = p_if;
|
||||
}
|
||||
|
||||
Intf_VLCWrapper::~Intf_VLCWrapper()
|
||||
{
|
||||
}
|
||||
|
||||
//bool Intf_VLCWrapper::manage()
|
||||
//{
|
||||
//
|
||||
// p_intf->pf_manage( p_intf );
|
||||
//
|
||||
// if ( p_intf->b_die )
|
||||
// {
|
||||
// // exit the lot
|
||||
// return( 1 );
|
||||
// }
|
||||
/* Update the input */
|
||||
// if( p_intf->p_sys->p_input != NULL )
|
||||
// {
|
||||
// if( p_intf->p_sys->p_input->b_dead )
|
||||
// {
|
||||
// vlc_object_release( p_intf->p_sys->p_input );
|
||||
// p_intf->p_sys->p_input = NULL;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
|
||||
// FIND_ANYWHERE );
|
||||
|
||||
// if ( p_intf->p_sys->p_input != NULL )
|
||||
// {
|
||||
// vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
|
||||
// if( !p_intf->p_sys->p_input->b_die )
|
||||
// {
|
||||
// /* New input or stream map change */
|
||||
// if( p_intf->p_sys->p_input->stream.b_changed ||
|
||||
// p_intf->p_sys->i_part !=
|
||||
// p_intf->p_sys->p_input->stream.p_selected_area->i_part )
|
||||
// {
|
||||
// setupMenus();
|
||||
// p_intf->p_sys->b_disabled_menus = 0;
|
||||
// }
|
||||
// }
|
||||
// vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
|
||||
// }
|
||||
// else if ( !p_intf->p_sys->b_disabled_menus )
|
||||
// {
|
||||
// setupMenus();
|
||||
// p_intf->p_sys->b_disabled_menus = 1;
|
||||
// }
|
||||
// return( 0 );
|
||||
//}
|
||||
|
||||
void Intf_VLCWrapper::quit()
|
||||
{
|
||||
p_intf->b_die = 1;
|
||||
}
|
||||
|
||||
/* playlist control */
|
||||
|
||||
int Intf_VLCWrapper::inputGetStatus()
|
||||
{
|
||||
if( p_intf->p_sys->p_input != NULL )
|
||||
{
|
||||
return( p_intf->p_sys->p_input->stream.control.i_status );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( UNDEF_S );
|
||||
}
|
||||
}
|
||||
|
||||
bool Intf_VLCWrapper::playlistPlay()
|
||||
{
|
||||
playlist_t *p_playlist =
|
||||
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
|
||||
vlc_mutex_lock( &p_playlist->object_lock );
|
||||
if( p_playlist->i_size )
|
||||
{
|
||||
vlc_mutex_unlock( &p_playlist->object_lock );
|
||||
playlist_Play( p_playlist );
|
||||
vlc_object_release( p_playlist );
|
||||
}
|
||||
else
|
||||
{
|
||||
vlc_mutex_unlock( &p_playlist->object_lock );
|
||||
vlc_object_release( p_playlist );
|
||||
}
|
||||
|
||||
return( true );
|
||||
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::playlistPause()
|
||||
{
|
||||
toggleMute( );
|
||||
playlist_t *p_playlist =
|
||||
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
playlist_Pause( p_playlist );
|
||||
vlc_object_release( p_playlist );
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::playlistStop()
|
||||
{
|
||||
playlist_t *p_playlist =
|
||||
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
|
||||
playlist_Stop( p_playlist );
|
||||
vlc_object_release( p_playlist );
|
||||
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::playlistNext()
|
||||
{
|
||||
playlist_t *p_playlist =
|
||||
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
|
||||
playlist_Next( p_playlist );
|
||||
vlc_object_release( p_playlist );
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::playlistPrev()
|
||||
{
|
||||
playlist_t *p_playlist =
|
||||
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
|
||||
playlist_Prev( p_playlist );
|
||||
vlc_object_release( p_playlist );
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::playlistSkip(int i)
|
||||
{
|
||||
playlist_t *p_playlist =
|
||||
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
|
||||
playlist_Skip( p_playlist, i );
|
||||
vlc_object_release( p_playlist );
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::playlistGoto(int i)
|
||||
{
|
||||
playlist_t *p_playlist =
|
||||
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
|
||||
playlist_Goto( p_playlist, i );
|
||||
vlc_object_release( p_playlist );
|
||||
}
|
||||
|
||||
/* playback control */
|
||||
void Intf_VLCWrapper::playSlower()
|
||||
{
|
||||
if( p_intf->p_sys->p_input != NULL )
|
||||
{
|
||||
input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
|
||||
}
|
||||
if (p_intf->p_sys->p_input->stream.control.i_rate == DEFAULT_RATE)
|
||||
{
|
||||
toggleMute( );
|
||||
}
|
||||
else
|
||||
{
|
||||
toggleMute ( );
|
||||
}
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::playFaster()
|
||||
{
|
||||
if( p_intf->p_sys->p_input != NULL )
|
||||
{
|
||||
input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
|
||||
}
|
||||
if (p_intf->p_sys->p_input->stream.control.i_rate == DEFAULT_RATE)
|
||||
{
|
||||
toggleMute( );
|
||||
}
|
||||
else
|
||||
{
|
||||
toggleMute ( );
|
||||
}
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::toggleProgram(int i_program){}
|
||||
|
||||
void Intf_VLCWrapper::toggleTitle(int i_title)
|
||||
{
|
||||
if( p_intf->p_sys->p_input != NULL )
|
||||
{
|
||||
input_ChangeArea( p_intf->p_sys->p_input,
|
||||
p_intf->p_sys->p_input->stream.pp_areas[i_title] );
|
||||
|
||||
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
|
||||
//setupMenus();
|
||||
|
||||
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
|
||||
}
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::toggleChapter(int i_chapter)
|
||||
{
|
||||
if( p_intf->p_sys->p_input != NULL )
|
||||
{
|
||||
p_intf->p_sys->p_input->stream.p_selected_area->i_part = i_chapter;
|
||||
input_ChangeArea( p_intf->p_sys->p_input,
|
||||
p_intf->p_sys->p_input->stream.p_selected_area );
|
||||
|
||||
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
|
||||
// setupMenus();
|
||||
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
|
||||
}
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::toggleLanguage(int i_language)
|
||||
{
|
||||
|
||||
int32 i_old = -1;
|
||||
int i_cat = AUDIO_ES;
|
||||
|
||||
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
|
||||
for( int i = 0; i < p_intf->p_sys->p_input->stream.i_selected_es_number ; i++ )
|
||||
{
|
||||
if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == i_cat )
|
||||
{
|
||||
i_old = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
|
||||
|
||||
msg_Info( p_intf, "Old: %d, New: %d", i_old, i_language);
|
||||
if( i_language != -1 )
|
||||
{
|
||||
input_ToggleES( p_intf->p_sys->p_input,
|
||||
p_intf->p_sys->p_input->stream.pp_selected_es[i_language],
|
||||
VLC_TRUE );
|
||||
}
|
||||
|
||||
if( (i_old != -1) && (i_old != i_language) )
|
||||
{
|
||||
input_ToggleES( p_intf->p_sys->p_input,
|
||||
p_intf->p_sys->p_input->stream.pp_selected_es[i_old],
|
||||
VLC_FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::toggleSubtitle(int i_subtitle)
|
||||
{
|
||||
int32 i_old = -1;
|
||||
int i_cat = SPU_ES;
|
||||
|
||||
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
|
||||
for( int i = 0; i < p_intf->p_sys->p_input->stream.i_selected_es_number ; i++ )
|
||||
{
|
||||
if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == i_cat )
|
||||
{
|
||||
i_old = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
|
||||
|
||||
msg_Info( p_intf, "Old: %d, New: %d", i_old, i_subtitle);
|
||||
if( i_subtitle != -1 )
|
||||
{
|
||||
input_ToggleES( p_intf->p_sys->p_input,
|
||||
p_intf->p_sys->p_input->stream.pp_selected_es[i_subtitle],
|
||||
VLC_TRUE );
|
||||
}
|
||||
|
||||
if( (i_old != -1) && (i_old != i_subtitle) )
|
||||
{
|
||||
input_ToggleES( p_intf->p_sys->p_input,
|
||||
p_intf->p_sys->p_input->stream.pp_selected_es[i_old],
|
||||
VLC_FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Intf_VLCWrapper::channelNext()
|
||||
{
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::channelPrev()
|
||||
{
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::eject(){}
|
||||
|
||||
|
||||
|
||||
/* playback info */
|
||||
|
||||
BString* Intf_VLCWrapper::getTimeAsString()
|
||||
{
|
||||
static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
|
||||
|
||||
if( p_intf->p_sys->p_input == NULL )
|
||||
{
|
||||
return (new BString("00:00:00"));
|
||||
}
|
||||
|
||||
input_OffsetToTime( p_intf->p_sys->p_input,
|
||||
psz_currenttime,
|
||||
p_intf->p_sys->p_input->stream.p_selected_area->i_tell );
|
||||
|
||||
return(new BString(psz_currenttime));
|
||||
}
|
||||
|
||||
float Intf_VLCWrapper::getTimeAsFloat()
|
||||
{
|
||||
float f_time = 0.0;
|
||||
|
||||
if( p_intf->p_sys->p_input != NULL )
|
||||
{
|
||||
f_time = (float)p_intf->p_sys->p_input->stream.p_selected_area->i_tell /
|
||||
(float)p_intf->p_sys->p_input->stream.p_selected_area->i_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
f_time = 0.0;
|
||||
}
|
||||
return( f_time );
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::setTimeAsFloat(float f_position)
|
||||
{
|
||||
if( p_intf->p_sys->p_input != NULL )
|
||||
{
|
||||
input_Seek( p_intf->p_sys->p_input,
|
||||
(long long int)(p_intf->p_sys->p_input->stream.p_selected_area->i_size * f_position / 100),
|
||||
INPUT_SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
BList *Intf_VLCWrapper::playlistAsArray()
|
||||
{
|
||||
int i;
|
||||
playlist_t *p_playlist =
|
||||
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
|
||||
BList* p_list = new BList(p_playlist->i_size);
|
||||
|
||||
vlc_mutex_lock( &p_playlist->object_lock );
|
||||
|
||||
for( i = 0; i < p_playlist->i_size; i++ )
|
||||
{
|
||||
p_list->AddItem(new BString(p_playlist->pp_items[i]->psz_name));
|
||||
}
|
||||
|
||||
vlc_mutex_unlock( &p_playlist->object_lock );
|
||||
vlc_object_release( p_playlist );
|
||||
return( p_list );
|
||||
}
|
||||
|
||||
/* open file/disc/network */
|
||||
void Intf_VLCWrapper::openFiles(BList *o_files)
|
||||
{
|
||||
BString *o_file;
|
||||
playlist_t *p_playlist =
|
||||
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
|
||||
while( ( o_file = (BString *)o_files->LastItem() ) )
|
||||
{
|
||||
o_files->RemoveItem(o_files->CountItems() - 1);
|
||||
playlist_Add( p_playlist, o_file->String(),
|
||||
PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
|
||||
delete o_file;
|
||||
}
|
||||
|
||||
vlc_object_release( p_playlist );
|
||||
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::openDisc(BString o_type, BString o_device, int i_title, int i_chapter)
|
||||
{
|
||||
BString o_source("");
|
||||
o_source << o_type << ":" << o_device ;
|
||||
|
||||
playlist_t *p_playlist =
|
||||
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
|
||||
FIND_ANYWHERE );
|
||||
playlist_Add( p_playlist, o_source.String(),
|
||||
PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
|
||||
vlc_object_release( p_playlist );
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::openNet(BString o_addr, int i_port)
|
||||
{
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::openNetChannel(BString o_addr, int i_port)
|
||||
{
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::openNetHTTP(BString o_addr)
|
||||
{
|
||||
}
|
||||
|
||||
void Intf_VLCWrapper::toggleMute( )
|
||||
{
|
||||
input_ToggleMute( p_intf->p_sys->p_input );
|
||||
}
|
||||
|
||||
/* menus management */
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* intf_vlc_wrapper.h: BeOS plugin for vlc (derived from MacOS X port )
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: intf_vlc_wrapper.h,v 1.3 2002/07/23 13:16:51 tcastley Exp $
|
||||
*
|
||||
* Authors: Florian G. Pflug <fgp@phlo.org>
|
||||
* Jon Lech Johansen <jon-vl@nanocrew.net>
|
||||
* Tony Casltey <tony@castley.net>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
class InterfaceWindow;
|
||||
|
||||
/*****************************************************************************
|
||||
* intf_sys_t: description and status of FB interface
|
||||
*****************************************************************************/
|
||||
struct intf_sys_t
|
||||
{
|
||||
InterfaceWindow *p_window;
|
||||
char i_key;
|
||||
|
||||
/* The input thread */
|
||||
input_thread_t * p_input;
|
||||
|
||||
/* The messages window */
|
||||
// msg_subscription_t * p_sub;
|
||||
|
||||
/* DVD mode */
|
||||
vlc_bool_t b_disabled_menus;
|
||||
vlc_bool_t b_loop;
|
||||
vlc_bool_t b_mute;
|
||||
int i_part;
|
||||
int i_saved_volume;
|
||||
int i_channel;
|
||||
|
||||
};
|
||||
|
||||
/* Intf_VLCWrapper is a singleton class
|
||||
(only one instance at any time) */
|
||||
class Intf_VLCWrapper
|
||||
{
|
||||
public:
|
||||
static Intf_VLCWrapper *getVLCWrapper(intf_thread_t *p_if);
|
||||
~Intf_VLCWrapper();
|
||||
|
||||
// bool manage();
|
||||
void quit();
|
||||
int inputGetStatus();
|
||||
/* playlist control */
|
||||
bool playlistPlay();
|
||||
void playlistPause();
|
||||
void playlistStop();
|
||||
void playlistNext();
|
||||
void playlistPrev();
|
||||
void playlistSkip(int i);
|
||||
void playlistGoto(int i);
|
||||
/* Playback Modes
|
||||
PLAYLIST_REPEAT_CURRENT
|
||||
PLAYLIST_FORWARD
|
||||
PLAYLIST_BACKWARD
|
||||
PLAYLIST_FORWARD_LOOP
|
||||
PLAYLIST_BACKWARD_LOOP
|
||||
PLAYLIST_RANDOM
|
||||
PLAYLIST_REVERSE_RANDOM
|
||||
*/
|
||||
|
||||
/* Stream Control */
|
||||
void playSlower();
|
||||
void playFaster();
|
||||
|
||||
/* input control */
|
||||
int getStatus();
|
||||
void setStatus(int status);
|
||||
void inputSeek();
|
||||
void toggleProgram(int i_program);
|
||||
void toggleTitle(int i_title);
|
||||
void toggleChapter(int i_chapter);
|
||||
void toggleLanguage(int i_language);
|
||||
void toggleSubtitle(int i_subtitle);
|
||||
void channelNext();
|
||||
void channelPrev();
|
||||
void eject();
|
||||
|
||||
/* playback info */
|
||||
BString* getTimeAsString();
|
||||
float getTimeAsFloat();
|
||||
void setTimeAsFloat(float i_offset);
|
||||
BList* playlistAsArray();
|
||||
|
||||
/* open file/disc/network */
|
||||
void openFiles(BList *o_files);
|
||||
void openDisc(BString o_type, BString o_device, int i_title, int i_chapter);
|
||||
void openNet(BString o_addr, int i_port);
|
||||
void openNetChannel(BString o_addr, int i_port);
|
||||
void openNetHTTP(BString o_addr);
|
||||
|
||||
/* audio stuff */
|
||||
void toggleMute( );
|
||||
/* menus management */
|
||||
void setupMenus();
|
||||
|
||||
private:
|
||||
Intf_VLCWrapper( intf_thread_t *p_if );
|
||||
es_descriptor_t * p_audio_es;
|
||||
intf_thread_t *p_intf;
|
||||
|
||||
};
|
||||
|
|
@ -1,653 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* vout_beos.cpp: beos video output display method
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000, 2001 VideoLAN
|
||||
* $Id: vout_beos.cpp,v 1.65 2002/07/31 20:56:50 sam Exp $
|
||||
*
|
||||
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
|
||||
* Samuel Hocevar <sam@zoy.org>
|
||||
* Tony Castley <tcastley@mail.powerup.com.au>
|
||||
* Richard Shepherd <richard@rshepherd.demon.co.uk>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <stdlib.h> /* free() */
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* strerror() */
|
||||
#include <InterfaceKit.h>
|
||||
#include <DirectWindow.h>
|
||||
#include <Application.h>
|
||||
#include <Bitmap.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/intf.h>
|
||||
#include <vlc/vout.h>
|
||||
|
||||
#include "VideoWindow.h"
|
||||
#include "DrawingTidbits.h"
|
||||
#include "MsgVals.h"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* vout_sys_t: BeOS video output method descriptor
|
||||
*****************************************************************************
|
||||
* This structure is part of the video output thread descriptor.
|
||||
* It describes the BeOS specific properties of an output thread.
|
||||
*****************************************************************************/
|
||||
struct vout_sys_t
|
||||
{
|
||||
VideoWindow * p_window;
|
||||
|
||||
s32 i_width;
|
||||
s32 i_height;
|
||||
|
||||
u32 source_chroma;
|
||||
int i_index;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* beos_GetAppWindow : retrieve a BWindow pointer from the window name
|
||||
*****************************************************************************/
|
||||
BWindow *beos_GetAppWindow(char *name)
|
||||
{
|
||||
int32 index;
|
||||
BWindow *window;
|
||||
|
||||
for (index = 0 ; ; index++)
|
||||
{
|
||||
window = be_app->WindowAt(index);
|
||||
if (window == NULL)
|
||||
break;
|
||||
if (window->LockWithTimeout(20000) == B_OK)
|
||||
{
|
||||
if (strcmp(window->Name(), name) == 0)
|
||||
{
|
||||
window->Unlock();
|
||||
break;
|
||||
}
|
||||
window->Unlock();
|
||||
}
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* VideoWindow constructor and destructor
|
||||
*****************************************************************************/
|
||||
VideoWindow::VideoWindow( int v_width, int v_height,
|
||||
BRect frame )
|
||||
: BWindow( frame, NULL, B_TITLED_WINDOW,
|
||||
B_NOT_CLOSABLE | B_NOT_MINIMIZABLE )
|
||||
{
|
||||
BView *mainView = new BView( Bounds(), "mainView",
|
||||
B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE);
|
||||
AddChild(mainView);
|
||||
mainView->SetViewColor(kBlack);
|
||||
|
||||
/* create the view to do the display */
|
||||
view = new VLCView( Bounds() );
|
||||
mainView->AddChild(view);
|
||||
|
||||
/* set the VideoWindow variables */
|
||||
teardownwindow = false;
|
||||
is_zoomed = false;
|
||||
vsync = false;
|
||||
i_buffer = 0;
|
||||
|
||||
/* call ScreenChanged to set vsync correctly */
|
||||
BScreen *screen;
|
||||
display_mode disp_mode;
|
||||
float refresh;
|
||||
|
||||
screen = new BScreen(this);
|
||||
|
||||
screen-> GetMode(&disp_mode);
|
||||
refresh =
|
||||
(disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)*
|
||||
(disp_mode.timing.v_total));
|
||||
if (refresh < 61)
|
||||
{
|
||||
vsync = true;
|
||||
}
|
||||
delete screen;
|
||||
|
||||
mode = SelectDrawingMode(v_width, v_height);
|
||||
|
||||
// remember current settings
|
||||
i_width = v_width;
|
||||
i_height = v_height;
|
||||
FrameResized(v_width, v_height);
|
||||
|
||||
if (mode == OVERLAY)
|
||||
{
|
||||
overlay_restrictions r;
|
||||
|
||||
bitmap[1]->GetOverlayRestrictions(&r);
|
||||
SetSizeLimits((i_width * r.min_width_scale) + 1, i_width * r.max_width_scale,
|
||||
(i_height * r.min_height_scale) + 1, i_height * r.max_height_scale);
|
||||
}
|
||||
Show();
|
||||
}
|
||||
|
||||
VideoWindow::~VideoWindow()
|
||||
{
|
||||
teardownwindow = true;
|
||||
delete bitmap[0];
|
||||
delete bitmap[1];
|
||||
delete bitmap[2];
|
||||
}
|
||||
|
||||
void VideoWindow::MessageReceived( BMessage *p_message )
|
||||
{
|
||||
switch( p_message->what )
|
||||
{
|
||||
case TOGGLE_FULL_SCREEN:
|
||||
((BWindow *)this)->Zoom();
|
||||
break;
|
||||
case RESIZE_100:
|
||||
if (is_zoomed)
|
||||
{
|
||||
((BWindow *)this)->Zoom();
|
||||
}
|
||||
ResizeTo(i_width, i_height);
|
||||
break;
|
||||
case RESIZE_200:
|
||||
if (is_zoomed)
|
||||
{
|
||||
((BWindow *)this)->Zoom();
|
||||
}
|
||||
ResizeTo(i_width * 2, i_height * 2);
|
||||
break;
|
||||
case VERT_SYNC:
|
||||
vsync = !vsync;
|
||||
break;
|
||||
case WINDOW_FEEL:
|
||||
{
|
||||
int16 winFeel;
|
||||
if (p_message->FindInt16("WinFeel", &winFeel) == B_OK)
|
||||
{
|
||||
SetFeel((window_feel)winFeel);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BWindow::MessageReceived( p_message );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWindow::drawBuffer(int bufferIndex)
|
||||
{
|
||||
i_buffer = bufferIndex;
|
||||
|
||||
// sync to the screen if required
|
||||
if (vsync)
|
||||
{
|
||||
BScreen *screen;
|
||||
screen = new BScreen(this);
|
||||
screen-> WaitForRetrace(22000);
|
||||
delete screen;
|
||||
}
|
||||
if (LockLooper())
|
||||
{
|
||||
// switch the overlay bitmap
|
||||
if (mode == OVERLAY)
|
||||
{
|
||||
rgb_color key;
|
||||
view->SetViewOverlay(bitmap[i_buffer],
|
||||
bitmap[i_buffer]->Bounds() ,
|
||||
view->Bounds(),
|
||||
&key, B_FOLLOW_ALL,
|
||||
B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
|
||||
B_OVERLAY_TRANSFER_CHANNEL);
|
||||
view->SetViewColor(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
// switch the bitmap
|
||||
view-> DrawBitmap(bitmap[i_buffer], view->Bounds() );
|
||||
}
|
||||
UnlockLooper();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWindow::Zoom(BPoint origin, float width, float height )
|
||||
{
|
||||
if(is_zoomed)
|
||||
{
|
||||
is_zoomed = !is_zoomed;
|
||||
MoveTo(winSize.left, winSize.top);
|
||||
ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
|
||||
be_app->ShowCursor();
|
||||
}
|
||||
else
|
||||
{
|
||||
is_zoomed = !is_zoomed;
|
||||
BScreen *screen;
|
||||
screen = new BScreen(this);
|
||||
BRect rect = screen->Frame();
|
||||
delete screen;
|
||||
MoveTo(0,0);
|
||||
ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
|
||||
be_app->ObscureCursor();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWindow::FrameMoved(BPoint origin)
|
||||
{
|
||||
if (is_zoomed) return ;
|
||||
winSize = Frame();
|
||||
}
|
||||
|
||||
void VideoWindow::FrameResized( float width, float height )
|
||||
{
|
||||
float out_width, out_height;
|
||||
float out_left, out_top;
|
||||
float width_scale = width / i_width;
|
||||
float height_scale = height / i_height;
|
||||
|
||||
if (width_scale <= height_scale)
|
||||
{
|
||||
out_width = (i_width * width_scale);
|
||||
out_height = (i_height * width_scale);
|
||||
out_left = 0;
|
||||
out_top = (height - out_height) / 2;
|
||||
}
|
||||
else /* if the height is proportionally smaller */
|
||||
{
|
||||
out_width = (i_width * height_scale);
|
||||
out_height = (i_height * height_scale);
|
||||
out_top = 0;
|
||||
out_left = (width - out_width) /2;
|
||||
}
|
||||
view->MoveTo(out_left,out_top);
|
||||
view->ResizeTo(out_width, out_height);
|
||||
if (!is_zoomed)
|
||||
{
|
||||
winSize = Frame();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWindow::ScreenChanged(BRect frame, color_space mode)
|
||||
{
|
||||
BScreen *screen;
|
||||
float refresh;
|
||||
|
||||
screen = new BScreen(this);
|
||||
display_mode disp_mode;
|
||||
|
||||
screen-> GetMode(&disp_mode);
|
||||
refresh =
|
||||
(disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)*
|
||||
(disp_mode.timing.v_total));
|
||||
if (refresh < 61)
|
||||
{
|
||||
vsync = true;
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWindow::WindowActivated(bool active)
|
||||
{
|
||||
}
|
||||
|
||||
int VideoWindow::SelectDrawingMode(int width, int height)
|
||||
{
|
||||
int drawingMode = BITMAP;
|
||||
int noOverlay = 0;
|
||||
|
||||
// int noOverlay = !config_GetIntVariable( "overlay" );
|
||||
for (int i = 0; i < COLOR_COUNT; i++)
|
||||
{
|
||||
if (noOverlay) break;
|
||||
bitmap[0] = new BBitmap ( BRect( 0, 0, width, height ),
|
||||
B_BITMAP_WILL_OVERLAY,
|
||||
colspace[i].colspace);
|
||||
|
||||
if(bitmap[0] && bitmap[0]->InitCheck() == B_OK)
|
||||
{
|
||||
colspace_index = i;
|
||||
|
||||
bitmap[1] = new BBitmap( BRect( 0, 0, width, height ), B_BITMAP_WILL_OVERLAY,
|
||||
colspace[colspace_index].colspace);
|
||||
bitmap[2] = new BBitmap( BRect( 0, 0, width, height ), B_BITMAP_WILL_OVERLAY,
|
||||
colspace[colspace_index].colspace);
|
||||
if ( (bitmap[2] && bitmap[2]->InitCheck() == B_OK) )
|
||||
{
|
||||
drawingMode = OVERLAY;
|
||||
rgb_color key;
|
||||
view->SetViewOverlay(bitmap[0],
|
||||
bitmap[0]->Bounds() ,
|
||||
view->Bounds(),
|
||||
&key, B_FOLLOW_ALL,
|
||||
B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL);
|
||||
view->SetViewColor(key);
|
||||
SetTitle(VOUT_TITLE " (Overlay)");
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete bitmap[0];
|
||||
delete bitmap[1];
|
||||
delete bitmap[2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete bitmap[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (drawingMode == BITMAP)
|
||||
{
|
||||
// fallback to RGB16
|
||||
colspace_index = DEFAULT_COL;
|
||||
SetTitle(VOUT_TITLE " (Bitmap)");
|
||||
bitmap[0] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace);
|
||||
bitmap[1] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace);
|
||||
bitmap[2] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace);
|
||||
}
|
||||
return drawingMode;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* VLCView::VLCView
|
||||
*****************************************************************************/
|
||||
VLCView::VLCView(BRect bounds) : BView(bounds, "", B_FOLLOW_NONE,
|
||||
B_WILL_DRAW)
|
||||
|
||||
{
|
||||
SetViewColor(B_TRANSPARENT_32_BIT);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* VLCView::~VLCView
|
||||
*****************************************************************************/
|
||||
VLCView::~VLCView()
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* VLCVIew::MouseDown
|
||||
*****************************************************************************/
|
||||
void VLCView::MouseDown(BPoint point)
|
||||
{
|
||||
BMessage* msg = Window()->CurrentMessage();
|
||||
int32 clicks = msg->FindInt32("clicks");
|
||||
|
||||
VideoWindow *vWindow = (VideoWindow *)Window();
|
||||
uint32 mouseButtons;
|
||||
BPoint where;
|
||||
GetMouse(&where, &mouseButtons, true);
|
||||
|
||||
if ((mouseButtons & B_PRIMARY_MOUSE_BUTTON) && (clicks == 2))
|
||||
{
|
||||
Window()->Zoom();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mouseButtons & B_SECONDARY_MOUSE_BUTTON)
|
||||
{
|
||||
BPopUpMenu *menu = new BPopUpMenu("context menu");
|
||||
menu->SetRadioMode(false);
|
||||
// Toggle FullScreen
|
||||
BMenuItem *zoomItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULL_SCREEN));
|
||||
zoomItem->SetMarked(vWindow->is_zoomed);
|
||||
menu->AddItem(zoomItem);
|
||||
// Resize to 100%
|
||||
BMenuItem *origItem = new BMenuItem("100%", new BMessage(RESIZE_100));
|
||||
menu->AddItem(origItem);
|
||||
// Resize to 200%
|
||||
BMenuItem *doubleItem = new BMenuItem("200%", new BMessage(RESIZE_200));
|
||||
menu->AddItem(doubleItem);
|
||||
menu->AddSeparatorItem();
|
||||
// Toggle vSync
|
||||
BMenuItem *vsyncItem = new BMenuItem("Vertical Sync", new BMessage(VERT_SYNC));
|
||||
vsyncItem->SetMarked(vWindow->vsync);
|
||||
menu->AddItem(vsyncItem);
|
||||
menu->AddSeparatorItem();
|
||||
|
||||
// Windwo Feel Items
|
||||
BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
|
||||
winNormFeel->AddInt16("WinFeel", (int16)B_NORMAL_WINDOW_FEEL);
|
||||
BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
|
||||
normWindItem->SetMarked(vWindow->Feel() == B_NORMAL_WINDOW_FEEL);
|
||||
menu->AddItem(normWindItem);
|
||||
|
||||
BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
|
||||
winFloatFeel->AddInt16("WinFeel", (int16)B_MODAL_ALL_WINDOW_FEEL);
|
||||
BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
|
||||
onTopWindItem->SetMarked(vWindow->Feel() == B_MODAL_ALL_WINDOW_FEEL);
|
||||
menu->AddItem(onTopWindItem);
|
||||
|
||||
BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
|
||||
winAllFeel->AddInt16("WinFeel", (int16)B_FLOATING_ALL_WINDOW_FEEL);
|
||||
BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
|
||||
allSpacesWindItem->SetMarked(vWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
|
||||
menu->AddItem(allSpacesWindItem);
|
||||
|
||||
menu->SetTargetForItems(this);
|
||||
ConvertToScreen(&where);
|
||||
menu->Go(where, true, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* VLCVIew::Draw
|
||||
*****************************************************************************/
|
||||
void VLCView::Draw(BRect updateRect)
|
||||
{
|
||||
VideoWindow *win = (VideoWindow *) Window();
|
||||
if (win->mode == BITMAP)
|
||||
FillRect(updateRect);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int Init ( vout_thread_t * );
|
||||
static void End ( vout_thread_t * );
|
||||
static int Manage ( vout_thread_t * );
|
||||
static void Display ( vout_thread_t *, picture_t * );
|
||||
|
||||
static int BeosOpenDisplay ( vout_thread_t *p_vout );
|
||||
static void BeosCloseDisplay( vout_thread_t *p_vout );
|
||||
|
||||
/*****************************************************************************
|
||||
* OpenVideo: allocates BeOS video thread output method
|
||||
*****************************************************************************
|
||||
* This function allocates and initializes a BeOS vout method.
|
||||
*****************************************************************************/
|
||||
int E_(OpenVideo) ( vlc_object_t *p_this )
|
||||
{
|
||||
vout_thread_t * p_vout = (vout_thread_t *)p_this;
|
||||
|
||||
/* Allocate structure */
|
||||
p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
|
||||
if( p_vout->p_sys == NULL )
|
||||
{
|
||||
msg_Err( p_vout, "out of memory" );
|
||||
return( 1 );
|
||||
}
|
||||
p_vout->p_sys->i_width = p_vout->render.i_width;
|
||||
p_vout->p_sys->i_height = p_vout->render.i_height;
|
||||
p_vout->p_sys->source_chroma = p_vout->render.i_chroma;
|
||||
|
||||
p_vout->pf_init = Init;
|
||||
p_vout->pf_end = End;
|
||||
p_vout->pf_manage = NULL;
|
||||
p_vout->pf_render = NULL;
|
||||
p_vout->pf_display = Display;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Init: initialize BeOS video thread output method
|
||||
*****************************************************************************/
|
||||
int Init( vout_thread_t *p_vout )
|
||||
{
|
||||
int i_index;
|
||||
picture_t *p_pic;
|
||||
|
||||
I_OUTPUTPICTURES = 0;
|
||||
|
||||
/* Open and initialize device */
|
||||
if( BeosOpenDisplay( p_vout ) )
|
||||
{
|
||||
msg_Err(p_vout, "vout error: can't open display");
|
||||
return 0;
|
||||
}
|
||||
p_vout->output.i_width = p_vout->render.i_width;
|
||||
p_vout->output.i_height = p_vout->render.i_height;
|
||||
|
||||
/* Assume we have square pixels */
|
||||
p_vout->output.i_aspect = p_vout->p_sys->i_width
|
||||
* VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
|
||||
p_vout->output.i_chroma = colspace[p_vout->p_sys->p_window->colspace_index].chroma;
|
||||
p_vout->p_sys->i_index = 0;
|
||||
|
||||
p_vout->b_direct = 1;
|
||||
|
||||
p_vout->output.i_rmask = 0x00ff0000;
|
||||
p_vout->output.i_gmask = 0x0000ff00;
|
||||
p_vout->output.i_bmask = 0x000000ff;
|
||||
|
||||
for (int buffer_index = 0 ; buffer_index < 3; buffer_index++)
|
||||
{
|
||||
p_pic = NULL;
|
||||
/* Find an empty picture slot */
|
||||
for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
|
||||
{
|
||||
p_pic = NULL;
|
||||
if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
|
||||
{
|
||||
p_pic = p_vout->p_picture + i_index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( p_pic == NULL )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
p_pic->p->p_pixels = (u8*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
|
||||
p_pic->p->i_lines = p_vout->p_sys->i_height;
|
||||
|
||||
p_pic->p->i_pixel_pitch = colspace[p_vout->p_sys->p_window->colspace_index].pixel_bytes;
|
||||
p_pic->i_planes = colspace[p_vout->p_sys->p_window->colspace_index].planes;
|
||||
p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow();
|
||||
p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch * ( p_vout->p_sys->p_window->bitmap[buffer_index]->Bounds().IntegerWidth() + 1 );
|
||||
|
||||
p_pic->i_status = DESTROYED_PICTURE;
|
||||
p_pic->i_type = DIRECT_PICTURE;
|
||||
|
||||
PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
|
||||
|
||||
I_OUTPUTPICTURES++;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* End: terminate BeOS video thread output method
|
||||
*****************************************************************************/
|
||||
void End( vout_thread_t *p_vout )
|
||||
{
|
||||
BeosCloseDisplay( p_vout );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* CloseVideo: destroy BeOS video thread output method
|
||||
*****************************************************************************
|
||||
* Terminate an output method created by DummyCreateOutputMethod
|
||||
*****************************************************************************/
|
||||
void E_(CloseVideo) ( vlc_object_t *p_this )
|
||||
{
|
||||
vout_thread_t * p_vout = (vout_thread_t *)p_this;
|
||||
|
||||
free( p_vout->p_sys );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Display: displays previously rendered output
|
||||
*****************************************************************************
|
||||
* This function send the currently rendered image to BeOS image, waits until
|
||||
* it is displayed and switch the two rendering buffers, preparing next frame.
|
||||
*****************************************************************************/
|
||||
void Display( vout_thread_t *p_vout, picture_t *p_pic )
|
||||
{
|
||||
VideoWindow * p_win = p_vout->p_sys->p_window;
|
||||
|
||||
/* draw buffer if required */
|
||||
if (!p_win->teardownwindow)
|
||||
{
|
||||
p_win->drawBuffer(p_vout->p_sys->i_index);
|
||||
}
|
||||
/* change buffer */
|
||||
p_vout->p_sys->i_index = ++p_vout->p_sys->i_index % 3;
|
||||
p_pic->p->p_pixels = (u8*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
|
||||
}
|
||||
|
||||
/* following functions are local */
|
||||
|
||||
/*****************************************************************************
|
||||
* BeosOpenDisplay: open and initialize BeOS device
|
||||
*****************************************************************************/
|
||||
static int BeosOpenDisplay( vout_thread_t *p_vout )
|
||||
{
|
||||
|
||||
p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
|
||||
p_vout->p_sys->i_height - 1,
|
||||
BRect( 20, 50,
|
||||
20 + p_vout->i_window_width - 1,
|
||||
50 + p_vout->i_window_height - 1 ));
|
||||
|
||||
if( p_vout->p_sys->p_window == NULL )
|
||||
{
|
||||
msg_Err( p_vout, "cannot allocate VideoWindow" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* BeosDisplay: close and reset BeOS device
|
||||
*****************************************************************************
|
||||
* Returns all resources allocated by BeosOpenDisplay and restore the original
|
||||
* state of the device.
|
||||
*****************************************************************************/
|
||||
static void BeosCloseDisplay( vout_thread_t *p_vout )
|
||||
{
|
||||
VideoWindow * p_win = p_vout->p_sys->p_window;
|
||||
/* Destroy the video window */
|
||||
if( p_win != NULL && !p_win->teardownwindow)
|
||||
{
|
||||
p_win->Lock();
|
||||
p_win->teardownwindow = true;
|
||||
p_win->Hide();
|
||||
p_win->Quit();
|
||||
}
|
||||
p_win = NULL;
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1,8 +0,0 @@
|
|||
chroma_i420_rgb_SOURCES = i420_rgb.c i420_rgb8.c i420_rgb16.c
|
||||
chroma_i420_rgb_mmx_SOURCES = i420_rgb.c i420_rgb16.c
|
||||
chroma_i420_yuy2_SOURCES = i420_yuy2.c
|
||||
chroma_i420_yuy2_mmx_SOURCES = i420_yuy2.c
|
||||
chroma_i422_yuy2_SOURCES = i422_yuy2.c
|
||||
chroma_i422_yuy2_mmx_SOURCES = i422_yuy2.c
|
||||
chroma_i420_ymga_SOURCES = i420_ymga.c
|
||||
chroma_i420_ymga_mmx_SOURCES = i420_ymga.c
|
|
@ -1,419 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* i420_rgb.c : YUV to bitmap RGB conversion module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000, 2001 VideoLAN
|
||||
* $Id: i420_rgb.c,v 1.11 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <math.h> /* exp(), pow() */
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <string.h> /* strerror() */
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/vout.h>
|
||||
|
||||
#include "i420_rgb.h"
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
# include "i420_rgb_c.h"
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Local and extern prototypes.
|
||||
*****************************************************************************/
|
||||
static int Activate ( vlc_object_t * );
|
||||
static void Deactivate ( vlc_object_t * );
|
||||
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
static void SetGammaTable ( int *pi_table, double f_gamma );
|
||||
static void SetYUV ( vout_thread_t * );
|
||||
static void Set8bppPalette ( vout_thread_t *, u8 * );
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor.
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
set_description( _("I420,IYUV,YV12 to "
|
||||
"RGB,RV15,RV16,RV24,RV32 conversions") );
|
||||
set_capability( "chroma", 80 );
|
||||
#elif defined (MODULE_NAME_IS_chroma_i420_rgb_mmx)
|
||||
set_description( _( "MMX I420,IYUV,YV12 to "
|
||||
"RV15,RV16,RV24,RV32 conversions") );
|
||||
set_capability( "chroma", 100 );
|
||||
add_requirement( MMX );
|
||||
#endif
|
||||
set_callbacks( Activate, Deactivate );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* Activate: allocate a chroma function
|
||||
*****************************************************************************
|
||||
* This function allocates and initializes a chroma function
|
||||
*****************************************************************************/
|
||||
static int Activate( vlc_object_t *p_this )
|
||||
{
|
||||
vout_thread_t *p_vout = (vout_thread_t *)p_this;
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
size_t i_tables_size;
|
||||
#endif
|
||||
|
||||
if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch( p_vout->render.i_chroma )
|
||||
{
|
||||
case VLC_FOURCC('Y','V','1','2'):
|
||||
case VLC_FOURCC('I','4','2','0'):
|
||||
case VLC_FOURCC('I','Y','U','V'):
|
||||
switch( p_vout->output.i_chroma )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
case VLC_FOURCC('R','G','B','2'):
|
||||
p_vout->chroma.pf_convert = E_(I420_RGB8);
|
||||
break;
|
||||
#endif
|
||||
case VLC_FOURCC('R','V','1','5'):
|
||||
p_vout->chroma.pf_convert = E_(I420_RGB15);
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('R','V','1','6'):
|
||||
p_vout->chroma.pf_convert = E_(I420_RGB16);
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('R','V','2','4'):
|
||||
case VLC_FOURCC('R','V','3','2'):
|
||||
p_vout->chroma.pf_convert = E_(I420_RGB32);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
p_vout->chroma.p_sys = malloc( sizeof( chroma_sys_t ) );
|
||||
if( p_vout->chroma.p_sys == NULL )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch( p_vout->output.i_chroma )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
case VLC_FOURCC('R','G','B','2'):
|
||||
p_vout->chroma.p_sys->p_buffer = malloc( VOUT_MAX_WIDTH );
|
||||
break;
|
||||
#endif
|
||||
|
||||
case VLC_FOURCC('R','V','1','5'):
|
||||
case VLC_FOURCC('R','V','1','6'):
|
||||
p_vout->chroma.p_sys->p_buffer = malloc( VOUT_MAX_WIDTH * 2 );
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('R','V','2','4'):
|
||||
case VLC_FOURCC('R','V','3','2'):
|
||||
p_vout->chroma.p_sys->p_buffer = malloc( VOUT_MAX_WIDTH * 4 );
|
||||
break;
|
||||
|
||||
default:
|
||||
p_vout->chroma.p_sys->p_buffer = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if( p_vout->chroma.p_sys->p_buffer == NULL )
|
||||
{
|
||||
free( p_vout->chroma.p_sys );
|
||||
return -1;
|
||||
}
|
||||
|
||||
p_vout->chroma.p_sys->p_offset = malloc( p_vout->output.i_width
|
||||
* ( ( p_vout->output.i_chroma
|
||||
== VLC_FOURCC('R','G','B','2') ) ? 2 : 1 )
|
||||
* sizeof( int ) );
|
||||
if( p_vout->chroma.p_sys->p_offset == NULL )
|
||||
{
|
||||
free( p_vout->chroma.p_sys->p_buffer );
|
||||
free( p_vout->chroma.p_sys );
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
switch( p_vout->output.i_chroma )
|
||||
{
|
||||
case VLC_FOURCC('R','G','B','2'):
|
||||
i_tables_size = sizeof( u8 ) * PALETTE_TABLE_SIZE;
|
||||
break;
|
||||
case VLC_FOURCC('R','V','1','5'):
|
||||
case VLC_FOURCC('R','V','1','6'):
|
||||
i_tables_size = sizeof( u16 ) * RGB_TABLE_SIZE;
|
||||
break;
|
||||
default: /* RV24, RV32 */
|
||||
i_tables_size = sizeof( u32 ) * RGB_TABLE_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
p_vout->chroma.p_sys->p_base = malloc( i_tables_size );
|
||||
if( p_vout->chroma.p_sys->p_base == NULL )
|
||||
{
|
||||
free( p_vout->chroma.p_sys->p_offset );
|
||||
free( p_vout->chroma.p_sys->p_buffer );
|
||||
free( p_vout->chroma.p_sys );
|
||||
return -1;
|
||||
}
|
||||
|
||||
SetYUV( p_vout );
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Deactivate: free the chroma function
|
||||
*****************************************************************************
|
||||
* This function frees the previously allocated chroma function
|
||||
*****************************************************************************/
|
||||
static void Deactivate( vlc_object_t *p_this )
|
||||
{
|
||||
vout_thread_t *p_vout = (vout_thread_t *)p_this;
|
||||
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
free( p_vout->chroma.p_sys->p_base );
|
||||
#endif
|
||||
free( p_vout->chroma.p_sys->p_offset );
|
||||
free( p_vout->chroma.p_sys->p_buffer );
|
||||
free( p_vout->chroma.p_sys );
|
||||
}
|
||||
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
/*****************************************************************************
|
||||
* SetGammaTable: return intensity table transformed by gamma curve.
|
||||
*****************************************************************************
|
||||
* pi_table is a table of 256 entries from 0 to 255.
|
||||
*****************************************************************************/
|
||||
static void SetGammaTable( int *pi_table, double f_gamma )
|
||||
{
|
||||
int i_y; /* base intensity */
|
||||
|
||||
/* Use exp(gamma) instead of gamma */
|
||||
f_gamma = exp( f_gamma );
|
||||
|
||||
/* Build gamma table */
|
||||
for( i_y = 0; i_y < 256; i_y++ )
|
||||
{
|
||||
pi_table[ i_y ] = pow( (double)i_y / 256, f_gamma ) * 256;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* SetYUV: compute tables and set function pointers
|
||||
*****************************************************************************/
|
||||
static void SetYUV( vout_thread_t *p_vout )
|
||||
{
|
||||
int pi_gamma[256]; /* gamma table */
|
||||
int i_index; /* index in tables */
|
||||
|
||||
/* Build gamma table */
|
||||
SetGammaTable( pi_gamma, p_vout->f_gamma );
|
||||
|
||||
/*
|
||||
* Set pointers and build YUV tables
|
||||
*/
|
||||
|
||||
/* Color: build red, green and blue tables */
|
||||
switch( p_vout->output.i_chroma )
|
||||
{
|
||||
case VLC_FOURCC('R','G','B','2'):
|
||||
p_vout->chroma.p_sys->p_rgb8 = (u8 *)p_vout->chroma.p_sys->p_base;
|
||||
Set8bppPalette( p_vout, p_vout->chroma.p_sys->p_rgb8 );
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('R','V','1','5'):
|
||||
case VLC_FOURCC('R','V','1','6'):
|
||||
p_vout->chroma.p_sys->p_rgb16 = (u16 *)p_vout->chroma.p_sys->p_base;
|
||||
for( i_index = 0; i_index < RED_MARGIN; i_index++ )
|
||||
{
|
||||
p_vout->chroma.p_sys->p_rgb16[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
|
||||
p_vout->chroma.p_sys->p_rgb16[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
|
||||
}
|
||||
for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
|
||||
{
|
||||
p_vout->chroma.p_sys->p_rgb16[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
|
||||
p_vout->chroma.p_sys->p_rgb16[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
|
||||
}
|
||||
for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
|
||||
{
|
||||
p_vout->chroma.p_sys->p_rgb16[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
|
||||
p_vout->chroma.p_sys->p_rgb16[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
|
||||
}
|
||||
for( i_index = 0; i_index < 256; i_index++ )
|
||||
{
|
||||
p_vout->chroma.p_sys->p_rgb16[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
|
||||
p_vout->chroma.p_sys->p_rgb16[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
|
||||
p_vout->chroma.p_sys->p_rgb16[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
|
||||
}
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('R','V','2','4'):
|
||||
case VLC_FOURCC('R','V','3','2'):
|
||||
p_vout->chroma.p_sys->p_rgb32 = (u32 *)p_vout->chroma.p_sys->p_base;
|
||||
for( i_index = 0; i_index < RED_MARGIN; i_index++ )
|
||||
{
|
||||
p_vout->chroma.p_sys->p_rgb32[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
|
||||
p_vout->chroma.p_sys->p_rgb32[RED_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
|
||||
}
|
||||
for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
|
||||
{
|
||||
p_vout->chroma.p_sys->p_rgb32[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
|
||||
p_vout->chroma.p_sys->p_rgb32[GREEN_OFFSET + 256 + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
|
||||
}
|
||||
for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
|
||||
{
|
||||
p_vout->chroma.p_sys->p_rgb32[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
|
||||
p_vout->chroma.p_sys->p_rgb32[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
|
||||
}
|
||||
for( i_index = 0; i_index < 256; i_index++ )
|
||||
{
|
||||
p_vout->chroma.p_sys->p_rgb32[RED_OFFSET + i_index] = RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
|
||||
p_vout->chroma.p_sys->p_rgb32[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
|
||||
p_vout->chroma.p_sys->p_rgb32[BLUE_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Set8bppPalette( vout_thread_t *p_vout, u8 *p_rgb8 )
|
||||
{
|
||||
#define CLIP( x ) ( ((x < 0) ? 0 : (x > 255) ? 255 : x) << 8 )
|
||||
|
||||
int y,u,v;
|
||||
int r,g,b;
|
||||
int i = 0, j = 0;
|
||||
u16 red[ 256 ], green[ 256 ], blue[ 256 ];
|
||||
unsigned char p_lookup[PALETTE_TABLE_SIZE];
|
||||
|
||||
/* This loop calculates the intersection of an YUV box and the RGB cube. */
|
||||
for ( y = 0; y <= 256; y += 16, i += 128 - 81 )
|
||||
{
|
||||
for ( u = 0; u <= 256; u += 32 )
|
||||
{
|
||||
for ( v = 0; v <= 256; v += 32 )
|
||||
{
|
||||
r = y + ( (V_RED_COEF*(v-128)) >> SHIFT );
|
||||
g = y + ( (U_GREEN_COEF*(u-128)
|
||||
+ V_GREEN_COEF*(v-128)) >> SHIFT );
|
||||
b = y + ( (U_BLUE_COEF*(u-128)) >> SHIFT );
|
||||
|
||||
if( r >= 0x00 && g >= 0x00 && b >= 0x00
|
||||
&& r <= 0xff && g <= 0xff && b <= 0xff )
|
||||
{
|
||||
/* This one should never happen unless someone
|
||||
* fscked up my code */
|
||||
if( j == 256 )
|
||||
{
|
||||
msg_Err( p_vout, "no colors left in palette" );
|
||||
break;
|
||||
}
|
||||
|
||||
/* Clip the colors */
|
||||
red[ j ] = CLIP( r );
|
||||
green[ j ] = CLIP( g );
|
||||
blue[ j ] = CLIP( b );
|
||||
|
||||
/* Allocate color */
|
||||
p_lookup[ i ] = 1;
|
||||
p_rgb8[ i++ ] = j;
|
||||
j++;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_lookup[ i ] = 0;
|
||||
p_rgb8[ i++ ] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The colors have been allocated, we can set the palette */
|
||||
p_vout->output.pf_setpalette( p_vout, red, green, blue );
|
||||
|
||||
#if 0
|
||||
/* There will eventually be a way to know which colors
|
||||
* couldn't be allocated and try to find a replacement */
|
||||
p_vout->i_white_pixel = 0xff;
|
||||
p_vout->i_black_pixel = 0x00;
|
||||
p_vout->i_gray_pixel = 0x44;
|
||||
p_vout->i_blue_pixel = 0x3b;
|
||||
#endif
|
||||
|
||||
/* This loop allocates colors that got outside the RGB cube */
|
||||
for ( i = 0, y = 0; y <= 256; y += 16, i += 128 - 81 )
|
||||
{
|
||||
for ( u = 0; u <= 256; u += 32 )
|
||||
{
|
||||
for ( v = 0; v <= 256; v += 32, i++ )
|
||||
{
|
||||
int u2, v2, dist, mindist = 100000000;
|
||||
|
||||
if( p_lookup[ i ] || y == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Heavy. yeah. */
|
||||
for( u2 = 0; u2 <= 256; u2 += 32 )
|
||||
{
|
||||
for( v2 = 0; v2 <= 256; v2 += 32 )
|
||||
{
|
||||
j = ((y>>4)<<7) + (u2>>5)*9 + (v2>>5);
|
||||
dist = (u-u2)*(u-u2) + (v-v2)*(v-v2);
|
||||
|
||||
/* Find the nearest color */
|
||||
if( p_lookup[ j ] && dist < mindist )
|
||||
{
|
||||
p_rgb8[ i ] = p_rgb8[ j ];
|
||||
mindist = dist;
|
||||
}
|
||||
|
||||
j -= 128;
|
||||
|
||||
/* Find the nearest color */
|
||||
if( p_lookup[ j ] && dist + 128 < mindist )
|
||||
{
|
||||
p_rgb8[ i ] = p_rgb8[ j ];
|
||||
mindist = dist + 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,315 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* i420_rgb.h : YUV to bitmap RGB conversion module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000 VideoLAN
|
||||
* $Id: i420_rgb.h,v 1.8 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* chroma_sys_t: chroma method descriptor
|
||||
*****************************************************************************
|
||||
* This structure is part of the chroma transformation descriptor, it
|
||||
* describes the yuv2rgb specific properties.
|
||||
*****************************************************************************/
|
||||
struct chroma_sys_t
|
||||
{
|
||||
u8 *p_buffer;
|
||||
int *p_offset;
|
||||
|
||||
#ifdef MODULE_NAME_IS_chroma_i420_rgb
|
||||
/* Pre-calculated conversion tables */
|
||||
void *p_base; /* base for all conversion tables */
|
||||
u8 *p_rgb8; /* RGB 8 bits table */
|
||||
u16 *p_rgb16; /* RGB 16 bits table */
|
||||
u32 *p_rgb32; /* RGB 32 bits table */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Prototypes
|
||||
*****************************************************************************/
|
||||
#ifdef MODULE_NAME_IS_chroma_i420_rgb
|
||||
void E_(I420_RGB8) ( vout_thread_t *, picture_t *, picture_t * );
|
||||
#endif
|
||||
void E_(I420_RGB15)( vout_thread_t *, picture_t *, picture_t * );
|
||||
void E_(I420_RGB16)( vout_thread_t *, picture_t *, picture_t * );
|
||||
void E_(I420_RGB32)( vout_thread_t *, picture_t *, picture_t * );
|
||||
|
||||
/*****************************************************************************
|
||||
* CONVERT_*_PIXEL: pixel conversion macros
|
||||
*****************************************************************************
|
||||
* These conversion routines are used by YUV conversion functions.
|
||||
* conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
|
||||
* which is also modified. CONVERT_4YUV_PIXEL is used for 8bpp dithering,
|
||||
* CONVERT_4YUV_PIXEL_SCALE does the same but also scales the output.
|
||||
*****************************************************************************/
|
||||
#define CONVERT_Y_PIXEL( BPP ) \
|
||||
/* Only Y sample is present */ \
|
||||
p_ybase = p_yuv + *p_y++; \
|
||||
*p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \
|
||||
p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) \
|
||||
+ i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
|
||||
|
||||
#define CONVERT_YUV_PIXEL( BPP ) \
|
||||
/* Y, U and V samples are present */ \
|
||||
i_uval = *p_u++; \
|
||||
i_vval = *p_v++; \
|
||||
i_red = (V_RED_COEF * i_vval) >> SHIFT; \
|
||||
i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
|
||||
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
|
||||
CONVERT_Y_PIXEL( BPP ) \
|
||||
|
||||
#define CONVERT_4YUV_PIXEL( CHROMA ) \
|
||||
*p_pic++ = p_lookup[ \
|
||||
(((*p_y++ + dither10[i_real_y]) >> 4) << 7) \
|
||||
+ ((*p_u + dither20[i_real_y]) >> 5) * 9 \
|
||||
+ ((*p_v + dither20[i_real_y]) >> 5) ]; \
|
||||
*p_pic++ = p_lookup[ \
|
||||
(((*p_y++ + dither11[i_real_y]) >> 4) << 7) \
|
||||
+ ((*p_u++ + dither21[i_real_y]) >> 5) * 9 \
|
||||
+ ((*p_v++ + dither21[i_real_y]) >> 5) ]; \
|
||||
*p_pic++ = p_lookup[ \
|
||||
(((*p_y++ + dither12[i_real_y]) >> 4) << 7) \
|
||||
+ ((*p_u + dither22[i_real_y]) >> 5) * 9 \
|
||||
+ ((*p_v + dither22[i_real_y]) >> 5) ]; \
|
||||
*p_pic++ = p_lookup[ \
|
||||
(((*p_y++ + dither13[i_real_y]) >> 4) << 7) \
|
||||
+ ((*p_u++ + dither23[i_real_y]) >> 5) * 9 \
|
||||
+ ((*p_v++ + dither23[i_real_y]) >> 5) ]; \
|
||||
|
||||
#define CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
|
||||
*p_pic++ = p_lookup[ \
|
||||
( ((*p_y + dither10[i_real_y]) >> 4) << 7) \
|
||||
+ ((*p_u + dither20[i_real_y]) >> 5) * 9 \
|
||||
+ ((*p_v + dither20[i_real_y]) >> 5) ]; \
|
||||
p_y += *p_offset++; \
|
||||
p_u += *p_offset; \
|
||||
p_v += *p_offset++; \
|
||||
*p_pic++ = p_lookup[ \
|
||||
( ((*p_y + dither11[i_real_y]) >> 4) << 7) \
|
||||
+ ((*p_u + dither21[i_real_y]) >> 5) * 9 \
|
||||
+ ((*p_v + dither21[i_real_y]) >> 5) ]; \
|
||||
p_y += *p_offset++; \
|
||||
p_u += *p_offset; \
|
||||
p_v += *p_offset++; \
|
||||
*p_pic++ = p_lookup[ \
|
||||
( ((*p_y + dither12[i_real_y]) >> 4) << 7) \
|
||||
+ ((*p_u + dither22[i_real_y]) >> 5) * 9 \
|
||||
+ ((*p_v + dither22[i_real_y]) >> 5) ]; \
|
||||
p_y += *p_offset++; \
|
||||
p_u += *p_offset; \
|
||||
p_v += *p_offset++; \
|
||||
*p_pic++ = p_lookup[ \
|
||||
( ((*p_y + dither13[i_real_y]) >> 4) << 7) \
|
||||
+ ((*p_u + dither23[i_real_y]) >> 5) * 9 \
|
||||
+ ((*p_v + dither23[i_real_y]) >> 5) ]; \
|
||||
p_y += *p_offset++; \
|
||||
p_u += *p_offset; \
|
||||
p_v += *p_offset++; \
|
||||
|
||||
/*****************************************************************************
|
||||
* SCALE_WIDTH: scale a line horizontally
|
||||
*****************************************************************************
|
||||
* This macro scales a line using rendering buffer and offset array. It works
|
||||
* for 1, 2 and 4 Bpp.
|
||||
*****************************************************************************/
|
||||
#define SCALE_WIDTH \
|
||||
if( b_hscale ) \
|
||||
{ \
|
||||
/* Horizontal scaling, conversion has been done to buffer. \
|
||||
* Rewind buffer and offset, then copy and scale line */ \
|
||||
p_buffer = p_buffer_start; \
|
||||
p_offset = p_offset_start; \
|
||||
for( i_x = p_vout->output.i_width / 16; i_x--; ) \
|
||||
{ \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
} \
|
||||
for( i_x = p_vout->output.i_width & 15; i_x--; ) \
|
||||
{ \
|
||||
*p_pic++ = *p_buffer; p_buffer += *p_offset++; \
|
||||
} \
|
||||
p_pic += i_right_margin; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* No scaling, conversion has been done directly in picture memory. \
|
||||
* Increment of picture pointer to end of line is still needed */ \
|
||||
(u8*)p_pic += p_dest->p->i_pitch; \
|
||||
} \
|
||||
|
||||
/*****************************************************************************
|
||||
* SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
|
||||
*****************************************************************************
|
||||
* This macro scales a line using an offset array.
|
||||
*****************************************************************************/
|
||||
#define SCALE_WIDTH_DITHER( CHROMA ) \
|
||||
if( b_hscale ) \
|
||||
{ \
|
||||
/* Horizontal scaling - we can't use a buffer due to dithering */ \
|
||||
p_offset = p_offset_start; \
|
||||
for( i_x = p_vout->output.i_width / 16; i_x--; ) \
|
||||
{ \
|
||||
CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
|
||||
CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
|
||||
CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
|
||||
CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
for( i_x = p_vout->render.i_width / 16; i_x--; ) \
|
||||
{ \
|
||||
CONVERT_4YUV_PIXEL( CHROMA ) \
|
||||
CONVERT_4YUV_PIXEL( CHROMA ) \
|
||||
CONVERT_4YUV_PIXEL( CHROMA ) \
|
||||
CONVERT_4YUV_PIXEL( CHROMA ) \
|
||||
} \
|
||||
} \
|
||||
/* Increment of picture pointer to end of line is still needed */ \
|
||||
p_pic += i_right_margin; \
|
||||
\
|
||||
/* Increment the Y coordinate in the matrix, modulo 4 */ \
|
||||
i_real_y = (i_real_y + 1) & 0x3; \
|
||||
|
||||
/*****************************************************************************
|
||||
* SCALE_HEIGHT: handle vertical scaling
|
||||
*****************************************************************************
|
||||
* This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
|
||||
* 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
|
||||
* and 4 Bpp.
|
||||
*****************************************************************************/
|
||||
#define SCALE_HEIGHT( CHROMA, BPP ) \
|
||||
/* If line is odd, rewind 4:2:0 U and V samples */ \
|
||||
if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
|
||||
{ \
|
||||
p_u -= i_chroma_width; \
|
||||
p_v -= i_chroma_width; \
|
||||
} \
|
||||
\
|
||||
/* \
|
||||
* Handle vertical scaling. The current line can be copied or next one \
|
||||
* can be ignored. \
|
||||
*/ \
|
||||
switch( i_vscale ) \
|
||||
{ \
|
||||
case -1: /* vertical scaling factor is < 1 */ \
|
||||
while( (i_scale_count -= p_vout->output.i_height) > 0 ) \
|
||||
{ \
|
||||
/* Height reduction: skip next source line */ \
|
||||
p_y += p_vout->render.i_width; \
|
||||
i_y++; \
|
||||
if( (CHROMA == 420) || (CHROMA == 422) ) \
|
||||
{ \
|
||||
if( i_y & 0x1 ) \
|
||||
{ \
|
||||
p_u += i_chroma_width; \
|
||||
p_v += i_chroma_width; \
|
||||
} \
|
||||
} \
|
||||
else if( CHROMA == 444 ) \
|
||||
{ \
|
||||
p_u += p_vout->render.i_width; \
|
||||
p_v += p_vout->render.i_width; \
|
||||
} \
|
||||
} \
|
||||
i_scale_count += p_vout->render.i_height; \
|
||||
break; \
|
||||
case 1: /* vertical scaling factor is > 1 */ \
|
||||
while( (i_scale_count -= p_vout->render.i_height) > 0 ) \
|
||||
{ \
|
||||
/* Height increment: copy previous picture line */ \
|
||||
p_vout->p_vlc->pf_memcpy( p_pic, p_pic_start, \
|
||||
p_vout->output.i_width * BPP ); \
|
||||
(u8*)p_pic += p_dest->p->i_pitch; \
|
||||
} \
|
||||
i_scale_count += p_vout->output.i_height; \
|
||||
break; \
|
||||
} \
|
||||
|
||||
/*****************************************************************************
|
||||
* SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
|
||||
*****************************************************************************
|
||||
* This macro handles vertical scaling for a picture. CHROMA may be 420,
|
||||
* 422 or 444 for RGB conversion, or 400 for gray conversion.
|
||||
*****************************************************************************/
|
||||
#define SCALE_HEIGHT_DITHER( CHROMA ) \
|
||||
\
|
||||
/* If line is odd, rewind 4:2:0 U and V samples */ \
|
||||
if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
|
||||
{ \
|
||||
p_u -= i_chroma_width; \
|
||||
p_v -= i_chroma_width; \
|
||||
} \
|
||||
\
|
||||
/* \
|
||||
* Handle vertical scaling. The current line can be copied or next one \
|
||||
* can be ignored. \
|
||||
*/ \
|
||||
\
|
||||
switch( i_vscale ) \
|
||||
{ \
|
||||
case -1: /* vertical scaling factor is < 1 */ \
|
||||
while( (i_scale_count -= p_vout->output.i_height) > 0 ) \
|
||||
{ \
|
||||
/* Height reduction: skip next source line */ \
|
||||
p_y += p_vout->render.i_width; \
|
||||
i_y++; \
|
||||
if( (CHROMA == 420) || (CHROMA == 422) ) \
|
||||
{ \
|
||||
if( i_y & 0x1 ) \
|
||||
{ \
|
||||
p_u += i_chroma_width; \
|
||||
p_v += i_chroma_width; \
|
||||
} \
|
||||
} \
|
||||
else if( CHROMA == 444 ) \
|
||||
{ \
|
||||
p_u += p_vout->render.i_width; \
|
||||
p_v += p_vout->render.i_width; \
|
||||
} \
|
||||
} \
|
||||
i_scale_count += p_vout->render.i_height; \
|
||||
break; \
|
||||
case 1: /* vertical scaling factor is > 1 */ \
|
||||
while( (i_scale_count -= p_vout->render.i_height) > 0 ) \
|
||||
{ \
|
||||
p_y -= p_vout->render.i_width; \
|
||||
p_u -= i_chroma_width; \
|
||||
p_v -= i_chroma_width; \
|
||||
SCALE_WIDTH_DITHER( CHROMA ); \
|
||||
} \
|
||||
i_scale_count += p_vout->output.i_height; \
|
||||
break; \
|
||||
} \
|
||||
|
|
@ -1,498 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* i420_rgb16.c : YUV to bitmap RGB conversion module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000 VideoLAN
|
||||
* $Id: i420_rgb16.c,v 1.10 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <string.h> /* strerror() */
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/vout.h>
|
||||
|
||||
#include "i420_rgb.h"
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
# include "i420_rgb_c.h"
|
||||
#elif defined (MODULE_NAME_IS_chroma_i420_rgb_mmx)
|
||||
# include "i420_rgb_mmx.h"
|
||||
#endif
|
||||
|
||||
static void SetOffset( int, int, int, int, vlc_bool_t *, int *, int * );
|
||||
|
||||
/*****************************************************************************
|
||||
* I420_RGB15: color YUV 4:2:0 to RGB 15 bpp
|
||||
*****************************************************************************
|
||||
* Horizontal alignment needed:
|
||||
* - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
|
||||
* - output: 1 pixel (2 bytes), margins allowed
|
||||
* Vertical alignment needed:
|
||||
* - input: 2 lines (2 Y lines, 1 U/V line)
|
||||
* - output: 1 line
|
||||
*****************************************************************************/
|
||||
void E_(I420_RGB15)( vout_thread_t *p_vout, picture_t *p_src,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
/* We got this one from the old arguments */
|
||||
u16 *p_pic = (u16*)p_dest->p->p_pixels;
|
||||
u8 *p_y = p_src->Y_PIXELS;
|
||||
u8 *p_u = p_src->U_PIXELS;
|
||||
u8 *p_v = p_src->V_PIXELS;
|
||||
|
||||
vlc_bool_t b_hscale; /* horizontal scaling type */
|
||||
int i_vscale; /* vertical scaling type */
|
||||
int i_x, i_y; /* horizontal and vertical indexes */
|
||||
int i_right_margin;
|
||||
int i_rewind;
|
||||
int i_scale_count; /* scale modulo counter */
|
||||
int i_chroma_width = p_vout->render.i_width / 2; /* chroma width */
|
||||
u16 * p_pic_start; /* beginning of the current line for copy */
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
int i_uval, i_vval; /* U and V samples */
|
||||
int i_red, i_green, i_blue; /* U and V modified samples */
|
||||
u16 * p_yuv = p_vout->chroma.p_sys->p_rgb16;
|
||||
u16 * p_ybase; /* Y dependant conversion table */
|
||||
#endif
|
||||
|
||||
/* Conversion buffer pointer */
|
||||
u16 * p_buffer_start = (u16*)p_vout->chroma.p_sys->p_buffer;
|
||||
u16 * p_buffer;
|
||||
|
||||
/* Offset array pointer */
|
||||
int * p_offset_start = p_vout->chroma.p_sys->p_offset;
|
||||
int * p_offset;
|
||||
|
||||
i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
|
||||
|
||||
if( p_vout->render.i_width & 7 )
|
||||
{
|
||||
i_rewind = 8 - ( p_vout->render.i_width & 7 );
|
||||
}
|
||||
else
|
||||
{
|
||||
i_rewind = 0;
|
||||
}
|
||||
|
||||
/* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
|
||||
* on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
|
||||
* then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
|
||||
SetOffset( p_vout->render.i_width, p_vout->render.i_height,
|
||||
p_vout->output.i_width, p_vout->output.i_height,
|
||||
&b_hscale, &i_vscale, p_offset_start );
|
||||
|
||||
/*
|
||||
* Perform conversion
|
||||
*/
|
||||
i_scale_count = ( i_vscale == 1 ) ?
|
||||
p_vout->output.i_height : p_vout->render.i_height;
|
||||
for( i_y = 0; i_y < p_vout->render.i_height; i_y++ )
|
||||
{
|
||||
p_pic_start = p_pic;
|
||||
p_buffer = b_hscale ? p_buffer_start : p_pic;
|
||||
|
||||
for ( i_x = p_vout->render.i_width / 8; i_x--; )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
#elif defined (MODULE_NAME_IS_chroma_i420_rgb_mmx)
|
||||
__asm__( MMX_INIT_16
|
||||
: : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
|
||||
|
||||
__asm__( ".align 8"
|
||||
MMX_YUV_MUL
|
||||
MMX_YUV_ADD
|
||||
MMX_UNPACK_15
|
||||
: : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
|
||||
|
||||
p_y += 8;
|
||||
p_u += 4;
|
||||
p_v += 4;
|
||||
p_buffer += 8;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Here we do some unaligned reads and duplicate conversions, but
|
||||
* at least we have all the pixels */
|
||||
if( i_rewind )
|
||||
{
|
||||
p_y -= i_rewind;
|
||||
p_u -= i_rewind >> 1;
|
||||
p_v -= i_rewind >> 1;
|
||||
p_buffer -= i_rewind;
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
#elif defined (MODULE_NAME_IS_chroma_i420_rgb_mmx)
|
||||
__asm__( MMX_INIT_16
|
||||
: : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
|
||||
|
||||
__asm__( ".align 8"
|
||||
MMX_YUV_MUL
|
||||
MMX_YUV_ADD
|
||||
MMX_UNPACK_15
|
||||
: : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
|
||||
|
||||
p_y += 8;
|
||||
p_u += 4;
|
||||
p_v += 4;
|
||||
p_buffer += 8;
|
||||
#endif
|
||||
}
|
||||
SCALE_WIDTH;
|
||||
SCALE_HEIGHT( 420, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I420_RGB16: color YUV 4:2:0 to RGB 16 bpp
|
||||
*****************************************************************************
|
||||
* Horizontal alignment needed:
|
||||
* - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
|
||||
* - output: 1 pixel (2 bytes), margins allowed
|
||||
* Vertical alignment needed:
|
||||
* - input: 2 lines (2 Y lines, 1 U/V line)
|
||||
* - output: 1 line
|
||||
*****************************************************************************/
|
||||
void E_(I420_RGB16)( vout_thread_t *p_vout, picture_t *p_src,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
/* We got this one from the old arguments */
|
||||
u16 *p_pic = (u16*)p_dest->p->p_pixels;
|
||||
u8 *p_y = p_src->Y_PIXELS;
|
||||
u8 *p_u = p_src->U_PIXELS;
|
||||
u8 *p_v = p_src->V_PIXELS;
|
||||
|
||||
vlc_bool_t b_hscale; /* horizontal scaling type */
|
||||
int i_vscale; /* vertical scaling type */
|
||||
int i_x, i_y; /* horizontal and vertical indexes */
|
||||
int i_right_margin;
|
||||
int i_rewind;
|
||||
int i_scale_count; /* scale modulo counter */
|
||||
int i_chroma_width = p_vout->render.i_width / 2; /* chroma width */
|
||||
u16 * p_pic_start; /* beginning of the current line for copy */
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
int i_uval, i_vval; /* U and V samples */
|
||||
int i_red, i_green, i_blue; /* U and V modified samples */
|
||||
u16 * p_yuv = p_vout->chroma.p_sys->p_rgb16;
|
||||
u16 * p_ybase; /* Y dependant conversion table */
|
||||
#endif
|
||||
|
||||
/* Conversion buffer pointer */
|
||||
u16 * p_buffer_start = (u16*)p_vout->chroma.p_sys->p_buffer;
|
||||
u16 * p_buffer;
|
||||
|
||||
/* Offset array pointer */
|
||||
int * p_offset_start = p_vout->chroma.p_sys->p_offset;
|
||||
int * p_offset;
|
||||
|
||||
i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
|
||||
|
||||
if( p_vout->render.i_width & 7 )
|
||||
{
|
||||
i_rewind = 8 - ( p_vout->render.i_width & 7 );
|
||||
}
|
||||
else
|
||||
{
|
||||
i_rewind = 0;
|
||||
}
|
||||
|
||||
/* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
|
||||
* on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
|
||||
* then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
|
||||
SetOffset( p_vout->render.i_width, p_vout->render.i_height,
|
||||
p_vout->output.i_width, p_vout->output.i_height,
|
||||
&b_hscale, &i_vscale, p_offset_start );
|
||||
|
||||
/*
|
||||
* Perform conversion
|
||||
*/
|
||||
i_scale_count = ( i_vscale == 1 ) ?
|
||||
p_vout->output.i_height : p_vout->render.i_height;
|
||||
for( i_y = 0; i_y < p_vout->render.i_height; i_y++ )
|
||||
{
|
||||
p_pic_start = p_pic;
|
||||
p_buffer = b_hscale ? p_buffer_start : p_pic;
|
||||
|
||||
for ( i_x = p_vout->render.i_width / 8; i_x--; )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
#elif defined (MODULE_NAME_IS_chroma_i420_rgb_mmx)
|
||||
__asm__( MMX_INIT_16
|
||||
: : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
|
||||
|
||||
__asm__( ".align 8"
|
||||
MMX_YUV_MUL
|
||||
MMX_YUV_ADD
|
||||
MMX_UNPACK_16
|
||||
: : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
|
||||
|
||||
p_y += 8;
|
||||
p_u += 4;
|
||||
p_v += 4;
|
||||
p_buffer += 8;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Here we do some unaligned reads and duplicate conversions, but
|
||||
* at least we have all the pixels */
|
||||
if( i_rewind )
|
||||
{
|
||||
p_y -= i_rewind;
|
||||
p_u -= i_rewind >> 1;
|
||||
p_v -= i_rewind >> 1;
|
||||
p_buffer -= i_rewind;
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
|
||||
#elif defined (MODULE_NAME_IS_chroma_i420_rgb_mmx)
|
||||
__asm__( MMX_INIT_16
|
||||
: : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
|
||||
|
||||
__asm__( ".align 8"
|
||||
MMX_YUV_MUL
|
||||
MMX_YUV_ADD
|
||||
MMX_UNPACK_16
|
||||
: : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
|
||||
|
||||
p_y += 8;
|
||||
p_u += 4;
|
||||
p_v += 4;
|
||||
p_buffer += 8;
|
||||
#endif
|
||||
}
|
||||
SCALE_WIDTH;
|
||||
SCALE_HEIGHT( 420, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I420_RGB32: color YUV 4:2:0 to RGB 32 bpp
|
||||
*****************************************************************************
|
||||
* Horizontal alignment needed:
|
||||
* - input: 8 pixels (8 Y bytes, 4 U/V bytes), margins not allowed
|
||||
* - output: 1 pixel (2 bytes), margins allowed
|
||||
* Vertical alignment needed:
|
||||
* - input: 2 lines (2 Y lines, 1 U/V line)
|
||||
* - output: 1 line
|
||||
*****************************************************************************/
|
||||
void E_(I420_RGB32)( vout_thread_t *p_vout, picture_t *p_src,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
/* We got this one from the old arguments */
|
||||
u32 *p_pic = (u32*)p_dest->p->p_pixels;
|
||||
u8 *p_y = p_src->Y_PIXELS;
|
||||
u8 *p_u = p_src->U_PIXELS;
|
||||
u8 *p_v = p_src->V_PIXELS;
|
||||
|
||||
vlc_bool_t b_hscale; /* horizontal scaling type */
|
||||
int i_vscale; /* vertical scaling type */
|
||||
int i_x, i_y; /* horizontal and vertical indexes */
|
||||
int i_right_margin;
|
||||
int i_rewind;
|
||||
int i_scale_count; /* scale modulo counter */
|
||||
int i_chroma_width = p_vout->render.i_width / 4; /* chroma width */
|
||||
u32 * p_pic_start; /* beginning of the current line for copy */
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
int i_uval, i_vval; /* U and V samples */
|
||||
int i_red, i_green, i_blue; /* U and V modified samples */
|
||||
u32 * p_yuv = p_vout->chroma.p_sys->p_rgb32;
|
||||
u32 * p_ybase; /* Y dependant conversion table */
|
||||
#endif
|
||||
|
||||
/* Conversion buffer pointer */
|
||||
u32 * p_buffer_start = (u32*)p_vout->chroma.p_sys->p_buffer;
|
||||
u32 * p_buffer;
|
||||
|
||||
/* Offset array pointer */
|
||||
int * p_offset_start = p_vout->chroma.p_sys->p_offset;
|
||||
int * p_offset;
|
||||
|
||||
i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
|
||||
|
||||
if( p_vout->render.i_width & 7 )
|
||||
{
|
||||
i_rewind = 8 - ( p_vout->render.i_width & 7 );
|
||||
}
|
||||
else
|
||||
{
|
||||
i_rewind = 0;
|
||||
}
|
||||
|
||||
/* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
|
||||
* on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
|
||||
* then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
|
||||
SetOffset( p_vout->render.i_width, p_vout->render.i_height,
|
||||
p_vout->output.i_width, p_vout->output.i_height,
|
||||
&b_hscale, &i_vscale, p_offset_start );
|
||||
|
||||
/*
|
||||
* Perform conversion
|
||||
*/
|
||||
i_scale_count = ( i_vscale == 1 ) ?
|
||||
p_vout->output.i_height : p_vout->render.i_height;
|
||||
for( i_y = 0; i_y < p_vout->render.i_height; i_y++ )
|
||||
{
|
||||
p_pic_start = p_pic;
|
||||
p_buffer = b_hscale ? p_buffer_start : p_pic;
|
||||
|
||||
for ( i_x = p_vout->render.i_width / 8; i_x--; )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
|
||||
CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
|
||||
CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
|
||||
CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
|
||||
#elif defined (MODULE_NAME_IS_chroma_i420_rgb_mmx)
|
||||
__asm__( MMX_INIT_32
|
||||
: : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
|
||||
|
||||
__asm__( ".align 8"
|
||||
MMX_YUV_MUL
|
||||
MMX_YUV_ADD
|
||||
MMX_UNPACK_32
|
||||
: : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
|
||||
|
||||
p_y += 8;
|
||||
p_u += 4;
|
||||
p_v += 4;
|
||||
p_buffer += 8;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Here we do some unaligned reads and duplicate conversions, but
|
||||
* at least we have all the pixels */
|
||||
if( i_rewind )
|
||||
{
|
||||
p_y -= i_rewind;
|
||||
p_u -= i_rewind >> 1;
|
||||
p_v -= i_rewind >> 1;
|
||||
p_buffer -= i_rewind;
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_rgb)
|
||||
CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
|
||||
CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
|
||||
CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
|
||||
CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
|
||||
#elif defined (MODULE_NAME_IS_chroma_i420_rgb_mmx)
|
||||
__asm__( MMX_INIT_32
|
||||
: : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
|
||||
|
||||
__asm__( ".align 8"
|
||||
MMX_YUV_MUL
|
||||
MMX_YUV_ADD
|
||||
MMX_UNPACK_32
|
||||
: : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
|
||||
|
||||
p_y += 8;
|
||||
p_u += 4;
|
||||
p_v += 4;
|
||||
p_buffer += 8;
|
||||
#endif
|
||||
}
|
||||
SCALE_WIDTH;
|
||||
SCALE_HEIGHT( 420, 4 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Following functions are local */
|
||||
|
||||
/*****************************************************************************
|
||||
* SetOffset: build offset array for conversion functions
|
||||
*****************************************************************************
|
||||
* This function will build an offset array used in later conversion functions.
|
||||
* It will also set horizontal and vertical scaling indicators.
|
||||
*****************************************************************************/
|
||||
static void SetOffset( int i_width, int i_height, int i_pic_width,
|
||||
int i_pic_height, vlc_bool_t *pb_hscale,
|
||||
int *pi_vscale, int *p_offset )
|
||||
{
|
||||
int i_x; /* x position in destination */
|
||||
int i_scale_count; /* modulo counter */
|
||||
|
||||
/*
|
||||
* Prepare horizontal offset array
|
||||
*/
|
||||
if( i_pic_width - i_width == 0 )
|
||||
{
|
||||
/* No horizontal scaling: YUV conversion is done directly to picture */
|
||||
*pb_hscale = 0;
|
||||
}
|
||||
else if( i_pic_width - i_width > 0 )
|
||||
{
|
||||
/* Prepare scaling array for horizontal extension */
|
||||
*pb_hscale = 1;
|
||||
i_scale_count = i_pic_width;
|
||||
for( i_x = i_width; i_x--; )
|
||||
{
|
||||
while( (i_scale_count -= i_width) > 0 )
|
||||
{
|
||||
*p_offset++ = 0;
|
||||
}
|
||||
*p_offset++ = 1;
|
||||
i_scale_count += i_pic_width;
|
||||
}
|
||||
}
|
||||
else /* if( i_pic_width - i_width < 0 ) */
|
||||
{
|
||||
/* Prepare scaling array for horizontal reduction */
|
||||
*pb_hscale = 1;
|
||||
i_scale_count = i_width;
|
||||
for( i_x = i_pic_width; i_x--; )
|
||||
{
|
||||
*p_offset = 1;
|
||||
while( (i_scale_count -= i_pic_width) > 0 )
|
||||
{
|
||||
*p_offset += 1;
|
||||
}
|
||||
p_offset++;
|
||||
i_scale_count += i_width;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set vertical scaling indicator
|
||||
*/
|
||||
if( i_pic_height - i_height == 0 )
|
||||
{
|
||||
*pi_vscale = 0;
|
||||
}
|
||||
else if( i_pic_height - i_height > 0 )
|
||||
{
|
||||
*pi_vscale = 1;
|
||||
}
|
||||
else /* if( i_pic_height - i_height < 0 ) */
|
||||
{
|
||||
*pi_vscale = -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* i420_rgb8.c : YUV to bitmap RGB conversion module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000 VideoLAN
|
||||
* $Id: i420_rgb8.c,v 1.8 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <string.h> /* strerror() */
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/vout.h>
|
||||
|
||||
#include "i420_rgb.h"
|
||||
#include "i420_rgb_c.h"
|
||||
|
||||
static void SetOffset( int, int, int, int, vlc_bool_t *, int *, int * );
|
||||
|
||||
/*****************************************************************************
|
||||
* I420_RGB8: color YUV 4:2:0 to RGB 8 bpp
|
||||
*****************************************************************************/
|
||||
void E_(I420_RGB8)( vout_thread_t *p_vout, picture_t *p_src, picture_t *p_dest )
|
||||
{
|
||||
/* We got this one from the old arguments */
|
||||
u8 *p_pic = (u8*)p_dest->p->p_pixels;
|
||||
u8 *p_y = p_src->Y_PIXELS;
|
||||
u8 *p_u = p_src->U_PIXELS;
|
||||
u8 *p_v = p_src->V_PIXELS;
|
||||
|
||||
vlc_bool_t b_hscale; /* horizontal scaling type */
|
||||
int i_vscale; /* vertical scaling type */
|
||||
int i_x, i_y; /* horizontal and vertical indexes */
|
||||
int i_real_y; /* y % 4 */
|
||||
int i_right_margin;
|
||||
int i_scale_count; /* scale modulo counter */
|
||||
int i_chroma_width = p_vout->render.i_width / 2; /* chroma width */
|
||||
|
||||
/* Lookup table */
|
||||
u8 * p_lookup = p_vout->chroma.p_sys->p_base;
|
||||
|
||||
/* Offset array pointer */
|
||||
int * p_offset_start = p_vout->chroma.p_sys->p_offset;
|
||||
int * p_offset;
|
||||
|
||||
/* The dithering matrices */
|
||||
static int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
|
||||
static int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
|
||||
static int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
|
||||
static int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
|
||||
|
||||
static int dither20[4] = { 0x0, 0x10, 0x4, 0x14 };
|
||||
static int dither21[4] = { 0x18, 0x8, 0x1c, 0xc };
|
||||
static int dither22[4] = { 0x6, 0x16, 0x2, 0x12 };
|
||||
static int dither23[4] = { 0x1e, 0xe, 0x1a, 0xa };
|
||||
|
||||
SetOffset( p_vout->render.i_width, p_vout->render.i_height,
|
||||
p_vout->output.i_width, p_vout->output.i_height,
|
||||
&b_hscale, &i_vscale, p_offset_start );
|
||||
|
||||
i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
|
||||
|
||||
/*
|
||||
* Perform conversion
|
||||
*/
|
||||
i_scale_count = ( i_vscale == 1 ) ?
|
||||
p_vout->output.i_height : p_vout->render.i_height;
|
||||
for( i_y = 0, i_real_y = 0; i_y < p_vout->render.i_height; i_y++ )
|
||||
{
|
||||
/* Do horizontal and vertical scaling */
|
||||
SCALE_WIDTH_DITHER( 420 );
|
||||
SCALE_HEIGHT_DITHER( 420 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Following functions are local */
|
||||
|
||||
/*****************************************************************************
|
||||
* SetOffset: build offset array for conversion functions
|
||||
*****************************************************************************
|
||||
* This function will build an offset array used in later conversion functions.
|
||||
* It will also set horizontal and vertical scaling indicators. The p_offset
|
||||
* structure has interleaved Y and U/V offsets.
|
||||
*****************************************************************************/
|
||||
static void SetOffset( int i_width, int i_height, int i_pic_width,
|
||||
int i_pic_height, vlc_bool_t *pb_hscale,
|
||||
int *pi_vscale, int *p_offset )
|
||||
{
|
||||
int i_x; /* x position in destination */
|
||||
int i_scale_count; /* modulo counter */
|
||||
|
||||
/*
|
||||
* Prepare horizontal offset array
|
||||
*/
|
||||
if( i_pic_width - i_width == 0 )
|
||||
{
|
||||
/* No horizontal scaling: YUV conversion is done directly to picture */
|
||||
*pb_hscale = 0;
|
||||
}
|
||||
else if( i_pic_width - i_width > 0 )
|
||||
{
|
||||
int i_dummy = 0;
|
||||
|
||||
/* Prepare scaling array for horizontal extension */
|
||||
*pb_hscale = 1;
|
||||
i_scale_count = i_pic_width;
|
||||
for( i_x = i_width; i_x--; )
|
||||
{
|
||||
while( (i_scale_count -= i_width) > 0 )
|
||||
{
|
||||
*p_offset++ = 0;
|
||||
*p_offset++ = 0;
|
||||
}
|
||||
*p_offset++ = 1;
|
||||
*p_offset++ = i_dummy;
|
||||
i_dummy = 1 - i_dummy;
|
||||
i_scale_count += i_pic_width;
|
||||
}
|
||||
}
|
||||
else /* if( i_pic_width - i_width < 0 ) */
|
||||
{
|
||||
int i_remainder = 0;
|
||||
int i_jump;
|
||||
|
||||
/* Prepare scaling array for horizontal reduction */
|
||||
*pb_hscale = 1;
|
||||
i_scale_count = i_width;
|
||||
for( i_x = i_pic_width; i_x--; )
|
||||
{
|
||||
i_jump = 1;
|
||||
while( (i_scale_count -= i_pic_width) > 0 )
|
||||
{
|
||||
i_jump += 1;
|
||||
}
|
||||
*p_offset++ = i_jump;
|
||||
*p_offset++ = ( i_jump += i_remainder ) >> 1;
|
||||
i_remainder = i_jump & 1;
|
||||
i_scale_count += i_width;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set vertical scaling indicator
|
||||
*/
|
||||
if( i_pic_height - i_height == 0 )
|
||||
{
|
||||
*pi_vscale = 0;
|
||||
}
|
||||
else if( i_pic_height - i_height > 0 )
|
||||
{
|
||||
*pi_vscale = 1;
|
||||
}
|
||||
else /* if( i_pic_height - i_height < 0 ) */
|
||||
{
|
||||
*pi_vscale = -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* chroma_common.h: YUV transformation functions
|
||||
* Provides functions to perform the YUV conversion. The functions provided here
|
||||
* are a complete and portable C implementation, and may be replaced in certain
|
||||
* case by optimized functions.
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000 VideoLAN
|
||||
* $Id: i420_rgb_c.h,v 1.1 2002/01/04 14:01:34 sam Exp $
|
||||
*
|
||||
* Authors: Vincent Seguin <seguin@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-1307, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Constants
|
||||
*****************************************************************************/
|
||||
|
||||
/* Margins and offsets in conversion tables - Margins are used in case a RGB
|
||||
* RGB conversion would give a value outside the 0-255 range. Offsets have been
|
||||
* calculated to avoid using the same cache line for 2 tables. conversion tables
|
||||
* are 2*MARGIN + 256 long and stores pixels.*/
|
||||
#define RED_MARGIN 178
|
||||
#define GREEN_MARGIN 135
|
||||
#define BLUE_MARGIN 224
|
||||
#define RED_OFFSET 1501 /* 1323 to 1935 */
|
||||
#define GREEN_OFFSET 135 /* 0 to 526 */
|
||||
#define BLUE_OFFSET 818 /* 594 to 1298 */
|
||||
#define RGB_TABLE_SIZE 1935 /* total table size */
|
||||
|
||||
#define GRAY_MARGIN 384
|
||||
#define GRAY_TABLE_SIZE 1024 /* total table size */
|
||||
|
||||
#define PALETTE_TABLE_SIZE 2176 /* YUV -> 8bpp palette lookup table */
|
||||
|
||||
/* macros used for YUV pixel conversions */
|
||||
#define SHIFT 20
|
||||
#define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
|
||||
#define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
|
||||
#define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
|
||||
#define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
|
||||
|
|
@ -1,284 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* transforms_yuvmmx.h: MMX YUV transformation assembly
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000 VideoLAN
|
||||
* $Id: i420_rgb_mmx.h,v 1.3 2002/06/01 12:31:58 sam Exp $
|
||||
*
|
||||
* Authors: Olie Lho <ollie@sis.com.tw>
|
||||
* Gaël Hendryckx <jimmy@via.ecp.fr>
|
||||
* Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* 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-1307, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
/* hope these constant values are cache line aligned */
|
||||
#define UNUSED_LONGLONG(foo) \
|
||||
static const unsigned long long foo __asm__ (#foo) __attribute__((unused))
|
||||
UNUSED_LONGLONG(mmx_80w) = 0x0080008000800080;
|
||||
UNUSED_LONGLONG(mmx_10w) = 0x1010101010101010;
|
||||
UNUSED_LONGLONG(mmx_00ffw) = 0x00ff00ff00ff00ff;
|
||||
UNUSED_LONGLONG(mmx_Y_coeff) = 0x253f253f253f253f;
|
||||
|
||||
UNUSED_LONGLONG(mmx_U_green) = 0xf37df37df37df37d;
|
||||
UNUSED_LONGLONG(mmx_U_blue) = 0x4093409340934093;
|
||||
UNUSED_LONGLONG(mmx_V_red) = 0x3312331233123312;
|
||||
UNUSED_LONGLONG(mmx_V_green) = 0xe5fce5fce5fce5fc;
|
||||
|
||||
UNUSED_LONGLONG(mmx_mask_f8) = 0xf8f8f8f8f8f8f8f8;
|
||||
UNUSED_LONGLONG(mmx_mask_fc) = 0xfcfcfcfcfcfcfcfc;
|
||||
#undef UNUSED_LONGLONG
|
||||
|
||||
#define MMX_INIT_16 " \n\
|
||||
movd (%1), %%mm0 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
movd (%2), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
pxor %%mm4, %%mm4 # zero mm4 \n\
|
||||
movq (%0), %%mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
#movl $0, (%3) # cache preload for image \n\
|
||||
"
|
||||
|
||||
#define MMX_INIT_16_GRAY " \n\
|
||||
movq (%0), %%mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
#movl $0, (%3) # cache preload for image \n\
|
||||
"
|
||||
|
||||
#define MMX_INIT_32 " \n\
|
||||
movd (%1), %%mm0 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
movl $0, (%3) # cache preload for image \n\
|
||||
movd (%2), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
pxor %%mm4, %%mm4 # zero mm4 \n\
|
||||
movq (%0), %%mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
"
|
||||
|
||||
/*
|
||||
* Do the multiply part of the conversion for even and odd pixels,
|
||||
* register usage:
|
||||
* mm0 -> Cblue, mm1 -> Cred, mm2 -> Cgreen even pixels,
|
||||
* mm3 -> Cblue, mm4 -> Cred, mm5 -> Cgreen odd pixels,
|
||||
* mm6 -> Y even, mm7 -> Y odd
|
||||
*/
|
||||
|
||||
#define MMX_YUV_MUL " \n\
|
||||
# convert the chroma part \n\
|
||||
punpcklbw %%mm4, %%mm0 # scatter 4 Cb 00 u3 00 u2 00 u1 00 u0 \n\
|
||||
punpcklbw %%mm4, %%mm1 # scatter 4 Cr 00 v3 00 v2 00 v1 00 v0 \n\
|
||||
psubsw mmx_80w, %%mm0 # Cb -= 128 \n\
|
||||
psubsw mmx_80w, %%mm1 # Cr -= 128 \n\
|
||||
psllw $3, %%mm0 # Promote precision \n\
|
||||
psllw $3, %%mm1 # Promote precision \n\
|
||||
movq %%mm0, %%mm2 # Copy 4 Cb 00 u3 00 u2 00 u1 00 u0 \n\
|
||||
movq %%mm1, %%mm3 # Copy 4 Cr 00 v3 00 v2 00 v1 00 v0 \n\
|
||||
pmulhw mmx_U_green, %%mm2 # Mul Cb with green coeff -> Cb green \n\
|
||||
pmulhw mmx_V_green, %%mm3 # Mul Cr with green coeff -> Cr green \n\
|
||||
pmulhw mmx_U_blue, %%mm0 # Mul Cb -> Cblue 00 b3 00 b2 00 b1 00 b0 \n\
|
||||
pmulhw mmx_V_red, %%mm1 # Mul Cr -> Cred 00 r3 00 r2 00 r1 00 r0 \n\
|
||||
paddsw %%mm3, %%mm2 # Cb green + Cr green -> Cgreen \n\
|
||||
\n\
|
||||
# convert the luma part \n\
|
||||
psubusb mmx_10w, %%mm6 # Y -= 16 \n\
|
||||
movq %%mm6, %%mm7 # Copy 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
pand mmx_00ffw, %%mm6 # get Y even 00 Y6 00 Y4 00 Y2 00 Y0 \n\
|
||||
psrlw $8, %%mm7 # get Y odd 00 Y7 00 Y5 00 Y3 00 Y1 \n\
|
||||
psllw $3, %%mm6 # Promote precision \n\
|
||||
psllw $3, %%mm7 # Promote precision \n\
|
||||
pmulhw mmx_Y_coeff, %%mm6 # Mul 4 Y even 00 y6 00 y4 00 y2 00 y0 \n\
|
||||
pmulhw mmx_Y_coeff, %%mm7 # Mul 4 Y odd 00 y7 00 y5 00 y3 00 y1 \n\
|
||||
"
|
||||
|
||||
/*
|
||||
* Do the addition part of the conversion for even and odd pixels,
|
||||
* register usage:
|
||||
* mm0 -> Cblue, mm1 -> Cred, mm2 -> Cgreen even pixels,
|
||||
* mm3 -> Cblue, mm4 -> Cred, mm5 -> Cgreen odd pixels,
|
||||
* mm6 -> Y even, mm7 -> Y odd
|
||||
*/
|
||||
|
||||
#define MMX_YUV_ADD " \n\
|
||||
# Do horizontal and vertical scaling \n\
|
||||
movq %%mm0, %%mm3 # Copy Cblue \n\
|
||||
movq %%mm1, %%mm4 # Copy Cred \n\
|
||||
movq %%mm2, %%mm5 # Copy Cgreen \n\
|
||||
paddsw %%mm6, %%mm0 # Y even + Cblue 00 B6 00 B4 00 B2 00 B0 \n\
|
||||
paddsw %%mm7, %%mm3 # Y odd + Cblue 00 B7 00 B5 00 B3 00 B1 \n\
|
||||
paddsw %%mm6, %%mm1 # Y even + Cred 00 R6 00 R4 00 R2 00 R0 \n\
|
||||
paddsw %%mm7, %%mm4 # Y odd + Cred 00 R7 00 R5 00 R3 00 R1 \n\
|
||||
paddsw %%mm6, %%mm2 # Y even + Cgreen 00 G6 00 G4 00 G2 00 G0 \n\
|
||||
paddsw %%mm7, %%mm5 # Y odd + Cgreen 00 G7 00 G5 00 G3 00 G1 \n\
|
||||
\n\
|
||||
# Limit RGB even to 0..255 \n\
|
||||
packuswb %%mm0, %%mm0 # B6 B4 B2 B0 / B6 B4 B2 B0 \n\
|
||||
packuswb %%mm1, %%mm1 # R6 R4 R2 R0 / R6 R4 R2 R0 \n\
|
||||
packuswb %%mm2, %%mm2 # G6 G4 G2 G0 / G6 G4 G2 G0 \n\
|
||||
\n\
|
||||
# Limit RGB odd to 0..255 \n\
|
||||
packuswb %%mm3, %%mm3 # B7 B5 B3 B1 / B7 B5 B3 B1 \n\
|
||||
packuswb %%mm4, %%mm4 # R7 R5 R3 R1 / R7 R5 R3 R1 \n\
|
||||
packuswb %%mm5, %%mm5 # G7 G5 G3 G1 / G7 G5 G3 G1 \n\
|
||||
\n\
|
||||
# Interleave RGB even and odd \n\
|
||||
punpcklbw %%mm3, %%mm0 # B7 B6 B5 B4 B3 B2 B1 B0 \n\
|
||||
punpcklbw %%mm4, %%mm1 # R7 R6 R5 R4 R3 R2 R1 R0 \n\
|
||||
punpcklbw %%mm5, %%mm2 # G7 G6 G5 G4 G3 G2 G1 G0 \n\
|
||||
"
|
||||
|
||||
/*
|
||||
* Grayscale case, only use Y
|
||||
*/
|
||||
|
||||
#define MMX_YUV_GRAY " \n\
|
||||
# convert the luma part \n\
|
||||
psubusb mmx_10w, %%mm6 \n\
|
||||
movq %%mm6, %%mm7 \n\
|
||||
pand mmx_00ffw, %%mm6 \n\
|
||||
psrlw $8, %%mm7 \n\
|
||||
psllw $3, %%mm6 \n\
|
||||
psllw $3, %%mm7 \n\
|
||||
pmulhw mmx_Y_coeff, %%mm6 \n\
|
||||
pmulhw mmx_Y_coeff, %%mm7 \n\
|
||||
packuswb %%mm6, %%mm6 \n\
|
||||
packuswb %%mm7, %%mm7 \n\
|
||||
punpcklbw %%mm7, %%mm6 \n\
|
||||
"
|
||||
|
||||
#define MMX_UNPACK_16_GRAY " \n\
|
||||
movq %%mm6, %%mm5 \n\
|
||||
pand mmx_mask_f8, %%mm6 \n\
|
||||
pand mmx_mask_fc, %%mm5 \n\
|
||||
movq %%mm6, %%mm7 \n\
|
||||
psrlw $3, %%mm7 \n\
|
||||
pxor %%mm3, %%mm3 \n\
|
||||
movq %%mm7, %%mm2 \n\
|
||||
movq %%mm5, %%mm0 \n\
|
||||
punpcklbw %%mm3, %%mm5 \n\
|
||||
punpcklbw %%mm6, %%mm7 \n\
|
||||
psllw $3, %%mm5 \n\
|
||||
por %%mm5, %%mm7 \n\
|
||||
movq %%mm7, (%3) \n\
|
||||
punpckhbw %%mm3, %%mm0 \n\
|
||||
punpckhbw %%mm6, %%mm2 \n\
|
||||
psllw $3, %%mm0 \n\
|
||||
movq 8(%0), %%mm6 \n\
|
||||
por %%mm0, %%mm2 \n\
|
||||
movq %%mm2, 8(%3) \n\
|
||||
"
|
||||
|
||||
|
||||
/*
|
||||
* convert RGB plane to RGB 15 bits,
|
||||
* mm0 -> B, mm1 -> R, mm2 -> G,
|
||||
* mm4 -> GB, mm5 -> AR pixel 4-7,
|
||||
* mm6 -> GB, mm7 -> AR pixel 0-3
|
||||
*/
|
||||
|
||||
#define MMX_UNPACK_15 " \n\
|
||||
# mask unneeded bits off \n\
|
||||
pand mmx_mask_f8, %%mm0 # b7b6b5b4 b3______ b7b6b5b4 b3______ \n\
|
||||
psrlw $3,%%mm0 # ______b7 b6b5b4b3 ______b7 b6b5b4b3 \n\
|
||||
pand mmx_mask_f8, %%mm2 # g7g6g5g4 g3______ g7g6g5g4 g3______ \n\
|
||||
pand mmx_mask_f8, %%mm1 # r7r6r5r4 r3______ r7r6r5r4 r3______ \n\
|
||||
psrlw $1,%%mm1 # __r7r6r5 r4r3____ __r7r6r5 r4r3____ \n\
|
||||
pxor %%mm4, %%mm4 # zero mm4 \n\
|
||||
movq %%mm0, %%mm5 # Copy B7-B0 \n\
|
||||
movq %%mm2, %%mm7 # Copy G7-G0 \n\
|
||||
\n\
|
||||
# convert rgb24 plane to rgb15 pack for pixel 0-3 \n\
|
||||
punpcklbw %%mm4, %%mm2 # ________ ________ g7g6g5g4 g3______ \n\
|
||||
punpcklbw %%mm1, %%mm0 # r7r6r5r4 r3______ ______b7 b6b5b4b3 \n\
|
||||
psllw $2,%%mm2 # ________ ____g7g6 g5g4g3__ ________ \n\
|
||||
por %%mm2, %%mm0 # r7r6r5r4 r3__g7g6 g5g4g3b7 b6b5b4b3 \n\
|
||||
movq 8(%0), %%mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
movq %%mm0, (%3) # store pixel 0-3 \n\
|
||||
\n\
|
||||
# convert rgb24 plane to rgb16 pack for pixel 0-3 \n\
|
||||
punpckhbw %%mm4, %%mm7 # ________ ________ g7g6g5g4 g3______ \n\
|
||||
punpckhbw %%mm1, %%mm5 # r7r6r5r4 r3______ ______b7 b6b5b4b3 \n\
|
||||
psllw $2,%%mm7 # ________ ____g7g6 g5g4g3__ ________ \n\
|
||||
movd 4(%1), %%mm0 # Load 4 Cb __ __ __ __ u3 u2 u1 u0 \n\
|
||||
por %%mm7, %%mm5 # r7r6r5r4 r3__g7g6 g5g4g3b7 b6b5b4b3 \n\
|
||||
movd 4(%2), %%mm1 # Load 4 Cr __ __ __ __ v3 v2 v1 v0 \n\
|
||||
movq %%mm5, 8(%3) # store pixel 4-7 \n\
|
||||
"
|
||||
|
||||
/*
|
||||
* convert RGB plane to RGB 16 bits,
|
||||
* mm0 -> B, mm1 -> R, mm2 -> G,
|
||||
* mm4 -> GB, mm5 -> AR pixel 4-7,
|
||||
* mm6 -> GB, mm7 -> AR pixel 0-3
|
||||
*/
|
||||
|
||||
#define MMX_UNPACK_16 " \n\
|
||||
# mask unneeded bits off \n\
|
||||
pand mmx_mask_f8, %%mm0 # b7b6b5b4 b3______ b7b6b5b4 b3______ \n\
|
||||
pand mmx_mask_fc, %%mm2 # g7g6g5g4 g3g2____ g7g6g5g4 g3g2____ \n\
|
||||
pand mmx_mask_f8, %%mm1 # r7r6r5r4 r3______ r7r6r5r4 r3______ \n\
|
||||
psrlw $3,%%mm0 # ______b7 b6b5b4b3 ______b7 b6b5b4b3 \n\
|
||||
pxor %%mm4, %%mm4 # zero mm4 \n\
|
||||
movq %%mm0, %%mm5 # Copy B7-B0 \n\
|
||||
movq %%mm2, %%mm7 # Copy G7-G0 \n\
|
||||
\n\
|
||||
# convert rgb24 plane to rgb16 pack for pixel 0-3 \n\
|
||||
punpcklbw %%mm4, %%mm2 # ________ ________ g7g6g5g4 g3g2____ \n\
|
||||
punpcklbw %%mm1, %%mm0 # r7r6r5r4 r3______ ______b7 b6b5b4b3 \n\
|
||||
psllw $3,%%mm2 # ________ __g7g6g5 g4g3g2__ ________ \n\
|
||||
por %%mm2, %%mm0 # r7r6r5r4 r3g7g6g5 g4g3g2b7 b6b5b4b3 \n\
|
||||
movq 8(%0), %%mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
movq %%mm0, (%3) # store pixel 0-3 \n\
|
||||
\n\
|
||||
# convert rgb24 plane to rgb16 pack for pixel 0-3 \n\
|
||||
punpckhbw %%mm4, %%mm7 # ________ ________ g7g6g5g4 g3g2____ \n\
|
||||
punpckhbw %%mm1, %%mm5 # r7r6r5r4 r3______ ______b7 b6b5b4b3 \n\
|
||||
psllw $3,%%mm7 # ________ __g7g6g5 g4g3g2__ ________ \n\
|
||||
movd 4(%1), %%mm0 # Load 4 Cb __ __ __ __ u3 u2 u1 u0 \n\
|
||||
por %%mm7, %%mm5 # r7r6r5r4 r3g7g6g5 g4g3g2b7 b6b5b4b3 \n\
|
||||
movd 4(%2), %%mm1 # Load 4 Cr __ __ __ __ v3 v2 v1 v0 \n\
|
||||
movq %%mm5, 8(%3) # store pixel 4-7 \n\
|
||||
"
|
||||
|
||||
/*
|
||||
* convert RGB plane to RGB packed format,
|
||||
* mm0 -> B, mm1 -> R, mm2 -> G, mm3 -> 0,
|
||||
* mm4 -> GB, mm5 -> AR pixel 4-7,
|
||||
* mm6 -> GB, mm7 -> AR pixel 0-3
|
||||
*/
|
||||
|
||||
#define MMX_UNPACK_32 " \n\
|
||||
pxor %%mm3, %%mm3 # zero mm3 \n\
|
||||
movq %%mm0, %%mm6 # B7 B6 B5 B4 B3 B2 B1 B0 \n\
|
||||
movq %%mm1, %%mm7 # R7 R6 R5 R4 R3 R2 R1 R0 \n\
|
||||
movq %%mm0, %%mm4 # B7 B6 B5 B4 B3 B2 B1 B0 \n\
|
||||
movq %%mm1, %%mm5 # R7 R6 R5 R4 R3 R2 R1 R0 \n\
|
||||
punpcklbw %%mm2, %%mm6 # G3 B3 G2 B2 G1 B1 G0 B0 \n\
|
||||
punpcklbw %%mm3, %%mm7 # 00 R3 00 R2 00 R1 00 R0 \n\
|
||||
punpcklwd %%mm7, %%mm6 # 00 R1 B1 G1 00 R0 B0 G0 \n\
|
||||
movq %%mm6, (%3) # Store ARGB1 ARGB0 \n\
|
||||
movq %%mm0, %%mm6 # B7 B6 B5 B4 B3 B2 B1 B0 \n\
|
||||
punpcklbw %%mm2, %%mm6 # G3 B3 G2 B2 G1 B1 G0 B0 \n\
|
||||
punpckhwd %%mm7, %%mm6 # 00 R3 G3 B3 00 R2 B3 G2 \n\
|
||||
movq %%mm6, 8(%3) # Store ARGB3 ARGB2 \n\
|
||||
punpckhbw %%mm2, %%mm4 # G7 B7 G6 B6 G5 B5 G4 B4 \n\
|
||||
punpckhbw %%mm3, %%mm5 # 00 R7 00 R6 00 R5 00 R4 \n\
|
||||
punpcklwd %%mm5, %%mm4 # 00 R5 B5 G5 00 R4 B4 G4 \n\
|
||||
movq %%mm4, 16(%3) # Store ARGB5 ARGB4 \n\
|
||||
movq %%mm0, %%mm4 # B7 B6 B5 B4 B3 B2 B1 B0 \n\
|
||||
punpckhbw %%mm2, %%mm4 # G7 B7 G6 B6 G5 B5 G4 B4 \n\
|
||||
punpckhwd %%mm5, %%mm4 # 00 R7 G7 B7 00 R6 B6 G6 \n\
|
||||
movq %%mm4, 24(%3) # Store ARGB7 ARGB6 \n\
|
||||
\n\
|
||||
#movd 4(%1), %%mm0 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
#movd 4(%2), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
#pxor %%mm4, %%mm4 # zero mm4 \n\
|
||||
#movq 8(%0), %%mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
"
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* i420_ymga.c : YUV to YUV conversion module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000, 2001 VideoLAN
|
||||
* $Id: i420_ymga.c,v 1.8 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <string.h> /* strerror() */
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/vout.h>
|
||||
|
||||
#define SRC_FOURCC "I420,IYUV,YV12"
|
||||
#define DEST_FOURCC "YMGA"
|
||||
|
||||
/*****************************************************************************
|
||||
* Local and extern prototypes.
|
||||
*****************************************************************************/
|
||||
static int Activate ( vlc_object_t * );
|
||||
static void I420_YMGA ( vout_thread_t *, picture_t *, picture_t * );
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_ymga)
|
||||
set_description( _("conversions from " SRC_FOURCC " to " DEST_FOURCC) );
|
||||
set_capability( "chroma", 80 );
|
||||
#elif defined (MODULE_NAME_IS_chroma_i420_ymga_mmx)
|
||||
set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
|
||||
set_capability( "chroma", 100 );
|
||||
add_requirement( MMX );
|
||||
#endif
|
||||
set_callbacks( Activate, NULL );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* Activate: allocate a chroma function
|
||||
*****************************************************************************
|
||||
* This function allocates and initializes a chroma function
|
||||
*****************************************************************************/
|
||||
static int Activate( vlc_object_t *p_this )
|
||||
{
|
||||
vout_thread_t *p_vout = (vout_thread_t *)p_this;
|
||||
|
||||
if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch( p_vout->render.i_chroma )
|
||||
{
|
||||
case VLC_FOURCC('Y','V','1','2'):
|
||||
case VLC_FOURCC('I','4','2','0'):
|
||||
case VLC_FOURCC('I','Y','U','V'):
|
||||
switch( p_vout->output.i_chroma )
|
||||
{
|
||||
case VLC_FOURCC('Y','M','G','A'):
|
||||
p_vout->chroma.pf_convert = I420_YMGA;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Following functions are local */
|
||||
|
||||
/*****************************************************************************
|
||||
* I420_YMGA: planar YUV 4:2:0 to Matrox's planar/packed YUV 4:2:0
|
||||
*****************************************************************************/
|
||||
static void I420_YMGA( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
u8 *p_uv = p_dest->U_PIXELS;
|
||||
u8 *p_u = p_source->U_PIXELS;
|
||||
u8 *p_v = p_source->V_PIXELS;
|
||||
|
||||
int i_x;
|
||||
|
||||
/* Copy the Y part */
|
||||
p_vout->p_vlc->pf_memcpy( p_dest->Y_PIXELS, p_source->Y_PIXELS,
|
||||
p_dest->p[Y_PLANE].i_pitch * p_dest->p[Y_PLANE].i_lines );
|
||||
|
||||
/* Copy the U:V part */
|
||||
for( i_x = p_dest->p[U_PLANE].i_pitch * p_dest->p[U_PLANE].i_lines / 64;
|
||||
i_x--; )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_ymga)
|
||||
*p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
|
||||
*p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
|
||||
*p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
|
||||
*p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
|
||||
*p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
|
||||
*p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
|
||||
*p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
|
||||
*p_uv++ = *p_u++; *p_uv++ = *p_v++; *p_uv++ = *p_u++; *p_uv++ = *p_v++;
|
||||
#else
|
||||
__asm__( ".align 32 \n\
|
||||
movd (%0), %%mm0 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
movd 4(%0), %%mm2 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
movd 8(%0), %%mm4 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
movd 12(%0), %%mm6 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
movd (%1), %%mm1 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
movd 4(%1), %%mm3 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
movd 8(%1), %%mm5 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
movd 12(%1), %%mm7 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
punpcklbw %%mm1, %%mm0 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
|
||||
punpcklbw %%mm3, %%mm2 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
|
||||
punpcklbw %%mm5, %%mm4 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
|
||||
punpcklbw %%mm7, %%mm6 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
|
||||
movq %%mm0, (%2) # Store CrCb \n\
|
||||
movq %%mm2, 8(%2) # Store CrCb \n\
|
||||
movq %%mm4, 16(%2) # Store CrCb \n\
|
||||
movq %%mm6, 24(%2) # Store CrCb"
|
||||
: : "r" (p_v), "r" (p_u), "r" (p_uv) );
|
||||
|
||||
p_v += 16; p_u += 16; p_uv += 32;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -1,377 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* i420_yuy2.c : YUV to YUV conversion module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000, 2001 VideoLAN
|
||||
* $Id: i420_yuy2.c,v 1.11 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <string.h> /* strerror() */
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/vout.h>
|
||||
|
||||
#include "i420_yuy2.h"
|
||||
|
||||
#define SRC_FOURCC "I420,IYUV,YV12"
|
||||
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_yuy2)
|
||||
# define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
|
||||
#else
|
||||
# define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Local and extern prototypes.
|
||||
*****************************************************************************/
|
||||
static int Activate ( vlc_object_t * );
|
||||
|
||||
static void I420_YUY2 ( vout_thread_t *, picture_t *, picture_t * );
|
||||
static void I420_YVYU ( vout_thread_t *, picture_t *, picture_t * );
|
||||
static void I420_UYVY ( vout_thread_t *, picture_t *, picture_t * );
|
||||
static void I420_IUYV ( vout_thread_t *, picture_t *, picture_t * );
|
||||
static void I420_cyuv ( vout_thread_t *, picture_t *, picture_t * );
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_yuy2)
|
||||
static void I420_Y211 ( vout_thread_t *, picture_t *, picture_t * );
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_NAME_IS_chroma_i420_yuy2_mmx
|
||||
static unsigned long long i_00ffw;
|
||||
static unsigned long long i_80w;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor.
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_yuy2)
|
||||
set_description( _("conversions from " SRC_FOURCC " to " DEST_FOURCC) );
|
||||
set_capability( "chroma", 80 );
|
||||
#elif defined (MODULE_NAME_IS_chroma_i420_yuy2_mmx)
|
||||
set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
|
||||
set_capability( "chroma", 100 );
|
||||
add_requirement( MMX );
|
||||
/* Initialize MMX-specific constants */
|
||||
i_00ffw = 0x00ff00ff00ff00ff;
|
||||
i_80w = 0x0000000080808080;
|
||||
#endif
|
||||
set_callbacks( Activate, NULL );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* Activate: allocate a chroma function
|
||||
*****************************************************************************
|
||||
* This function allocates and initializes a chroma function
|
||||
*****************************************************************************/
|
||||
static int Activate( vlc_object_t *p_this )
|
||||
{
|
||||
vout_thread_t *p_vout = (vout_thread_t *)p_this;
|
||||
|
||||
if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch( p_vout->render.i_chroma )
|
||||
{
|
||||
case VLC_FOURCC('Y','V','1','2'):
|
||||
case VLC_FOURCC('I','4','2','0'):
|
||||
case VLC_FOURCC('I','Y','U','V'):
|
||||
switch( p_vout->output.i_chroma )
|
||||
{
|
||||
case VLC_FOURCC('Y','U','Y','2'):
|
||||
case VLC_FOURCC('Y','U','N','V'):
|
||||
p_vout->chroma.pf_convert = I420_YUY2;
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('Y','V','Y','U'):
|
||||
p_vout->chroma.pf_convert = I420_YVYU;
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('U','Y','V','Y'):
|
||||
case VLC_FOURCC('U','Y','N','V'):
|
||||
case VLC_FOURCC('Y','4','2','2'):
|
||||
p_vout->chroma.pf_convert = I420_UYVY;
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('I','U','Y','V'):
|
||||
p_vout->chroma.pf_convert = I420_IUYV;
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('c','y','u','v'):
|
||||
p_vout->chroma.pf_convert = I420_cyuv;
|
||||
break;
|
||||
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_yuy2)
|
||||
case VLC_FOURCC('Y','2','1','1'):
|
||||
p_vout->chroma.pf_convert = I420_Y211;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Following functions are local */
|
||||
|
||||
/*****************************************************************************
|
||||
* I420_YUY2: planar YUV 4:2:0 to packed YUYV 4:2:2
|
||||
*****************************************************************************/
|
||||
static void I420_YUY2( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
|
||||
u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
|
||||
u8 *p_u = p_source->U_PIXELS;
|
||||
u8 *p_v = p_source->V_PIXELS;
|
||||
|
||||
int i_x, i_y;
|
||||
|
||||
const int i_source_margin = p_source->p->i_pitch
|
||||
- p_source->p->i_visible_pitch;
|
||||
const int i_dest_margin = p_dest->p->i_pitch
|
||||
- p_dest->p->i_visible_pitch;
|
||||
|
||||
for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
|
||||
{
|
||||
p_line1 = p_line2;
|
||||
p_line2 += p_dest->p->i_pitch;
|
||||
|
||||
p_y1 = p_y2;
|
||||
p_y2 += p_source->p[Y_PLANE].i_pitch;
|
||||
|
||||
for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_yuy2)
|
||||
C_YUV420_YUYV( );
|
||||
C_YUV420_YUYV( );
|
||||
C_YUV420_YUYV( );
|
||||
C_YUV420_YUYV( );
|
||||
#else
|
||||
MMX_CALL( MMX_YUV420_YUYV );
|
||||
#endif
|
||||
}
|
||||
|
||||
p_y1 += i_source_margin;
|
||||
p_y2 += i_source_margin;
|
||||
p_line1 += i_dest_margin;
|
||||
p_line2 += i_dest_margin;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I420_YVYU: planar YUV 4:2:0 to packed YVYU 4:2:2
|
||||
*****************************************************************************/
|
||||
static void I420_YVYU( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
|
||||
u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
|
||||
u8 *p_u = p_source->U_PIXELS;
|
||||
u8 *p_v = p_source->V_PIXELS;
|
||||
|
||||
int i_x, i_y;
|
||||
|
||||
const int i_source_margin = p_source->p->i_pitch
|
||||
- p_source->p->i_visible_pitch;
|
||||
const int i_dest_margin = p_dest->p->i_pitch
|
||||
- p_dest->p->i_visible_pitch;
|
||||
|
||||
for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
|
||||
{
|
||||
p_line1 = p_line2;
|
||||
p_line2 += p_dest->p->i_pitch;
|
||||
|
||||
p_y1 = p_y2;
|
||||
p_y2 += p_source->p[Y_PLANE].i_pitch;
|
||||
|
||||
for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_yuy2)
|
||||
C_YUV420_YVYU( );
|
||||
C_YUV420_YVYU( );
|
||||
C_YUV420_YVYU( );
|
||||
C_YUV420_YVYU( );
|
||||
#else
|
||||
MMX_CALL( MMX_YUV420_YVYU );
|
||||
#endif
|
||||
}
|
||||
|
||||
p_y1 += i_source_margin;
|
||||
p_y2 += i_source_margin;
|
||||
p_line1 += i_dest_margin;
|
||||
p_line2 += i_dest_margin;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I420_UYVY: planar YUV 4:2:0 to packed UYVY 4:2:2
|
||||
*****************************************************************************/
|
||||
static void I420_UYVY( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
|
||||
u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
|
||||
u8 *p_u = p_source->U_PIXELS;
|
||||
u8 *p_v = p_source->V_PIXELS;
|
||||
|
||||
int i_x, i_y;
|
||||
|
||||
const int i_source_margin = p_source->p->i_pitch
|
||||
- p_source->p->i_visible_pitch;
|
||||
const int i_dest_margin = p_dest->p->i_pitch
|
||||
- p_dest->p->i_visible_pitch;
|
||||
|
||||
for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
|
||||
{
|
||||
p_line1 = p_line2;
|
||||
p_line2 += p_dest->p->i_pitch;
|
||||
|
||||
p_y1 = p_y2;
|
||||
p_y2 += p_source->p[Y_PLANE].i_pitch;
|
||||
|
||||
for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_yuy2)
|
||||
C_YUV420_UYVY( );
|
||||
C_YUV420_UYVY( );
|
||||
C_YUV420_UYVY( );
|
||||
C_YUV420_UYVY( );
|
||||
#else
|
||||
MMX_CALL( MMX_YUV420_UYVY );
|
||||
#endif
|
||||
}
|
||||
|
||||
p_y1 += i_source_margin;
|
||||
p_y2 += i_source_margin;
|
||||
p_line1 += i_dest_margin;
|
||||
p_line2 += i_dest_margin;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I420_IUYV: planar YUV 4:2:0 to interleaved packed UYVY 4:2:2
|
||||
*****************************************************************************/
|
||||
static void I420_IUYV( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
/* FIXME: TODO ! */
|
||||
msg_Err( p_vout, "I420_IUYV unimplemented, please harass <sam@zoy.org>" );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I420_cyuv: planar YUV 4:2:0 to upside-down packed UYVY 4:2:2
|
||||
*****************************************************************************/
|
||||
static void I420_cyuv( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
u8 *p_line1 = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch
|
||||
+ p_dest->p->i_pitch;
|
||||
u8 *p_line2 = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch;
|
||||
u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
|
||||
u8 *p_u = p_source->U_PIXELS;
|
||||
u8 *p_v = p_source->V_PIXELS;
|
||||
|
||||
int i_x, i_y;
|
||||
|
||||
const int i_source_margin = p_source->p->i_pitch
|
||||
- p_source->p->i_visible_pitch;
|
||||
const int i_dest_margin = p_dest->p->i_pitch
|
||||
- p_dest->p->i_visible_pitch;
|
||||
|
||||
for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
|
||||
{
|
||||
p_line1 -= 3 * p_dest->p->i_pitch;
|
||||
p_line2 -= 3 * p_dest->p->i_pitch;
|
||||
|
||||
p_y1 = p_y2;
|
||||
p_y2 += p_source->p[Y_PLANE].i_pitch;
|
||||
|
||||
for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_yuy2)
|
||||
C_YUV420_UYVY( );
|
||||
C_YUV420_UYVY( );
|
||||
C_YUV420_UYVY( );
|
||||
C_YUV420_UYVY( );
|
||||
#else
|
||||
MMX_CALL( MMX_YUV420_UYVY );
|
||||
#endif
|
||||
}
|
||||
|
||||
p_y1 += i_source_margin;
|
||||
p_y2 += i_source_margin;
|
||||
p_line1 += i_dest_margin;
|
||||
p_line2 += i_dest_margin;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I420_Y211: planar YUV 4:2:0 to packed YUYV 2:1:1
|
||||
*****************************************************************************/
|
||||
#if defined (MODULE_NAME_IS_chroma_i420_yuy2)
|
||||
static void I420_Y211( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
u8 *p_line1, *p_line2 = p_dest->p->p_pixels;
|
||||
u8 *p_y1, *p_y2 = p_source->Y_PIXELS;
|
||||
u8 *p_u = p_source->U_PIXELS;
|
||||
u8 *p_v = p_source->V_PIXELS;
|
||||
|
||||
int i_x, i_y;
|
||||
|
||||
const int i_source_margin = p_source->p->i_pitch
|
||||
- p_source->p->i_visible_pitch;
|
||||
const int i_dest_margin = p_dest->p->i_pitch
|
||||
- p_dest->p->i_visible_pitch;
|
||||
|
||||
for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
|
||||
{
|
||||
p_line1 = p_line2;
|
||||
p_line2 += p_dest->p->i_pitch;
|
||||
|
||||
p_y1 = p_y2;
|
||||
p_y2 += p_source->p[Y_PLANE].i_pitch;
|
||||
|
||||
for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
|
||||
{
|
||||
C_YUV420_Y211( );
|
||||
C_YUV420_Y211( );
|
||||
}
|
||||
|
||||
p_y1 += i_source_margin;
|
||||
p_y2 += i_source_margin;
|
||||
p_line1 += i_dest_margin;
|
||||
p_line2 += i_dest_margin;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,143 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* i420_yuy2.h : YUV to YUV conversion module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000, 2001 VideoLAN
|
||||
* $Id: i420_yuy2.h,v 1.10 2002/06/01 16:45:34 sam Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef MODULE_NAME_IS_chroma_i420_yuy2_mmx
|
||||
|
||||
#define MMX_CALL(MMX_INSTRUCTIONS) \
|
||||
do { \
|
||||
__asm__ __volatile__( \
|
||||
".align 8 \n\t" \
|
||||
MMX_INSTRUCTIONS \
|
||||
: \
|
||||
: "r" (p_line1), "r" (p_line2), "r" (p_y1), "r" (p_y2), \
|
||||
"r" (p_u), "r" (p_v) ); \
|
||||
p_line1 += 16; p_line2 += 16; p_y1 += 8; p_y2 += 8; p_u += 4; p_v += 4; \
|
||||
} while(0); \
|
||||
|
||||
#define MMX_YUV420_YUYV " \n\
|
||||
movq (%2), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
|
||||
movd (%4), %%mm1 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
movd (%5), %%mm2 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
punpcklbw %%mm2, %%mm1 # v3 u3 v2 u2 v1 u1 v0 u0 \n\
|
||||
movq %%mm0, %%mm2 # y7 y6 y5 y4 y3 y2 y1 y0 \n\
|
||||
punpcklbw %%mm1, %%mm2 # v1 y3 u1 y2 v0 y1 u0 y0 \n\
|
||||
movq %%mm2, (%0) # Store low YUYV \n\
|
||||
punpckhbw %%mm1, %%mm0 # v3 y7 u3 y6 v2 y5 u2 y4 \n\
|
||||
movq %%mm0, 8(%0) # Store high YUYV \n\
|
||||
movq (%3), %%mm0 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
movq %%mm0, %%mm2 # Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
punpcklbw %%mm1, %%mm2 # v1 Y3 u1 Y2 v0 Y1 u0 Y0 \n\
|
||||
movq %%mm2, (%1) # Store low YUYV \n\
|
||||
punpckhbw %%mm1, %%mm0 # v3 Y7 u3 Y6 v2 Y5 u2 Y4 \n\
|
||||
movq %%mm0, 8(%1) # Store high YUYV \n\
|
||||
"
|
||||
|
||||
#define MMX_YUV420_YVYU " \n\
|
||||
movq (%2), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
|
||||
movd (%4), %%mm2 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
movd (%5), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
punpcklbw %%mm2, %%mm1 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
|
||||
movq %%mm0, %%mm2 # y7 y6 y5 y4 y3 y2 y1 y0 \n\
|
||||
punpcklbw %%mm1, %%mm2 # u1 y3 v1 y2 u0 y1 v0 y0 \n\
|
||||
movq %%mm2, (%0) # Store low YUYV \n\
|
||||
punpckhbw %%mm1, %%mm0 # u3 y7 v3 y6 u2 y5 v2 y4 \n\
|
||||
movq %%mm0, 8(%0) # Store high YUYV \n\
|
||||
movq (%3), %%mm0 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
movq %%mm0, %%mm2 # Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
punpcklbw %%mm1, %%mm2 # u1 Y3 v1 Y2 u0 Y1 v0 Y0 \n\
|
||||
movq %%mm2, (%1) # Store low YUYV \n\
|
||||
punpckhbw %%mm1, %%mm0 # u3 Y7 v3 Y6 u2 Y5 v2 Y4 \n\
|
||||
movq %%mm0, 8(%1) # Store high YUYV \n\
|
||||
"
|
||||
|
||||
#define MMX_YUV420_UYVY " \n\
|
||||
movq (%2), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
|
||||
movq (%3), %%mm3 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
movd (%4), %%mm2 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
movd (%5), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
punpcklbw %%mm2, %%mm1 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
|
||||
movq %%mm1, %%mm2 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
|
||||
punpcklbw %%mm0, %%mm2 # y3 v1 y2 u1 y1 v0 y0 u0 \n\
|
||||
movq %%mm2, (%0) # Store low UYVY \n\
|
||||
movq %%mm1, %%mm2 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
|
||||
punpckhbw %%mm0, %%mm2 # y3 v1 y2 u1 y1 v0 y0 u0 \n\
|
||||
movq %%mm2, 8(%0) # Store high UYVY \n\
|
||||
movq %%mm1, %%mm2 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
|
||||
punpcklbw %%mm3, %%mm2 # Y3 v1 Y2 u1 Y1 v0 Y0 u0 \n\
|
||||
movq %%mm2, (%1) # Store low UYVY \n\
|
||||
punpckhbw %%mm3, %%mm1 # Y7 v3 Y6 u3 Y5 v2 Y4 u2 \n\
|
||||
movq %%mm1, 8(%1) # Store high UYVY \n\
|
||||
"
|
||||
|
||||
/* FIXME: this code does not work ! Chroma seems to be wrong. */
|
||||
#define MMX_YUV420_Y211 " \n\
|
||||
movq (%2), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
|
||||
movq (%3), %%mm1 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
movd (%4), %%mm2 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
movd (%5), %%mm3 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
pand i_00ffw, %%mm0 # get Y even 00 Y6 00 Y4 00 Y2 00 Y0 \n\
|
||||
packuswb %%mm0, %%mm0 # pack Y y6 y4 y2 y0 y6 y4 y2 y0 \n\
|
||||
pand i_00ffw, %%mm2 # get U even 00 u6 00 u4 00 u2 00 u0 \n\
|
||||
packuswb %%mm2, %%mm2 # pack U 00 00 u2 u0 00 00 u2 u0 \n\
|
||||
pand i_00ffw, %%mm3 # get V even 00 v6 00 v4 00 v2 00 v0 \n\
|
||||
packuswb %%mm3, %%mm3 # pack V 00 00 v2 v0 00 00 v2 v0 \n\
|
||||
punpcklbw %%mm3, %%mm2 # 00 00 00 00 v2 u2 v0 u0 \n\
|
||||
psubsw i_80w, %%mm2 # U,V -= 128 \n\
|
||||
punpcklbw %%mm2, %%mm0 # v2 y6 u2 y4 v0 y2 u0 y0 \n\
|
||||
movq %%mm0, (%0) # Store YUYV \n\
|
||||
pand i_00ffw, %%mm1 # get Y even 00 Y6 00 Y4 00 Y2 00 Y0 \n\
|
||||
packuswb %%mm1, %%mm1 # pack Y Y6 Y4 Y2 Y0 Y6 Y4 Y2 Y0 \n\
|
||||
punpcklbw %%mm2, %%mm1 # v2 Y6 u2 Y4 v0 Y2 u0 Y0 \n\
|
||||
movq %%mm1, (%1) # Store YUYV \n\
|
||||
"
|
||||
|
||||
#else
|
||||
|
||||
#define C_YUV420_YUYV( ) \
|
||||
*(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
|
||||
*(p_line1)++ = *(p_line2)++ = *(p_u)++; \
|
||||
*(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
|
||||
*(p_line1)++ = *(p_line2)++ = *(p_v)++; \
|
||||
|
||||
#define C_YUV420_YVYU( ) \
|
||||
*(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
|
||||
*(p_line1)++ = *(p_line2)++ = *(p_v)++; \
|
||||
*(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
|
||||
*(p_line1)++ = *(p_line2)++ = *(p_u)++; \
|
||||
|
||||
#define C_YUV420_UYVY( ) \
|
||||
*(p_line1)++ = *(p_line2)++ = *(p_u)++; \
|
||||
*(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
|
||||
*(p_line1)++ = *(p_line2)++ = *(p_v)++; \
|
||||
*(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
|
||||
|
||||
#define C_YUV420_Y211( ) \
|
||||
*(p_line1)++ = *(p_y1); ((u16*)p_y1)++; \
|
||||
*(p_line2)++ = *(p_y2); ((u16*)p_y2)++; \
|
||||
*(p_line1)++ = *(p_line2)++ = *(p_u) - 0x80; ((u16*)p_u)++; \
|
||||
*(p_line1)++ = *(p_y1); ((u16*)p_y1)++; \
|
||||
*(p_line2)++ = *(p_y2); ((u16*)p_y2)++; \
|
||||
*(p_line1)++ = *(p_line2)++ = *(p_v) - 0x80; ((u16*)p_v)++; \
|
||||
|
||||
#endif
|
||||
|
|
@ -1,318 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* i422_yuy2.c : YUV to YUV conversion module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000, 2001 VideoLAN
|
||||
* $Id: i422_yuy2.c,v 1.8 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <string.h> /* strerror() */
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/vout.h>
|
||||
|
||||
#include "i422_yuy2.h"
|
||||
|
||||
#define SRC_FOURCC "I422"
|
||||
#if defined (MODULE_NAME_IS_chroma_i422_yuy2)
|
||||
# define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
|
||||
#else
|
||||
# define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Local and extern prototypes.
|
||||
*****************************************************************************/
|
||||
static int Activate ( vlc_object_t * );
|
||||
|
||||
static void I422_YUY2 ( vout_thread_t *, picture_t *, picture_t * );
|
||||
static void I422_YVYU ( vout_thread_t *, picture_t *, picture_t * );
|
||||
static void I422_UYVY ( vout_thread_t *, picture_t *, picture_t * );
|
||||
static void I422_IUYV ( vout_thread_t *, picture_t *, picture_t * );
|
||||
static void I422_cyuv ( vout_thread_t *, picture_t *, picture_t * );
|
||||
#if defined (MODULE_NAME_IS_chroma_i422_yuy2)
|
||||
static void I422_Y211 ( vout_thread_t *, picture_t *, picture_t * );
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
#if defined (MODULE_NAME_IS_chroma_i422_yuy2)
|
||||
set_description( _("conversions from " SRC_FOURCC " to " DEST_FOURCC) );
|
||||
set_capability( "chroma", 80 );
|
||||
#elif defined (MODULE_NAME_IS_chroma_i422_yuy2_mmx)
|
||||
set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
|
||||
set_capability( "chroma", 100 );
|
||||
add_requirement( MMX );
|
||||
#endif
|
||||
set_callbacks( Activate, NULL );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* Activate: allocate a chroma function
|
||||
*****************************************************************************
|
||||
* This function allocates and initializes a chroma function
|
||||
*****************************************************************************/
|
||||
static int Activate( vlc_object_t *p_this )
|
||||
{
|
||||
vout_thread_t *p_vout = (vout_thread_t *)p_this;
|
||||
|
||||
if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch( p_vout->render.i_chroma )
|
||||
{
|
||||
case VLC_FOURCC('I','4','2','2'):
|
||||
switch( p_vout->output.i_chroma )
|
||||
{
|
||||
case VLC_FOURCC('Y','U','Y','2'):
|
||||
case VLC_FOURCC('Y','U','N','V'):
|
||||
p_vout->chroma.pf_convert = I422_YUY2;
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('Y','V','Y','U'):
|
||||
p_vout->chroma.pf_convert = I422_YVYU;
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('U','Y','V','Y'):
|
||||
case VLC_FOURCC('U','Y','N','V'):
|
||||
case VLC_FOURCC('Y','4','2','2'):
|
||||
p_vout->chroma.pf_convert = I422_UYVY;
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('I','U','Y','V'):
|
||||
p_vout->chroma.pf_convert = I422_IUYV;
|
||||
break;
|
||||
|
||||
case VLC_FOURCC('c','y','u','v'):
|
||||
p_vout->chroma.pf_convert = I422_cyuv;
|
||||
break;
|
||||
|
||||
#if defined (MODULE_NAME_IS_chroma_i422_yuy2)
|
||||
case VLC_FOURCC('Y','2','1','1'):
|
||||
p_vout->chroma.pf_convert = I422_Y211;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Following functions are local */
|
||||
|
||||
/*****************************************************************************
|
||||
* I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
|
||||
*****************************************************************************/
|
||||
static void I422_YUY2( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
u8 *p_line = p_dest->p->p_pixels;
|
||||
u8 *p_y = p_source->Y_PIXELS;
|
||||
u8 *p_u = p_source->U_PIXELS;
|
||||
u8 *p_v = p_source->V_PIXELS;
|
||||
|
||||
int i_x, i_y;
|
||||
|
||||
for( i_y = p_vout->render.i_height ; i_y-- ; )
|
||||
{
|
||||
for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i422_yuy2)
|
||||
C_YUV422_YUYV( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_YUYV( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_YUYV( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_YUYV( p_line, p_y, p_u, p_v );
|
||||
#else
|
||||
__asm__( ".align 8" MMX_YUV422_YUYV
|
||||
: : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
|
||||
|
||||
p_line += 8; p_y += 4; p_u += 2; p_v += 2;
|
||||
|
||||
__asm__( ".align 8" MMX_YUV422_YUYV
|
||||
: : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
|
||||
|
||||
p_line += 8; p_y += 4; p_u += 2; p_v += 2;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
|
||||
*****************************************************************************/
|
||||
static void I422_YVYU( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
u8 *p_line = p_dest->p->p_pixels;
|
||||
u8 *p_y = p_source->Y_PIXELS;
|
||||
u8 *p_u = p_source->U_PIXELS;
|
||||
u8 *p_v = p_source->V_PIXELS;
|
||||
|
||||
int i_x, i_y;
|
||||
|
||||
for( i_y = p_vout->render.i_height ; i_y-- ; )
|
||||
{
|
||||
for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i422_yuy2)
|
||||
C_YUV422_YVYU( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_YVYU( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_YVYU( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_YVYU( p_line, p_y, p_u, p_v );
|
||||
#else
|
||||
__asm__( ".align 8" MMX_YUV422_YVYU
|
||||
: : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
|
||||
|
||||
p_line += 8; p_y += 4; p_u += 2; p_v += 2;
|
||||
|
||||
__asm__( ".align 8" MMX_YUV422_YVYU
|
||||
: : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
|
||||
|
||||
p_line += 8; p_y += 4; p_u += 2; p_v += 2;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
|
||||
*****************************************************************************/
|
||||
static void I422_UYVY( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
u8 *p_line = p_dest->p->p_pixels;
|
||||
u8 *p_y = p_source->Y_PIXELS;
|
||||
u8 *p_u = p_source->U_PIXELS;
|
||||
u8 *p_v = p_source->V_PIXELS;
|
||||
|
||||
int i_x, i_y;
|
||||
|
||||
for( i_y = p_vout->render.i_height ; i_y-- ; )
|
||||
{
|
||||
for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
|
||||
{
|
||||
#if defined (MODULE_NAME_IS_chroma_i422_yuy2)
|
||||
C_YUV422_UYVY( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_UYVY( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_UYVY( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_UYVY( p_line, p_y, p_u, p_v );
|
||||
#else
|
||||
__asm__( ".align 8" MMX_YUV422_UYVY
|
||||
: : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
|
||||
|
||||
p_line += 8; p_y += 4; p_u += 2; p_v += 2;
|
||||
|
||||
__asm__( ".align 8" MMX_YUV422_UYVY
|
||||
: : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
|
||||
|
||||
p_line += 8; p_y += 4; p_u += 2; p_v += 2;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
|
||||
*****************************************************************************/
|
||||
static void I422_IUYV( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
/* FIXME: TODO ! */
|
||||
msg_Err( p_vout, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I422_cyuv: planar YUV 4:2:2 to upside-down packed UYVY 4:2:2
|
||||
*****************************************************************************/
|
||||
static void I422_cyuv( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
u8 *p_line = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch;
|
||||
u8 *p_y = p_source->Y_PIXELS;
|
||||
u8 *p_u = p_source->U_PIXELS;
|
||||
u8 *p_v = p_source->V_PIXELS;
|
||||
|
||||
int i_x, i_y;
|
||||
|
||||
for( i_y = p_vout->render.i_height ; i_y-- ; )
|
||||
{
|
||||
for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
|
||||
{
|
||||
p_line -= 2 * p_dest->p->i_pitch;
|
||||
|
||||
#if defined (MODULE_NAME_IS_chroma_i422_yuy2)
|
||||
C_YUV422_UYVY( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_UYVY( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_UYVY( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_UYVY( p_line, p_y, p_u, p_v );
|
||||
#else
|
||||
__asm__( ".align 8" MMX_YUV422_UYVY
|
||||
: : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
|
||||
|
||||
p_line += 8; p_y += 4; p_u += 2; p_v += 2;
|
||||
|
||||
__asm__( ".align 8" MMX_YUV422_UYVY
|
||||
: : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) );
|
||||
|
||||
p_line += 8; p_y += 4; p_u += 2; p_v += 2;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
|
||||
*****************************************************************************/
|
||||
#if defined (MODULE_NAME_IS_chroma_i422_yuy2)
|
||||
static void I422_Y211( vout_thread_t *p_vout, picture_t *p_source,
|
||||
picture_t *p_dest )
|
||||
{
|
||||
u8 *p_line = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch;
|
||||
u8 *p_y = p_source->Y_PIXELS;
|
||||
u8 *p_u = p_source->U_PIXELS;
|
||||
u8 *p_v = p_source->V_PIXELS;
|
||||
|
||||
int i_x, i_y;
|
||||
|
||||
for( i_y = p_vout->render.i_height ; i_y-- ; )
|
||||
{
|
||||
for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
|
||||
{
|
||||
C_YUV422_Y211( p_line, p_y, p_u, p_v );
|
||||
C_YUV422_Y211( p_line, p_y, p_u, p_v );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* i422_yuy2.h : YUV to YUV conversion module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2002 VideoLAN
|
||||
* $Id: i422_yuy2.h,v 1.1 2002/01/04 14:01:34 sam Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef MODULE_NAME_IS_chroma_i422_yuy2_mmx
|
||||
|
||||
#define MMX_YUV422_YUYV " \n\
|
||||
movq (%1), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
|
||||
movd (%2), %%mm1 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
movd (%3), %%mm2 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
punpcklbw %%mm2, %%mm1 # v3 u3 v2 u2 v1 u1 v0 u0 \n\
|
||||
movq %%mm0, %%mm2 # y7 y6 y5 y4 y3 y2 y1 y0 \n\
|
||||
punpcklbw %%mm1, %%mm2 # v1 y3 u1 y2 v0 y1 u0 y0 \n\
|
||||
movq %%mm2, (%0) # Store low YUYV \n\
|
||||
punpckhbw %%mm1, %%mm0 # v3 y7 u3 y6 v2 y5 u2 y4 \n\
|
||||
movq %%mm0, 8(%0) # Store high YUYV \n\
|
||||
"
|
||||
|
||||
#define MMX_YUV422_YVYU " \n\
|
||||
movq (%1), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
|
||||
movd (%2), %%mm2 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
movd (%3), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
punpcklbw %%mm2, %%mm1 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
|
||||
movq %%mm0, %%mm2 # y7 y6 y5 y4 y3 y2 y1 y0 \n\
|
||||
punpcklbw %%mm1, %%mm2 # u1 y3 v1 y2 u0 y1 v0 y0 \n\
|
||||
movq %%mm2, (%0) # Store low YUYV \n\
|
||||
punpckhbw %%mm1, %%mm0 # u3 y7 v3 y6 u2 y5 v2 y4 \n\
|
||||
movq %%mm0, 8(%0) # Store high YUYV \n\
|
||||
"
|
||||
|
||||
#define MMX_YUV422_UYVY " \n\
|
||||
movq (%1), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
|
||||
movd (%2), %%mm2 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
|
||||
movd (%3), %%mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
|
||||
punpcklbw %%mm2, %%mm1 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
|
||||
movq %%mm1, %%mm2 # u3 v3 u2 v2 u1 v1 u0 v0 \n\
|
||||
punpcklbw %%mm0, %%mm2 # y3 v1 y2 u1 y1 v0 y0 u0 \n\
|
||||
movq %%mm2, (%0) # Store low UYVY \n\
|
||||
punpckhbw %%mm0, %%mm1 # y7 v3 y6 u3 y5 v2 y4 u2 \n\
|
||||
movq %%mm1, 8(%0) # Store high UYVY \n\
|
||||
"
|
||||
|
||||
#define MMX_YUV422_Y211 " \n\
|
||||
"
|
||||
|
||||
#else
|
||||
|
||||
#define C_YUV422_YUYV( p_line, p_y, p_u, p_v ) \
|
||||
*(p_line)++ = *(p_y)++; \
|
||||
*(p_line)++ = *(p_u)++; \
|
||||
*(p_line)++ = *(p_y)++; \
|
||||
*(p_line)++ = *(p_v)++; \
|
||||
|
||||
#define C_YUV422_YVYU( p_line, p_y, p_u, p_v ) \
|
||||
*(p_line)++ = *(p_y)++; \
|
||||
*(p_line)++ = *(p_v)++; \
|
||||
*(p_line)++ = *(p_y)++; \
|
||||
*(p_line)++ = *(p_u)++; \
|
||||
|
||||
#define C_YUV422_UYVY( p_line, p_y, p_u, p_v ) \
|
||||
*(p_line)++ = *(p_u)++; \
|
||||
*(p_line)++ = *(p_y)++; \
|
||||
*(p_line)++ = *(p_v)++; \
|
||||
*(p_line)++ = *(p_y)++; \
|
||||
|
||||
#define C_YUV422_Y211( p_line, p_y, p_u, p_v ) \
|
||||
*(p_line)++ = *(p_y); ((u16*)p_y)++; \
|
||||
*(p_line)++ = *(p_u) - 0x80; ((u16*)p_u)++; \
|
||||
*(p_line)++ = *(p_y); ((u16*)p_y)++; \
|
||||
*(p_line)++ = *(p_v) - 0x80; ((u16*)p_v)++; \
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
*.bak
|
||||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1,2 +0,0 @@
|
|||
cinepak_SOURCES = cinepak.c
|
||||
|
|
@ -1,966 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* cinepak.c: cinepak video decoder
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: cinepak.c,v 1.5 2002/07/31 20:56:51 sam 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
|
||||
#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
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_SYS_TIMES_H
|
||||
# include <sys/times.h>
|
||||
#endif
|
||||
|
||||
#include "vdec_ext-plugins.h"
|
||||
#include "cinepak.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* 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 * );
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
set_description( "Cinepak video decoder" );
|
||||
set_capability( "decoder", 70 );
|
||||
set_callbacks( OpenDecoder, NULL );
|
||||
vlc_module_end();
|
||||
|
||||
/*****************************************************************************
|
||||
* OpenDecoder: probe the decoder and return score
|
||||
*****************************************************************************
|
||||
* Tries to launch a decoder and return score so that the interface is able
|
||||
* to chose.
|
||||
*****************************************************************************/
|
||||
static int OpenDecoder( vlc_object_t *p_this )
|
||||
{
|
||||
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
|
||||
|
||||
switch( p_fifo->i_fourcc )
|
||||
{
|
||||
case VLC_FOURCC('c','v','i','d'):
|
||||
case VLC_FOURCC('C','V','I','D'):
|
||||
p_fifo->pf_run = RunDecoder;
|
||||
return VLC_SUCCESS;
|
||||
}
|
||||
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* RunDecoder: this function is called just after the thread is created
|
||||
*****************************************************************************/
|
||||
static int RunDecoder( decoder_fifo_t *p_fifo )
|
||||
{
|
||||
videodec_thread_t *p_vdec;
|
||||
int b_error;
|
||||
|
||||
if ( !(p_vdec = (videodec_thread_t*)malloc( sizeof(videodec_thread_t))) )
|
||||
{
|
||||
msg_Err( p_fifo, "out of memory" );
|
||||
DecoderError( p_fifo );
|
||||
return( -1 );
|
||||
}
|
||||
memset( p_vdec, 0, sizeof( videodec_thread_t ) );
|
||||
|
||||
p_vdec->p_fifo = p_fifo;
|
||||
|
||||
if( InitThread( p_vdec ) != 0 )
|
||||
{
|
||||
DecoderError( p_fifo );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
while( (!p_vdec->p_fifo->b_die) && (!p_vdec->p_fifo->b_error) )
|
||||
{
|
||||
DecodeThread( p_vdec );
|
||||
}
|
||||
|
||||
if( ( b_error = p_vdec->p_fifo->b_error ) )
|
||||
{
|
||||
DecoderError( p_vdec->p_fifo );
|
||||
}
|
||||
|
||||
EndThread( p_vdec );
|
||||
|
||||
if( b_error )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* locales Functions
|
||||
*****************************************************************************/
|
||||
|
||||
static inline u16 GetWBE( u8 *p_buff )
|
||||
{
|
||||
return( (p_buff[0]<<8) + p_buff[1] );
|
||||
}
|
||||
|
||||
static inline u32 GetDWBE( u8 *p_buff )
|
||||
{
|
||||
return( (p_buff[0] << 24) + ( p_buff[1] <<16 ) +
|
||||
( p_buff[2] <<8 ) + p_buff[3] );
|
||||
}
|
||||
|
||||
#define GET2BYTES( p ) \
|
||||
GetWBE( p ); p+= 2;
|
||||
/* FIXME */
|
||||
#define GET3BYTES( p ) \
|
||||
(GetDWBE( p ) >> 8); p+= 3;
|
||||
|
||||
#define GET4BYTES( p ) \
|
||||
GetDWBE( p ); p+= 4;
|
||||
|
||||
#define FREE( p ) \
|
||||
if( p ) free( p )
|
||||
|
||||
/* get the first pes from fifo */
|
||||
static pes_packet_t *__PES_GET( decoder_fifo_t *p_fifo )
|
||||
{
|
||||
pes_packet_t *p_pes;
|
||||
|
||||
vlc_mutex_lock( &p_fifo->data_lock );
|
||||
|
||||
/* if fifo is emty wait */
|
||||
while( !p_fifo->p_first )
|
||||
{
|
||||
if( p_fifo->b_die )
|
||||
{
|
||||
vlc_mutex_unlock( &p_fifo->data_lock );
|
||||
return( NULL );
|
||||
}
|
||||
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
|
||||
}
|
||||
p_pes = p_fifo->p_first;
|
||||
|
||||
vlc_mutex_unlock( &p_fifo->data_lock );
|
||||
|
||||
return( p_pes );
|
||||
}
|
||||
|
||||
/* free the first pes and go to next */
|
||||
static void __PES_NEXT( decoder_fifo_t *p_fifo )
|
||||
{
|
||||
pes_packet_t *p_next;
|
||||
|
||||
vlc_mutex_lock( &p_fifo->data_lock );
|
||||
|
||||
p_next = p_fifo->p_first->p_next;
|
||||
p_fifo->p_first->p_next = NULL;
|
||||
input_DeletePES( p_fifo->p_packets_mgt, p_fifo->p_first );
|
||||
p_fifo->p_first = p_next;
|
||||
p_fifo->i_depth--;
|
||||
|
||||
if( !p_fifo->p_first )
|
||||
{
|
||||
/* No PES in the fifo */
|
||||
/* pp_last no longer valid */
|
||||
p_fifo->pp_last = &p_fifo->p_first;
|
||||
while( !p_fifo->p_first )
|
||||
{
|
||||
vlc_cond_signal( &p_fifo->data_wait );
|
||||
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
|
||||
}
|
||||
}
|
||||
vlc_mutex_unlock( &p_fifo->data_lock );
|
||||
}
|
||||
|
||||
static inline void __GetFrame( videodec_thread_t *p_vdec )
|
||||
{
|
||||
pes_packet_t *p_pes;
|
||||
data_packet_t *p_data;
|
||||
byte_t *p_buffer;
|
||||
|
||||
p_pes = __PES_GET( p_vdec->p_fifo );
|
||||
p_vdec->i_pts = p_pes->i_pts;
|
||||
|
||||
while( ( !p_pes->i_nb_data )||( !p_pes->i_pes_size ) )
|
||||
{
|
||||
__PES_NEXT( p_vdec->p_fifo );
|
||||
p_pes = __PES_GET( p_vdec->p_fifo );
|
||||
}
|
||||
p_vdec->i_framesize = p_pes->i_pes_size;
|
||||
if( p_pes->i_nb_data == 1 )
|
||||
{
|
||||
p_vdec->p_framedata = p_pes->p_first->p_payload_start;
|
||||
return;
|
||||
}
|
||||
/* get a buffer and gather all data packet */
|
||||
p_vdec->p_framedata = p_buffer = malloc( p_pes->i_pes_size );
|
||||
p_data = p_pes->p_first;
|
||||
do
|
||||
{
|
||||
p_vdec->p_fifo->p_vlc->pf_memcpy( p_buffer, p_data->p_payload_start,
|
||||
p_data->p_payload_end - p_data->p_payload_start );
|
||||
p_buffer += p_data->p_payload_end - p_data->p_payload_start;
|
||||
p_data = p_data->p_next;
|
||||
} while( p_data );
|
||||
}
|
||||
|
||||
static inline void __NextFrame( videodec_thread_t *p_vdec )
|
||||
{
|
||||
pes_packet_t *p_pes;
|
||||
|
||||
p_pes = __PES_GET( p_vdec->p_fifo );
|
||||
if( p_pes->i_nb_data != 1 )
|
||||
{
|
||||
free( p_vdec->p_framedata ); /* FIXME keep this buffer */
|
||||
}
|
||||
__PES_NEXT( p_vdec->p_fifo );
|
||||
}
|
||||
|
||||
static int cinepak_CheckVout( vout_thread_t *p_vout,
|
||||
int i_width,
|
||||
int i_height )
|
||||
{
|
||||
if( !p_vout )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if( ( p_vout->render.i_width != i_width )||
|
||||
( p_vout->render.i_height != i_height )||
|
||||
( p_vout->render.i_chroma != VLC_FOURCC('I','4','2','0') )||
|
||||
( p_vout->render.i_aspect != VOUT_ASPECT_FACTOR * i_width / i_height) )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a Vout */
|
||||
|
||||
static vout_thread_t *cinepak_CreateVout( videodec_thread_t *p_vdec,
|
||||
int i_width,
|
||||
int i_height )
|
||||
{
|
||||
vout_thread_t *p_vout;
|
||||
|
||||
if( (!i_width)||(!i_height) )
|
||||
{
|
||||
return( NULL ); /* Can't create a new vout without display size */
|
||||
}
|
||||
|
||||
/* Spawn a video output if there is none. First we look for our children,
|
||||
* then we look for any other vout that might be available. */
|
||||
p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
|
||||
FIND_CHILD );
|
||||
if( !p_vout )
|
||||
{
|
||||
p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
|
||||
FIND_ANYWHERE );
|
||||
}
|
||||
|
||||
if( p_vout )
|
||||
{
|
||||
if( !cinepak_CheckVout( p_vout, i_width, i_height ) )
|
||||
{
|
||||
/* We are not interested in this format, close this vout */
|
||||
vlc_object_detach_all( p_vout );
|
||||
vlc_object_release( p_vout );
|
||||
vout_DestroyThread( p_vout );
|
||||
p_vout = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This video output is cool! Hijack it. */
|
||||
vlc_object_detach_all( p_vout );
|
||||
vlc_object_attach( p_vout, p_vdec->p_fifo );
|
||||
vlc_object_release( p_vout );
|
||||
}
|
||||
}
|
||||
|
||||
if( p_vout == NULL )
|
||||
{
|
||||
msg_Dbg( p_vdec->p_fifo, "no vout present, spawning one" );
|
||||
|
||||
p_vout = vout_CreateThread( p_vdec->p_fifo,
|
||||
i_width,
|
||||
i_height,
|
||||
VLC_FOURCC('I','4','2','0'),
|
||||
VOUT_ASPECT_FACTOR * i_width / i_height );
|
||||
}
|
||||
|
||||
return( p_vout );
|
||||
}
|
||||
|
||||
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;
|
||||
#define SCALEBITS 12
|
||||
#define FIX( x ) ( (int)( (x) * ( 1L << SCALEBITS ) + 0.5 ) )
|
||||
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
i_y[i] = (u8)( *(p_data++) );
|
||||
}
|
||||
if( b_grayscale )
|
||||
{
|
||||
i_u = (s8)( *(p_data++) );
|
||||
i_v = (s8)( *(p_data++) );
|
||||
}
|
||||
else
|
||||
{
|
||||
i_u = 0;
|
||||
i_v = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
| Y | | 1 -0.0655 0.0110 | | CY |
|
||||
| Cb | = | 0 1.1656 -0.0062 | | CU |
|
||||
| Cr | | 0 0.0467 1.4187 | | CV |
|
||||
*/
|
||||
i_uv = ( FIX( -0.0655 ) * i_u + FIX( 0.0110 ) * i_v ) >> SCALEBITS;
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
i_y[i] += i_uv;
|
||||
}
|
||||
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;
|
||||
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
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_v = __MIN( __MAX( 0, i_Cr + 128 ), 255 );
|
||||
|
||||
#undef FIX
|
||||
#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 )
|
||||
{
|
||||
u8 i_index[4];
|
||||
int i,j;
|
||||
|
||||
u8 *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);
|
||||
|
||||
#define PIX_SET_UV( i, p, x, y, v ) \
|
||||
p[(x) + (y)* (p_context->i_stride[i])] = (v);
|
||||
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
i_index[i] = *(p_data++);
|
||||
}
|
||||
|
||||
/* y plane */
|
||||
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_v = p_context->p_pix[2] + p_context->i_stride[2] * (i_y/2) + (i_x/2);
|
||||
|
||||
for( i = 0; i < 2; i++ )
|
||||
{
|
||||
for( j = 0; j < 2; j ++ )
|
||||
{
|
||||
PIX_SET_Y( 2*j + 0, 2*i + 0,
|
||||
p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[0]);
|
||||
PIX_SET_Y( 2*j + 1, 2*i + 0,
|
||||
p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[1]);
|
||||
PIX_SET_Y( 2*j + 0, 2*i + 1,
|
||||
p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[2]);
|
||||
PIX_SET_Y( 2*j + 1, 2*i + 1,
|
||||
p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[3]);
|
||||
|
||||
PIX_SET_UV( 1, p_dst_u, j, i,
|
||||
p_context->codebook_v4[i_strip][i_index[j+2*i]].i_u );
|
||||
PIX_SET_UV( 2, p_dst_v, j, i,
|
||||
p_context->codebook_v4[i_strip][i_index[j+2*i]].i_v );
|
||||
}
|
||||
}
|
||||
#undef PIX_SET_Y
|
||||
#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 )
|
||||
{
|
||||
u8 i_index;
|
||||
int i,j;
|
||||
|
||||
u8 *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);
|
||||
|
||||
#define PIX_SET_UV( i,p, x, y, v ) \
|
||||
p[(x) + (y)* (p_context->i_stride[i])] = (v);
|
||||
|
||||
i_index = *(p_data++);
|
||||
|
||||
/* y plane */
|
||||
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_v = p_context->p_pix[2] + p_context->i_stride[2] * (i_y/2) + (i_x/2);
|
||||
|
||||
for( i = 0; i < 2; i++ )
|
||||
{
|
||||
for( j = 0; j < 2; j ++ )
|
||||
{
|
||||
PIX_SET_Y( 2*j + 0, 2*i + 0,
|
||||
p_context->codebook_v1[i_strip][i_index].i_y[0] );
|
||||
PIX_SET_Y( 2*j + 1, 2*i + 0,
|
||||
p_context->codebook_v1[i_strip][i_index].i_y[1] );
|
||||
PIX_SET_Y( 2*j + 0, 2*i + 1,
|
||||
p_context->codebook_v1[i_strip][i_index].i_y[2] );
|
||||
PIX_SET_Y( 2*j + 1, 2*i + 1,
|
||||
p_context->codebook_v1[i_strip][i_index].i_y[3] );
|
||||
|
||||
PIX_SET_UV( 1,p_dst_u, j, i,
|
||||
p_context->codebook_v1[i_strip][i_index].i_u );
|
||||
PIX_SET_UV( 2,p_dst_v, j, i,
|
||||
p_context->codebook_v1[i_strip][i_index].i_v );
|
||||
}
|
||||
}
|
||||
|
||||
#undef PIX_SET_Y
|
||||
#undef PIX_SET_UV
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* The function that decode one frame
|
||||
*****************************************************************************/
|
||||
int cinepak_decode_frame( cinepak_context_t *p_context,
|
||||
int i_length, u8 *p_data )
|
||||
{
|
||||
int i_strip;
|
||||
|
||||
int i_frame_flags;
|
||||
int i_frame_size;
|
||||
int i_width, i_height;
|
||||
int i_frame_strips;
|
||||
int i_index;
|
||||
int i_strip_x1 =0, i_strip_y1=0;
|
||||
int i_strip_x2 =0, i_strip_y2=0;
|
||||
|
||||
if( i_length <= 10 )
|
||||
{
|
||||
/* Broken header or no data */
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* get header */
|
||||
i_frame_flags = *(p_data++);
|
||||
i_frame_size = GET3BYTES( p_data );
|
||||
i_width = GET2BYTES( p_data );
|
||||
i_height = GET2BYTES( p_data );
|
||||
i_frame_strips = GET2BYTES( p_data );
|
||||
|
||||
/* Check if we have a picture buffer with good size */
|
||||
if( ( p_context->i_width != i_width )||
|
||||
( p_context->i_height != i_height ) )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
FREE( p_context->p_pix[i] );
|
||||
}
|
||||
|
||||
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[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[1] = p_context->i_lines[2] =
|
||||
p_context->i_lines[0] /2;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
p_context->p_pix[i] = malloc( p_context->i_stride[i] *
|
||||
p_context->i_lines[i] );
|
||||
}
|
||||
}
|
||||
|
||||
if( i_frame_size != i_length )
|
||||
{
|
||||
i_length = __MIN( i_length, i_frame_size );
|
||||
}
|
||||
i_length -= 10;
|
||||
|
||||
if( i_frame_strips >= CINEPAK_MAXSTRIP )
|
||||
{
|
||||
i_frame_strips = CINEPAK_MAXSTRIP;
|
||||
}
|
||||
|
||||
/* Now decode each strip */
|
||||
|
||||
for( i_strip = 0; i_strip < i_frame_strips; i_strip++ )
|
||||
{
|
||||
int i_strip_id;
|
||||
int i_strip_size;
|
||||
|
||||
if( i_length <= 12 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
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; */
|
||||
i_strip_y1 = i_strip_y2 + GET2BYTES( p_data );
|
||||
i_strip_x1 = GET2BYTES( p_data );
|
||||
i_strip_y2 = i_strip_y2 + GET2BYTES( p_data );
|
||||
i_strip_x2 = GET2BYTES( p_data );
|
||||
|
||||
i_length -= i_strip_size;
|
||||
|
||||
i_strip_size -= 12;
|
||||
/* init codebook , if needed */
|
||||
if( ( i_strip > 0 )&&( !(i_frame_flags&0x01) ) )
|
||||
{
|
||||
memcpy( &p_context->codebook_v1[i_strip],
|
||||
&p_context->codebook_v1[i_strip-1],
|
||||
sizeof(cinepak_codebook_t[256] ) );
|
||||
|
||||
memcpy( &p_context->codebook_v4[i_strip],
|
||||
&p_context->codebook_v4[i_strip-1],
|
||||
sizeof(cinepak_codebook_t[256] ) );
|
||||
}
|
||||
|
||||
/* Now parse all chunk in this strip */
|
||||
while( i_strip_size > 0 )
|
||||
{
|
||||
cinepak_codebook_t (*p_codebook)[CINEPAK_MAXSTRIP][256];
|
||||
int i_mode;
|
||||
|
||||
int i_chunk_id;
|
||||
int i_chunk_size;
|
||||
u32 i_vector_flags;
|
||||
int i_count;
|
||||
int i;
|
||||
int i_x, i_y; /* (0,0) begin in fact at (x1,y1) ... */
|
||||
|
||||
i_chunk_id = GET2BYTES( p_data );
|
||||
i_chunk_size = GET2BYTES( p_data );
|
||||
i_chunk_size = __MIN( i_chunk_size, i_strip_size );
|
||||
i_strip_size -= i_chunk_size;
|
||||
|
||||
i_chunk_size -= 4;
|
||||
|
||||
i_x = 0;
|
||||
i_y = 0;
|
||||
if( i_chunk_size < 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch( i_chunk_id )
|
||||
{
|
||||
case( 0x2000 ): /* 12bits v4 Intra*/
|
||||
case( 0x2200 ): /* 12bits v1 Intra*/
|
||||
case( 0x2400 ): /* 8bits v4 Intra*/
|
||||
case( 0x2600 ): /* 8bits v1 Intra */
|
||||
i_mode = ( ( i_chunk_id&0x0400 ) == 0 );
|
||||
p_codebook = ( i_chunk_id&0x0200 ) ?
|
||||
&p_context->codebook_v1 :
|
||||
&p_context->codebook_v4;
|
||||
|
||||
i_count = __MIN( i_chunk_size / ( i_mode ? 6 : 4 ), 256 );
|
||||
|
||||
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++ )
|
||||
{
|
||||
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 );
|
||||
|
||||
p_data += i_mode ? 6 : 4;
|
||||
i_chunk_size -= i_mode ? 6 : 4;
|
||||
}
|
||||
i_index++;
|
||||
i_vector_flags <<= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case( 0x3000 ): /* load image Intra */
|
||||
while( (i_chunk_size >= 4 )&&(i_y<i_strip_y2-i_strip_y1) )
|
||||
{
|
||||
i_vector_flags = GET4BYTES( p_data );
|
||||
i_chunk_size -= 4;
|
||||
i_strip_size -= 4;
|
||||
i_length -= 4;
|
||||
|
||||
for( i = 0; i < 32; i++ )
|
||||
{
|
||||
if( ( i_y >= i_strip_y2 - i_strip_y1)||
|
||||
( i_chunk_size<=0) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if( i_vector_flags&0x80000000UL )
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
i_vector_flags <<= 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;
|
||||
if( i_x >= i_strip_x2 - i_strip_x1 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
int i_status;
|
||||
|
||||
int i_plane;
|
||||
u8 *p_dst, *p_src;
|
||||
picture_t *p_pic; /* videolan picture */
|
||||
|
||||
__GetFrame( p_vdec );
|
||||
|
||||
i_status = cinepak_decode_frame( p_vdec->p_context,
|
||||
p_vdec->i_framesize,
|
||||
p_vdec->p_framedata );
|
||||
__NextFrame( p_vdec );
|
||||
|
||||
if( i_status < 0 )
|
||||
{
|
||||
msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
|
||||
p_vdec->i_framesize );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check our vout */
|
||||
if( !cinepak_CheckVout( p_vdec->p_vout,
|
||||
p_vdec->p_context->i_width,
|
||||
p_vdec->p_context->i_height ) )
|
||||
{
|
||||
p_vdec->p_vout =
|
||||
cinepak_CreateVout( p_vdec,
|
||||
p_vdec->p_context->i_width,
|
||||
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 = 1; /* 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 );
|
||||
|
||||
if( p_vdec->p_vout != NULL )
|
||||
{
|
||||
/* We are about to die. Reattach video output to p_vlc. */
|
||||
vlc_object_detach( p_vdec->p_vout, p_vdec->p_fifo );
|
||||
vlc_object_attach( p_vdec->p_vout, p_vdec->p_fifo->p_vlc );
|
||||
}
|
||||
|
||||
free( p_vdec );
|
||||
}
|
||||
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* cinepak.h: Cinepak video decoder
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: cinepak.h,v 1.2 2002/07/21 18:47:22 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;
|
||||
int i_framesize;
|
||||
byte_t *p_framedata;
|
||||
} videodec_thread_t;
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1 +0,0 @@
|
|||
directx_SOURCES = directx.c vout_directx.c vout_events.c aout_directx.c
|
|
@ -1,761 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* aout_directx.c: Windows DirectX audio output method
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: aout_directx.c,v 1.26 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Gildas Bazin <gbazin@netcourrier.com>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <fcntl.h> /* open(), O_WRONLY */
|
||||
#include <string.h> /* strerror() */
|
||||
|
||||
#include <stdlib.h> /* calloc(), malloc(), free() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/aout.h>
|
||||
|
||||
#include <mmsystem.h>
|
||||
#include <dsound.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* DirectSound GUIDs.
|
||||
* Defining them here allows us to get rid of the dxguid library during
|
||||
* the linking stage.
|
||||
*****************************************************************************/
|
||||
#include <initguid.h>
|
||||
DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
|
||||
|
||||
/*****************************************************************************
|
||||
* notification_thread_t: DirectX event thread
|
||||
*****************************************************************************/
|
||||
typedef struct notification_thread_t
|
||||
{
|
||||
VLC_COMMON_MEMBERS
|
||||
|
||||
aout_thread_t * p_aout;
|
||||
DSBPOSITIONNOTIFY p_events[2]; /* play notification events */
|
||||
|
||||
} notification_thread_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* aout_sys_t: directx audio output method descriptor
|
||||
*****************************************************************************
|
||||
* This structure is part of the audio output thread descriptor.
|
||||
* It describes the direct sound specific properties of an audio device.
|
||||
*****************************************************************************/
|
||||
|
||||
struct aout_sys_t
|
||||
{
|
||||
LPDIRECTSOUND p_dsobject; /* main Direct Sound object */
|
||||
|
||||
LPDIRECTSOUNDBUFFER p_dsbuffer_primary; /* the actual sound card buffer
|
||||
(not used directly) */
|
||||
|
||||
LPDIRECTSOUNDBUFFER p_dsbuffer; /* the sound buffer we use (direct sound
|
||||
* takes care of mixing all the
|
||||
* secondary buffers into the primary) */
|
||||
|
||||
LPDIRECTSOUNDNOTIFY p_dsnotify; /* the position notify interface */
|
||||
|
||||
HINSTANCE hdsound_dll; /* handle of the opened dsound dll */
|
||||
|
||||
long l_buffer_size; /* secondary sound buffer size */
|
||||
long l_write_position; /* next write position for the buffer */
|
||||
|
||||
volatile vlc_bool_t b_buffer_underflown; /* buffer underflow detection */
|
||||
volatile long l_data_played_from_beginning; /* for underflow detection */
|
||||
volatile long l_data_written_from_beginning; /* for underflow detection */
|
||||
|
||||
vlc_mutex_t buffer_lock; /* audio buffer lock */
|
||||
|
||||
notification_thread_t * p_notif; /* DirectSoundThread id */
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes.
|
||||
*****************************************************************************/
|
||||
static int SetFormat ( aout_thread_t * );
|
||||
static int GetBufInfo ( aout_thread_t *, int );
|
||||
static void Play ( aout_thread_t *, byte_t *, int );
|
||||
|
||||
/* local functions */
|
||||
static int DirectxCreateSecondaryBuffer ( aout_thread_t * );
|
||||
static void DirectxDestroySecondaryBuffer( aout_thread_t * );
|
||||
static int DirectxInitDSound ( aout_thread_t * );
|
||||
static void DirectSoundThread ( notification_thread_t * );
|
||||
|
||||
/*****************************************************************************
|
||||
* OpenAudio: open the audio device
|
||||
*****************************************************************************
|
||||
* This function opens and setups Direct Sound.
|
||||
*****************************************************************************/
|
||||
int E_(OpenAudio) ( vlc_object_t *p_this )
|
||||
{
|
||||
aout_thread_t * p_aout = (aout_thread_t *)p_this;
|
||||
HRESULT dsresult;
|
||||
DSBUFFERDESC dsbuffer_desc;
|
||||
|
||||
msg_Dbg( p_aout, "Open" );
|
||||
|
||||
/* Allocate structure */
|
||||
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
|
||||
|
||||
if( p_aout->p_sys == NULL )
|
||||
{
|
||||
msg_Err( p_aout, "out of memory" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* Initialize some variables */
|
||||
p_aout->p_sys->p_dsobject = NULL;
|
||||
p_aout->p_sys->p_dsbuffer_primary = NULL;
|
||||
p_aout->p_sys->p_dsbuffer = NULL;
|
||||
p_aout->p_sys->p_dsnotify = NULL;
|
||||
p_aout->p_sys->l_data_written_from_beginning = 0;
|
||||
p_aout->p_sys->l_data_played_from_beginning = 0;
|
||||
vlc_mutex_init( p_aout, &p_aout->p_sys->buffer_lock );
|
||||
|
||||
p_aout->pf_setformat = SetFormat;
|
||||
p_aout->pf_getbufinfo = GetBufInfo;
|
||||
p_aout->pf_play = Play;
|
||||
|
||||
/* Initialise DirectSound */
|
||||
if( DirectxInitDSound( p_aout ) )
|
||||
{
|
||||
msg_Warn( p_aout, "cannot initialize DirectSound" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* Obtain (not create) Direct Sound primary buffer */
|
||||
memset( &dsbuffer_desc, 0, sizeof(DSBUFFERDESC) );
|
||||
dsbuffer_desc.dwSize = sizeof(DSBUFFERDESC);
|
||||
dsbuffer_desc.dwFlags = DSBCAPS_PRIMARYBUFFER;
|
||||
msg_Warn( p_aout, "create direct sound primary buffer" );
|
||||
dsresult = IDirectSound_CreateSoundBuffer(p_aout->p_sys->p_dsobject,
|
||||
&dsbuffer_desc,
|
||||
&p_aout->p_sys->p_dsbuffer_primary,
|
||||
NULL);
|
||||
if( dsresult != DS_OK )
|
||||
{
|
||||
msg_Warn( p_aout, "cannot create direct sound primary buffer" );
|
||||
IDirectSound_Release( p_aout->p_sys->p_dsobject );
|
||||
p_aout->p_sys->p_dsobject = NULL;
|
||||
p_aout->p_sys->p_dsbuffer_primary = NULL;
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
||||
/* Now we need to setup DirectSound play notification */
|
||||
|
||||
/* first we need to create the notification events */
|
||||
p_aout->p_sys->p_notif->p_events[0].hEventNotify =
|
||||
CreateEvent( NULL, FALSE, FALSE, NULL );
|
||||
p_aout->p_sys->p_notif->p_events[1].hEventNotify =
|
||||
CreateEvent( NULL, FALSE, FALSE, NULL );
|
||||
|
||||
/* then launch the notification thread */
|
||||
msg_Dbg( p_aout, "creating DirectSoundThread" );
|
||||
p_aout->p_sys->p_notif =
|
||||
vlc_object_create( p_aout, sizeof(notification_thread_t) );
|
||||
p_aout->p_sys->p_notif->p_aout = p_aout;
|
||||
if( vlc_thread_create( p_aout->p_sys->p_notif,
|
||||
"DirectSound Notification Thread", DirectSoundThread, 1 ) )
|
||||
{
|
||||
msg_Err( p_aout, "cannot create DirectSoundThread" );
|
||||
/* Let's go on anyway */
|
||||
}
|
||||
|
||||
vlc_object_attach( p_aout->p_sys->p_notif, p_aout );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* SetFormat: reset the audio device and sets its format
|
||||
*****************************************************************************
|
||||
* This functions set a new audio format.
|
||||
* For this we need to close the current secondary buffer and create another
|
||||
* one with the desired format.
|
||||
*****************************************************************************/
|
||||
static int SetFormat( aout_thread_t *p_aout )
|
||||
{
|
||||
HRESULT dsresult;
|
||||
WAVEFORMATEX *p_waveformat;
|
||||
unsigned long i_size_struct;
|
||||
|
||||
msg_Dbg( p_aout, "SetFormat" );
|
||||
|
||||
/* Set the format of Direct Sound primary buffer */
|
||||
|
||||
/* first we need to know the current format */
|
||||
dsresult = IDirectSoundBuffer_GetFormat( p_aout->p_sys->p_dsbuffer_primary,
|
||||
NULL, 0, &i_size_struct );
|
||||
if( dsresult == DS_OK )
|
||||
{
|
||||
p_waveformat = malloc( i_size_struct );
|
||||
dsresult = IDirectSoundBuffer_GetFormat(
|
||||
p_aout->p_sys->p_dsbuffer_primary,
|
||||
p_waveformat, i_size_struct,
|
||||
NULL );
|
||||
}
|
||||
|
||||
if( dsresult == DS_OK )
|
||||
{
|
||||
/* Here we'll change the format */
|
||||
p_waveformat->nChannels = 2;
|
||||
p_waveformat->nSamplesPerSec = (p_aout->i_rate < 44100) ? 44100
|
||||
: p_aout->i_rate;
|
||||
p_waveformat->wBitsPerSample = 16;
|
||||
p_waveformat->nBlockAlign = p_waveformat->wBitsPerSample / 8 *
|
||||
p_waveformat->nChannels;
|
||||
p_waveformat->nAvgBytesPerSec = p_waveformat->nSamplesPerSec *
|
||||
p_waveformat->nBlockAlign;
|
||||
|
||||
dsresult = IDirectSoundBuffer_SetFormat(
|
||||
p_aout->p_sys->p_dsbuffer_primary,
|
||||
p_waveformat );
|
||||
}
|
||||
else msg_Warn( p_aout, "cannot get primary buffer format" );
|
||||
|
||||
if( dsresult != DS_OK )
|
||||
msg_Warn( p_aout, "cannot set primary buffer format" );
|
||||
|
||||
|
||||
/* Now we need to take care of Direct Sound secondary buffer */
|
||||
|
||||
vlc_mutex_lock( &p_aout->p_sys->buffer_lock );
|
||||
|
||||
/* first release the current secondary buffer */
|
||||
DirectxDestroySecondaryBuffer( p_aout );
|
||||
|
||||
/* then create a new secondary buffer */
|
||||
if( DirectxCreateSecondaryBuffer( p_aout ) )
|
||||
{
|
||||
msg_Warn( p_aout, "cannot create buffer" );
|
||||
vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* GetBufInfo: buffer status query
|
||||
*****************************************************************************
|
||||
* returns the number of bytes in the audio buffer that have not yet been
|
||||
* sent to the sound device.
|
||||
*****************************************************************************/
|
||||
static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
|
||||
{
|
||||
long l_play_position, l_notused, l_result;
|
||||
HRESULT dsresult;
|
||||
|
||||
if( p_aout->p_sys->b_buffer_underflown )
|
||||
{
|
||||
msg_Warn( p_aout, "GetBufInfo underflow" );
|
||||
return( i_buffer_limit );
|
||||
}
|
||||
|
||||
dsresult = IDirectSoundBuffer_GetCurrentPosition(p_aout->p_sys->p_dsbuffer,
|
||||
&l_play_position, &l_notused);
|
||||
if( dsresult != DS_OK )
|
||||
{
|
||||
msg_Warn( p_aout, "GetBufInfo cannot get current pos" );
|
||||
return( i_buffer_limit );
|
||||
}
|
||||
|
||||
l_result = (p_aout->p_sys->l_write_position >= l_play_position) ?
|
||||
(p_aout->p_sys->l_write_position - l_play_position)
|
||||
: (p_aout->p_sys->l_buffer_size - l_play_position
|
||||
+ p_aout->p_sys->l_write_position);
|
||||
|
||||
#if 0
|
||||
msg_Dbg( p_aout, "GetBufInfo: %i", i_result);
|
||||
#endif
|
||||
return l_result;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Play: play a sound buffer
|
||||
*****************************************************************************
|
||||
* This function writes a buffer of i_length bytes
|
||||
* Don't forget that DirectSound buffers are circular buffers.
|
||||
*****************************************************************************/
|
||||
static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
|
||||
{
|
||||
VOID *p_write_position, *p_start_buffer;
|
||||
long l_bytes1, l_bytes2, l_play_position;
|
||||
HRESULT dsresult;
|
||||
|
||||
/* protect buffer access (because of DirectSoundThread) */
|
||||
vlc_mutex_lock( &p_aout->p_sys->buffer_lock );
|
||||
|
||||
if( p_aout->p_sys->b_buffer_underflown )
|
||||
{
|
||||
/* there has been an underflow so we need to play the new sample
|
||||
* as soon as possible. This is why we query the play position */
|
||||
dsresult = IDirectSoundBuffer_GetCurrentPosition(
|
||||
p_aout->p_sys->p_dsbuffer,
|
||||
&l_play_position,
|
||||
&p_aout->p_sys->l_write_position );
|
||||
if( dsresult != DS_OK )
|
||||
{
|
||||
msg_Warn( p_aout, "cannot get buffer position" );
|
||||
p_aout->p_sys->l_write_position = 0;
|
||||
}
|
||||
|
||||
msg_Warn( p_aout, "Play underflow" );
|
||||
/* reinitialise the underflow detection counters */
|
||||
p_aout->p_sys->b_buffer_underflown = 0;
|
||||
p_aout->p_sys->l_data_written_from_beginning = 0;
|
||||
|
||||
#define WRITE_P p_aout->p_sys->l_write_position
|
||||
#define PLAY_P l_play_position
|
||||
#define BUF_SIZE p_aout->p_sys->l_buffer_size
|
||||
p_aout->p_sys->l_data_played_from_beginning = -(WRITE_P %(BUF_SIZE/2));
|
||||
if( PLAY_P < BUF_SIZE/2 && WRITE_P > BUF_SIZE/2 )
|
||||
{
|
||||
p_aout->p_sys->l_data_played_from_beginning -= (BUF_SIZE/2);
|
||||
}
|
||||
if( PLAY_P > BUF_SIZE/2 && WRITE_P < BUF_SIZE/2 )
|
||||
{
|
||||
p_aout->p_sys->l_data_played_from_beginning -= (BUF_SIZE/2);
|
||||
}
|
||||
#undef WRITE_P
|
||||
#undef PLAY_P
|
||||
#undef BUF_SIZE
|
||||
}
|
||||
|
||||
/* Before copying anything, we have to lock the buffer */
|
||||
dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
|
||||
p_aout->p_sys->l_write_position, /* Offset of lock start */
|
||||
i_size, /* Number of bytes to lock */
|
||||
&p_write_position, /* Address of lock start */
|
||||
&l_bytes1, /* Count of bytes locked before wrap around */
|
||||
&p_start_buffer, /* Buffer adress (if wrap around) */
|
||||
&l_bytes2, /* Count of bytes after wrap around */
|
||||
0); /* Flags */
|
||||
if( dsresult == DSERR_BUFFERLOST )
|
||||
{
|
||||
IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
|
||||
dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
|
||||
p_aout->p_sys->l_write_position,
|
||||
i_size,
|
||||
&p_write_position,
|
||||
&l_bytes1,
|
||||
&p_start_buffer,
|
||||
&l_bytes2,
|
||||
0);
|
||||
|
||||
}
|
||||
if( dsresult != DS_OK )
|
||||
{
|
||||
msg_Warn( p_aout, "Play cannot lock buffer" );
|
||||
vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now do the actual memcpy (two memcpy because the buffer is circular) */
|
||||
memcpy( p_write_position, buffer, l_bytes1 );
|
||||
if( p_start_buffer != NULL )
|
||||
{
|
||||
memcpy( p_start_buffer, buffer + l_bytes1, l_bytes2 );
|
||||
}
|
||||
|
||||
/* Now the data has been copied, unlock the buffer */
|
||||
IDirectSoundBuffer_Unlock( p_aout->p_sys->p_dsbuffer,
|
||||
p_write_position, l_bytes1, p_start_buffer, l_bytes2 );
|
||||
|
||||
/* Update the write position index of the buffer*/
|
||||
p_aout->p_sys->l_write_position += i_size;
|
||||
p_aout->p_sys->l_write_position %= p_aout->p_sys->l_buffer_size;
|
||||
p_aout->p_sys->l_data_written_from_beginning += i_size;
|
||||
|
||||
vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
|
||||
|
||||
/* The play function has no effect if the buffer is already playing */
|
||||
dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer,
|
||||
0, /* Unused */
|
||||
0, /* Unused */
|
||||
DSBPLAY_LOOPING ); /* Flags */
|
||||
if( dsresult == DSERR_BUFFERLOST )
|
||||
{
|
||||
IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
|
||||
dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer,
|
||||
0, /* Unused */
|
||||
0, /* Unused */
|
||||
DSBPLAY_LOOPING ); /* Flags */
|
||||
}
|
||||
if( dsresult != DS_OK )
|
||||
{
|
||||
msg_Warn( p_aout, "Play cannot play buffer" );
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* CloseAudio: close the audio device
|
||||
*****************************************************************************/
|
||||
void E_(CloseAudio) ( vlc_object_t *p_this )
|
||||
{
|
||||
aout_thread_t * p_aout = (aout_thread_t *)p_this;
|
||||
|
||||
msg_Dbg( p_aout, "Close" );
|
||||
|
||||
/* kill the position notification thread, if any */
|
||||
vlc_object_detach_all( p_aout->p_sys->p_notif );
|
||||
if( p_aout->p_sys->p_notif->b_thread )
|
||||
{
|
||||
p_aout->p_sys->p_notif->b_die = 1;
|
||||
vlc_thread_join( p_aout->p_sys->p_notif );
|
||||
}
|
||||
vlc_object_destroy( p_aout->p_sys->p_notif );
|
||||
|
||||
/* release the secondary buffer */
|
||||
DirectxDestroySecondaryBuffer( p_aout );
|
||||
|
||||
/* then release the primary buffer */
|
||||
if( p_aout->p_sys->p_dsbuffer_primary != NULL )
|
||||
{
|
||||
IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer_primary );
|
||||
p_aout->p_sys->p_dsbuffer_primary = NULL;
|
||||
}
|
||||
|
||||
/* finally release the DirectSound object */
|
||||
if( p_aout->p_sys->p_dsobject != NULL )
|
||||
{
|
||||
IDirectSound_Release( p_aout->p_sys->p_dsobject );
|
||||
p_aout->p_sys->p_dsobject = NULL;
|
||||
}
|
||||
|
||||
/* free DSOUND.DLL */
|
||||
if( p_aout->p_sys->hdsound_dll != NULL )
|
||||
{
|
||||
FreeLibrary( p_aout->p_sys->hdsound_dll );
|
||||
p_aout->p_sys->hdsound_dll = NULL;
|
||||
}
|
||||
|
||||
/* Close the Output. */
|
||||
if ( p_aout->p_sys != NULL )
|
||||
{
|
||||
free( p_aout->p_sys );
|
||||
p_aout->p_sys = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* DirectxInitDSound
|
||||
*****************************************************************************
|
||||
*****************************************************************************/
|
||||
static int DirectxInitDSound( aout_thread_t *p_aout )
|
||||
{
|
||||
HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
|
||||
|
||||
p_aout->p_sys->hdsound_dll = LoadLibrary("DSOUND.DLL");
|
||||
if( p_aout->p_sys->hdsound_dll == NULL )
|
||||
{
|
||||
msg_Warn( p_aout, "cannot open DSOUND.DLL" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
OurDirectSoundCreate = (void *)GetProcAddress( p_aout->p_sys->hdsound_dll,
|
||||
"DirectSoundCreate" );
|
||||
|
||||
if( OurDirectSoundCreate == NULL )
|
||||
{
|
||||
msg_Warn( p_aout, "GetProcAddress FAILED" );
|
||||
FreeLibrary( p_aout->p_sys->hdsound_dll );
|
||||
p_aout->p_sys->hdsound_dll = NULL;
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* Create the direct sound object */
|
||||
if( OurDirectSoundCreate(NULL, &p_aout->p_sys->p_dsobject, NULL) != DS_OK )
|
||||
{
|
||||
msg_Warn( p_aout, "cannot create a direct sound device" );
|
||||
p_aout->p_sys->p_dsobject = NULL;
|
||||
FreeLibrary( p_aout->p_sys->hdsound_dll );
|
||||
p_aout->p_sys->hdsound_dll = NULL;
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* Set DirectSound Cooperative level, ie what control we want over Windows
|
||||
* sound device. In our case, DSSCL_EXCLUSIVE means that we can modify the
|
||||
* settings of the primary buffer, but also that only the sound of our
|
||||
* application will be hearable when it will have the focus.
|
||||
* !!! (this is not really working as intended yet because to set the
|
||||
* cooperative level you need the window handle of your application, and
|
||||
* I don't know of any easy way to get it. Especially since we might play
|
||||
* sound without any video, and so what window handle should we use ???
|
||||
* The hack for now is to use the Desktop window handle - it seems to be
|
||||
* working */
|
||||
if( IDirectSound_SetCooperativeLevel(p_aout->p_sys->p_dsobject,
|
||||
GetDesktopWindow(),
|
||||
DSSCL_EXCLUSIVE) )
|
||||
{
|
||||
msg_Warn( p_aout, "cannot set direct sound cooperative level" );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* DirectxCreateSecondaryBuffer
|
||||
*****************************************************************************
|
||||
* This function creates the buffer we'll use to play audio.
|
||||
* In DirectSound there are two kinds of buffers:
|
||||
* - the primary buffer: which is the actual buffer that the soundcard plays
|
||||
* - the secondary buffer(s): these buffers are the one actually used by
|
||||
* applications and DirectSound takes care of mixing them into the primary.
|
||||
*
|
||||
* Once you create a secondary buffer, you cannot change its format anymore so
|
||||
* you have to release the current and create another one.
|
||||
*****************************************************************************/
|
||||
static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout )
|
||||
{
|
||||
WAVEFORMATEX waveformat;
|
||||
DSBUFFERDESC dsbdesc;
|
||||
DSBCAPS dsbcaps;
|
||||
|
||||
/* First set the buffer format */
|
||||
memset(&waveformat, 0, sizeof(WAVEFORMATEX));
|
||||
waveformat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
waveformat.nChannels = p_aout->i_channels;
|
||||
waveformat.nSamplesPerSec = p_aout->i_rate;
|
||||
waveformat.wBitsPerSample = 16;
|
||||
waveformat.nBlockAlign = waveformat.wBitsPerSample / 8 *
|
||||
waveformat.nChannels;
|
||||
waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec *
|
||||
waveformat.nBlockAlign;
|
||||
|
||||
/* Then fill in the descriptor */
|
||||
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
|
||||
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
|
||||
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */
|
||||
| DSBCAPS_CTRLPOSITIONNOTIFY /* We need notification */
|
||||
| DSBCAPS_GLOBALFOCUS; /* Allows background playing */
|
||||
dsbdesc.dwBufferBytes = waveformat.nAvgBytesPerSec * 2; /* 2 sec buffer */
|
||||
dsbdesc.lpwfxFormat = &waveformat;
|
||||
|
||||
if( IDirectSound_CreateSoundBuffer( p_aout->p_sys->p_dsobject,
|
||||
&dsbdesc,
|
||||
&p_aout->p_sys->p_dsbuffer,
|
||||
NULL) != DS_OK )
|
||||
{
|
||||
msg_Warn( p_aout, "cannot create direct sound secondary buffer" );
|
||||
p_aout->p_sys->p_dsbuffer = NULL;
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* backup the size of the secondary sound buffer */
|
||||
memset(&dsbcaps, 0, sizeof(DSBCAPS));
|
||||
dsbcaps.dwSize = sizeof(DSBCAPS);
|
||||
IDirectSoundBuffer_GetCaps( p_aout->p_sys->p_dsbuffer, &dsbcaps );
|
||||
p_aout->p_sys->l_buffer_size = dsbcaps.dwBufferBytes;
|
||||
p_aout->p_sys->l_write_position = 0;
|
||||
|
||||
msg_Dbg( p_aout, "DirectxCreateSecondaryBuffer: %li",
|
||||
p_aout->p_sys->l_buffer_size );
|
||||
|
||||
/* Now the secondary buffer is created, we need to setup its position
|
||||
* notification */
|
||||
p_aout->p_sys->p_notif->p_events[0].dwOffset = 0; /* notif position */
|
||||
p_aout->p_sys->p_notif->p_events[1].dwOffset = dsbcaps.dwBufferBytes / 2;
|
||||
|
||||
/* Get the IDirectSoundNotify interface */
|
||||
if FAILED( IDirectSoundBuffer_QueryInterface( p_aout->p_sys->p_dsbuffer,
|
||||
&IID_IDirectSoundNotify,
|
||||
(LPVOID *)&p_aout->p_sys->p_dsnotify ) )
|
||||
{
|
||||
msg_Warn( p_aout, "cannot get Notify interface" );
|
||||
/* Go on anyway */
|
||||
p_aout->p_sys->p_dsnotify = NULL;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if FAILED( IDirectSoundNotify_SetNotificationPositions(
|
||||
p_aout->p_sys->p_dsnotify,
|
||||
2,
|
||||
p_aout->p_sys->p_notif->p_events ) )
|
||||
{
|
||||
msg_Warn( p_aout, "cannot set position Notification" );
|
||||
/* Go on anyway */
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* DirectxCreateSecondaryBuffer
|
||||
*****************************************************************************
|
||||
* This function destroy the secondary buffer.
|
||||
*****************************************************************************/
|
||||
static void DirectxDestroySecondaryBuffer( aout_thread_t *p_aout )
|
||||
{
|
||||
/* make sure the buffer isn't playing */
|
||||
if( p_aout->p_sys->p_dsbuffer != NULL )
|
||||
{
|
||||
IDirectSoundBuffer_Stop( p_aout->p_sys->p_dsbuffer );
|
||||
}
|
||||
|
||||
if( p_aout->p_sys->p_dsnotify != NULL )
|
||||
{
|
||||
IDirectSoundNotify_Release( p_aout->p_sys->p_dsnotify );
|
||||
p_aout->p_sys->p_dsnotify = NULL;
|
||||
}
|
||||
|
||||
if( p_aout->p_sys->p_dsbuffer != NULL )
|
||||
{
|
||||
IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer );
|
||||
p_aout->p_sys->p_dsbuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* DirectSoundThread: this thread will capture play notification events.
|
||||
*****************************************************************************
|
||||
* As Direct Sound uses circular buffers, we need to use event notification to
|
||||
* manage them.
|
||||
* Using event notification implies blocking the thread until the event is
|
||||
* signaled so we really need to run this in a separate thread.
|
||||
*****************************************************************************/
|
||||
static void DirectSoundThread( notification_thread_t *p_notif )
|
||||
{
|
||||
HANDLE notification_events[2];
|
||||
VOID *p_write_position, *p_start_buffer;
|
||||
long l_bytes1, l_bytes2;
|
||||
HRESULT dsresult;
|
||||
long l_buffer_size, l_play_position, l_data_in_buffer;
|
||||
|
||||
aout_thread_t *p_aout = p_notif->p_aout;
|
||||
|
||||
#define P_EVENTS p_aout->p_sys->p_notif->p_events
|
||||
notification_events[0] = P_EVENTS[0].hEventNotify;
|
||||
notification_events[1] = P_EVENTS[1].hEventNotify;
|
||||
|
||||
/* Tell the main thread that we are ready */
|
||||
vlc_thread_ready( p_notif );
|
||||
|
||||
/* this thread must be high-priority */
|
||||
if( !SetThreadPriority( GetCurrentThread(),
|
||||
THREAD_PRIORITY_ABOVE_NORMAL ) )
|
||||
{
|
||||
msg_Warn( p_notif, "DirectSoundThread could not renice itself" );
|
||||
}
|
||||
|
||||
msg_Dbg( p_notif, "DirectSoundThread ready" );
|
||||
|
||||
while( !p_notif->b_die )
|
||||
{
|
||||
/* wait for the position notification */
|
||||
l_play_position = WaitForMultipleObjects( 2, notification_events,
|
||||
0, INFINITE );
|
||||
vlc_mutex_lock( &p_aout->p_sys->buffer_lock );
|
||||
|
||||
if( p_notif->b_die )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* check for buffer underflow (bodge for wrap around) */
|
||||
l_buffer_size = p_aout->p_sys->l_buffer_size;
|
||||
l_play_position = (l_play_position - WAIT_OBJECT_0) * l_buffer_size/2;
|
||||
p_aout->p_sys->l_data_played_from_beginning += (l_buffer_size/2);
|
||||
l_data_in_buffer = p_aout->p_sys->l_data_written_from_beginning -
|
||||
p_aout->p_sys->l_data_played_from_beginning;
|
||||
|
||||
/* detect wrap-around */
|
||||
if( l_data_in_buffer < (-l_buffer_size/2) )
|
||||
{
|
||||
msg_Dbg( p_notif, "DirectSoundThread wrap around: %li",
|
||||
l_data_in_buffer );
|
||||
l_data_in_buffer += l_buffer_size;
|
||||
}
|
||||
|
||||
/* detect underflow */
|
||||
if( l_data_in_buffer <= 0 )
|
||||
{
|
||||
msg_Warn( p_notif,
|
||||
"DirectSoundThread underflow: %li", l_data_in_buffer );
|
||||
p_aout->p_sys->b_buffer_underflown = 1;
|
||||
p_aout->p_sys->l_write_position =
|
||||
(l_play_position + l_buffer_size/2) % l_buffer_size;
|
||||
l_data_in_buffer = l_buffer_size / 2;
|
||||
p_aout->p_sys->l_data_played_from_beginning -= (l_buffer_size/2);
|
||||
}
|
||||
|
||||
|
||||
/* Clear the data which has already been played */
|
||||
|
||||
/* Before copying anything, we have to lock the buffer */
|
||||
dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
|
||||
p_aout->p_sys->l_write_position, /* Offset of lock start */
|
||||
l_buffer_size - l_data_in_buffer, /* Number of bytes */
|
||||
&p_write_position, /* Address of lock start */
|
||||
&l_bytes1, /* Count of bytes locked before wrap around */
|
||||
&p_start_buffer, /* Buffer adress (if wrap around) */
|
||||
&l_bytes2, /* Count of bytes after wrap around */
|
||||
0); /* Flags */
|
||||
if( dsresult == DSERR_BUFFERLOST )
|
||||
{
|
||||
IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
|
||||
dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
|
||||
p_aout->p_sys->l_write_position,
|
||||
l_buffer_size - l_data_in_buffer,
|
||||
&p_write_position,
|
||||
&l_bytes1,
|
||||
&p_start_buffer,
|
||||
&l_bytes2,
|
||||
0);
|
||||
}
|
||||
if( dsresult != DS_OK )
|
||||
{
|
||||
msg_Warn( p_notif, "Play cannot lock buffer" );
|
||||
vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now do the actual memcpy (two because the buffer is circular) */
|
||||
memset( p_write_position, 0, l_bytes1 );
|
||||
if( p_start_buffer != NULL )
|
||||
{
|
||||
memset( p_start_buffer, 0, l_bytes2 );
|
||||
}
|
||||
|
||||
/* Now the data has been copied, unlock the buffer */
|
||||
IDirectSoundBuffer_Unlock( p_aout->p_sys->p_dsbuffer,
|
||||
p_write_position, l_bytes1, p_start_buffer, l_bytes2 );
|
||||
|
||||
vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
|
||||
|
||||
}
|
||||
|
||||
/* free the events */
|
||||
CloseHandle( notification_events[0] );
|
||||
CloseHandle( notification_events[1] );
|
||||
|
||||
msg_Dbg( p_notif, "DirectSoundThread exiting" );
|
||||
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* directx.c : Windows DirectX plugin for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: directx.c,v 1.13 2002/07/31 22:37:28 sam Exp $
|
||||
*
|
||||
* Authors: Gildas Bazin <gbazin@netcourrier.com>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
#include <string.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* External prototypes
|
||||
*****************************************************************************/
|
||||
int E_(OpenVideo) ( vlc_object_t * );
|
||||
void E_(CloseVideo) ( vlc_object_t * );
|
||||
|
||||
int E_(OpenAudio) ( vlc_object_t * );
|
||||
void E_(CloseAudio) ( vlc_object_t * );
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
#define HW_YUV_TEXT N_("use hardware YUV->RGB conversions")
|
||||
#define HW_YUV_LONGTEXT N_( \
|
||||
"Try to use hardware acceleration for YUV->RGB conversions. " \
|
||||
"This option doesn't have any effect when using overlays." )
|
||||
#define SYSMEM_TEXT N_("use video buffers in system memory")
|
||||
#define SYSMEM_LONGTEXT N_( \
|
||||
"Create video buffers in system memory instead of video memory. This " \
|
||||
"isn't recommended as usually using video memory allows to benefit from " \
|
||||
"more hardware acceleration (like rescaling or YUV->RGB conversions). " \
|
||||
"This option doesn't have any effect when using overlays." )
|
||||
|
||||
vlc_module_begin();
|
||||
add_category_hint( N_("Video"), NULL );
|
||||
add_bool( "directx-hw-yuv", 1, NULL, HW_YUV_TEXT, HW_YUV_LONGTEXT );
|
||||
add_bool( "directx-use-sysmem", 0, NULL, SYSMEM_TEXT, SYSMEM_LONGTEXT );
|
||||
set_description( _("DirectX extension module") );
|
||||
add_submodule();
|
||||
set_capability( "video output", 150 );
|
||||
set_callbacks( E_(OpenVideo), E_(CloseVideo) );
|
||||
add_submodule();
|
||||
set_capability( "audio output", 150 );
|
||||
set_callbacks( E_(OpenAudio), E_(CloseAudio) );
|
||||
vlc_module_end();
|
||||
|
||||
#if 0 /* FIXME */
|
||||
/* check if we registered a window class because we need to
|
||||
* unregister it */
|
||||
WNDCLASS wndclass;
|
||||
if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) )
|
||||
UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,112 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* vout_directx.h: Windows DirectX video output header file
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1998, 1999, 2000 VideoLAN
|
||||
* $Id: vout_directx.h,v 1.11 2002/07/30 17:14:33 gbazin Exp $
|
||||
*
|
||||
* Authors: Gildas Bazin <gbazin@netcourrier.com>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* event_thread_t: DirectX event thread
|
||||
*****************************************************************************/
|
||||
typedef struct event_thread_t
|
||||
{
|
||||
VLC_COMMON_MEMBERS
|
||||
|
||||
vout_thread_t * p_vout;
|
||||
|
||||
} event_thread_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* vout_sys_t: video output DirectX method descriptor
|
||||
*****************************************************************************
|
||||
* This structure is part of the video output thread descriptor.
|
||||
* It describes the DirectX specific properties of an output thread.
|
||||
*****************************************************************************/
|
||||
struct vout_sys_t
|
||||
{
|
||||
LPDIRECTDRAW2 p_ddobject; /* DirectDraw object */
|
||||
LPDIRECTDRAWSURFACE2 p_display; /* Display device */
|
||||
LPDIRECTDRAWSURFACE2 p_current_surface; /* surface currently displayed */
|
||||
LPDIRECTDRAWCLIPPER p_clipper; /* clipper used for blitting */
|
||||
HINSTANCE hddraw_dll; /* handle of the opened ddraw dll */
|
||||
HBRUSH hbrush; /* window backgound brush (color) */
|
||||
HWND hwnd; /* Handle of the main window */
|
||||
|
||||
vlc_bool_t b_using_overlay; /* Are we using an overlay surface */
|
||||
vlc_bool_t b_use_sysmem; /* Should we use system memory for surfaces */
|
||||
vlc_bool_t b_hw_yuv; /* Should we use hardware YUV->RGB conversions */
|
||||
|
||||
/* size of the display */
|
||||
RECT rect_display;
|
||||
int i_display_depth;
|
||||
|
||||
/* Window position and size */
|
||||
int i_window_x;
|
||||
int i_window_y;
|
||||
int i_window_width;
|
||||
int i_window_height;
|
||||
|
||||
/* Coordinates of src and dest images (used when blitting to display) */
|
||||
RECT rect_src;
|
||||
RECT rect_src_clipped;
|
||||
RECT rect_dest;
|
||||
RECT rect_dest_clipped;
|
||||
|
||||
/* DDraw capabilities */
|
||||
int b_caps_overlay_clipping;
|
||||
|
||||
int i_rgb_colorkey; /* colorkey in RGB used by the overlay */
|
||||
int i_colorkey; /* colorkey used by the overlay */
|
||||
|
||||
volatile u16 i_changes; /* changes made to the video display */
|
||||
|
||||
/* Mouse */
|
||||
volatile vlc_bool_t b_cursor_hidden;
|
||||
volatile mtime_t i_lastmoved;
|
||||
|
||||
event_thread_t * p_event;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* picture_sys_t: direct buffer method descriptor
|
||||
*****************************************************************************
|
||||
* This structure is part of the picture descriptor, it describes the
|
||||
* DirectX specific properties of a direct buffer.
|
||||
*****************************************************************************/
|
||||
struct picture_sys_t
|
||||
{
|
||||
LPDIRECTDRAWSURFACE2 p_surface;
|
||||
DDSURFACEDESC ddsd;
|
||||
LPDIRECTDRAWSURFACE2 p_front_surface;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Prototypes from vout_directx.c
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Prototypes from vout_events.c
|
||||
*****************************************************************************/
|
||||
void DirectXEventThread ( event_thread_t *p_event );
|
||||
void DirectXUpdateOverlay( vout_thread_t *p_vout );
|
||||
|
||||
/*****************************************************************************
|
||||
* Constants
|
||||
*****************************************************************************/
|
||||
#define WM_VLC_HIDE_MOUSE WM_APP
|
|
@ -1,580 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* vout_events.c: Windows DirectX video output events handler
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: vout_events.c,v 1.25 2002/07/30 17:14:33 gbazin Exp $
|
||||
*
|
||||
* Authors: Gildas Bazin <gbazin@netcourrier.com>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble: This file contains the functions related to the creation of
|
||||
* a window and the handling of its messages (events).
|
||||
*****************************************************************************/
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <stdlib.h> /* free() */
|
||||
#include <string.h> /* strerror() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/intf.h>
|
||||
#include <vlc/vout.h>
|
||||
|
||||
#include "netutils.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
#include "vout_directx.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes.
|
||||
*****************************************************************************/
|
||||
static int DirectXCreateWindow( vout_thread_t *p_vout );
|
||||
static void DirectXCloseWindow ( vout_thread_t *p_vout );
|
||||
static void DirectXUpdateRects( vout_thread_t *p_vout );
|
||||
static long FAR PASCAL DirectXEventProc ( HWND hwnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam );
|
||||
|
||||
/*****************************************************************************
|
||||
* DirectXEventThread: Create video window & handle its messages
|
||||
*****************************************************************************
|
||||
* This function creates a video window and then enters an infinite loop
|
||||
* that handles the messages sent to that window.
|
||||
* The main goal of this thread is to isolate the Win32 PeekMessage function
|
||||
* because this one can block for a long time.
|
||||
*****************************************************************************/
|
||||
void DirectXEventThread( event_thread_t *p_event )
|
||||
{
|
||||
MSG msg;
|
||||
POINT old_mouse_pos;
|
||||
|
||||
/* Initialisation */
|
||||
|
||||
/* Create a window for the video */
|
||||
/* Creating a window under Windows also initializes the thread's event
|
||||
* message qeue */
|
||||
if( DirectXCreateWindow( p_event->p_vout ) )
|
||||
{
|
||||
msg_Err( p_event, "out of memory" );
|
||||
p_event->b_dead = 1;
|
||||
}
|
||||
|
||||
/* signal the creation of the window */
|
||||
vlc_thread_ready( p_event );
|
||||
|
||||
/* Main loop */
|
||||
/* GetMessage will sleep if there's no message in the queue */
|
||||
while( !p_event->b_die
|
||||
&& GetMessage( &msg, p_event->p_vout->p_sys->hwnd, 0, 0 ) )
|
||||
{
|
||||
/* Check if we are asked to exit */
|
||||
if( p_event->b_die )
|
||||
break;
|
||||
|
||||
switch( msg.message )
|
||||
{
|
||||
|
||||
case WM_NCMOUSEMOVE:
|
||||
case WM_MOUSEMOVE:
|
||||
if( (abs(GET_X_LPARAM(msg.lParam) - old_mouse_pos.x) > 2 ||
|
||||
(abs(GET_Y_LPARAM(msg.lParam) - old_mouse_pos.y)) > 2 ) )
|
||||
{
|
||||
GetCursorPos( &old_mouse_pos );
|
||||
p_event->p_vout->p_sys->i_lastmoved = mdate();
|
||||
|
||||
if( p_event->p_vout->p_sys->b_cursor_hidden )
|
||||
{
|
||||
p_event->p_vout->p_sys->b_cursor_hidden = 0;
|
||||
ShowCursor( TRUE );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_VLC_HIDE_MOUSE:
|
||||
GetCursorPos( &old_mouse_pos );
|
||||
ShowCursor( FALSE );
|
||||
break;
|
||||
|
||||
case WM_RBUTTONUP:
|
||||
{
|
||||
intf_thread_t *p_intf;
|
||||
p_intf = vlc_object_find( p_event, VLC_OBJECT_INTF,
|
||||
FIND_ANYWHERE );
|
||||
if( p_intf )
|
||||
{
|
||||
p_intf->b_menu_change = 1;
|
||||
vlc_object_release( p_intf );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDBLCLK:
|
||||
p_event->p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
/* the key events are first processed here. The next
|
||||
* message processed by this main message loop will be the
|
||||
* char translation of the key event */
|
||||
msg_Dbg( p_event, "WM_KEYDOWN" );
|
||||
switch( msg.wParam )
|
||||
{
|
||||
case VK_ESCAPE:
|
||||
/* exit application */
|
||||
p_event->p_vlc->b_die = 1;
|
||||
break;
|
||||
|
||||
case VK_F1: network_ChannelJoin( p_event, 1 ); break;
|
||||
case VK_F2: network_ChannelJoin( p_event, 2 ); break;
|
||||
case VK_F3: network_ChannelJoin( p_event, 3 ); break;
|
||||
case VK_F4: network_ChannelJoin( p_event, 4 ); break;
|
||||
case VK_F5: network_ChannelJoin( p_event, 5 ); break;
|
||||
case VK_F6: network_ChannelJoin( p_event, 6 ); break;
|
||||
case VK_F7: network_ChannelJoin( p_event, 7 ); break;
|
||||
case VK_F8: network_ChannelJoin( p_event, 8 ); break;
|
||||
case VK_F9: network_ChannelJoin( p_event, 9 ); break;
|
||||
case VK_F10: network_ChannelJoin( p_event, 10 ); break;
|
||||
case VK_F11: network_ChannelJoin( p_event, 11 ); break;
|
||||
case VK_F12: network_ChannelJoin( p_event, 12 ); break;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
break;
|
||||
|
||||
case WM_CHAR:
|
||||
switch( msg.wParam )
|
||||
{
|
||||
case 'q':
|
||||
case 'Q':
|
||||
/* exit application */
|
||||
p_event->p_vlc->b_die = 1;
|
||||
break;
|
||||
|
||||
case 'f': /* switch to fullscreen */
|
||||
case 'F':
|
||||
p_event->p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
|
||||
break;
|
||||
|
||||
case 'c': /* toggle grayscale */
|
||||
case 'C':
|
||||
p_event->p_vout->b_grayscale = ! p_event->p_vout->b_grayscale;
|
||||
p_event->p_vout->p_sys->i_changes |= VOUT_GRAYSCALE_CHANGE;
|
||||
break;
|
||||
|
||||
case 'i': /* toggle info */
|
||||
case 'I':
|
||||
p_event->p_vout->b_info = ! p_event->p_vout->b_info;
|
||||
p_event->p_vout->p_sys->i_changes |= VOUT_INFO_CHANGE;
|
||||
break;
|
||||
|
||||
case 's': /* toggle scaling */
|
||||
case 'S':
|
||||
p_event->p_vout->b_scale = ! p_event->p_vout->b_scale;
|
||||
p_event->p_vout->p_sys->i_changes |= VOUT_SCALE_CHANGE;
|
||||
break;
|
||||
|
||||
case ' ': /* toggle interface */
|
||||
p_event->p_vout->b_interface = ! p_event->p_vout->b_interface;
|
||||
p_event->p_vout->p_sys->i_changes |= VOUT_INTF_CHANGE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* Messages we don't handle directly are dispatched to the
|
||||
* window procedure */
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
break;
|
||||
|
||||
} /* End Switch */
|
||||
|
||||
} /* End Main loop */
|
||||
|
||||
if( msg.message == WM_QUIT )
|
||||
{
|
||||
msg_Warn( p_event, "WM_QUIT... should not happen!!" );
|
||||
p_event->p_vout->p_sys->hwnd = NULL; /* Window already destroyed */
|
||||
}
|
||||
|
||||
msg_Dbg( p_event, "DirectXEventThread Terminating" );
|
||||
|
||||
/* clear the changes formerly signaled */
|
||||
p_event->p_vout->p_sys->i_changes = 0;
|
||||
|
||||
DirectXCloseWindow( p_event->p_vout );
|
||||
}
|
||||
|
||||
|
||||
/* following functions are local */
|
||||
|
||||
/*****************************************************************************
|
||||
* DirectXCreateWindow: create a window for the video.
|
||||
*****************************************************************************
|
||||
* Before creating a direct draw surface, we need to create a window in which
|
||||
* the video will be displayed. This window will also allow us to capture the
|
||||
* events.
|
||||
*****************************************************************************/
|
||||
static int DirectXCreateWindow( vout_thread_t *p_vout )
|
||||
{
|
||||
HINSTANCE hInstance;
|
||||
WNDCLASSEX wc; /* window class components */
|
||||
RECT rect_window;
|
||||
COLORREF colorkey;
|
||||
HDC hdc;
|
||||
HICON vlc_icon = NULL;
|
||||
char vlc_path[_MAX_PATH+1];
|
||||
|
||||
msg_Dbg( p_vout, "DirectXCreateWindow" );
|
||||
|
||||
/* get this module's instance */
|
||||
hInstance = GetModuleHandle(NULL);
|
||||
|
||||
/* Create a BRUSH that will be used by Windows to paint the window
|
||||
* background.
|
||||
* This window background is important for us as it will be used by the
|
||||
* graphics card to display the overlay.
|
||||
* This is why we carefully choose the color for this background, the goal
|
||||
* being to choose a color which isn't complete black but nearly. We
|
||||
* obviously don't want to use black as a colorkey for the overlay because
|
||||
* black is one of the most used color and thus would give us undesirable
|
||||
* effects */
|
||||
/* the first step is to find the colorkey we want to use. The difficulty
|
||||
* comes from the potential dithering (depends on the display depth)
|
||||
* because we need to know the real RGB value of the chosen colorkey */
|
||||
hdc = GetDC( NULL );
|
||||
for( colorkey = 5; colorkey < 0xFF /*all shades of red*/; colorkey++ )
|
||||
{
|
||||
if( colorkey == GetNearestColor( hdc, colorkey ) )
|
||||
break;
|
||||
}
|
||||
msg_Dbg( p_vout, "background color: %i", colorkey );
|
||||
|
||||
/* create the actual brush */
|
||||
p_vout->p_sys->hbrush = CreateSolidBrush(colorkey);
|
||||
p_vout->p_sys->i_rgb_colorkey = (int)colorkey;
|
||||
|
||||
/* Get the current size of the display and its colour depth */
|
||||
p_vout->p_sys->rect_display.right = GetDeviceCaps( hdc, HORZRES );
|
||||
p_vout->p_sys->rect_display.bottom = GetDeviceCaps( hdc, VERTRES );
|
||||
p_vout->p_sys->i_display_depth = GetDeviceCaps( hdc, BITSPIXEL );
|
||||
msg_Dbg( p_vout, "screen dimensions %ix%i colour depth %i",
|
||||
p_vout->p_sys->rect_display.right,
|
||||
p_vout->p_sys->rect_display.bottom,
|
||||
p_vout->p_sys->i_display_depth );
|
||||
|
||||
ReleaseDC( NULL, hdc );
|
||||
|
||||
/* Get the Icon from the main app */
|
||||
vlc_icon = NULL;
|
||||
if( GetModuleFileName( NULL, vlc_path, _MAX_PATH ) )
|
||||
{
|
||||
vlc_icon = ExtractIcon( hInstance, vlc_path, 0 );
|
||||
}
|
||||
|
||||
|
||||
/* fill in the window class structure */
|
||||
wc.cbSize = sizeof(WNDCLASSEX);
|
||||
wc.style = CS_DBLCLKS; /* style: dbl click */
|
||||
wc.lpfnWndProc = (WNDPROC)DirectXEventProc; /* event handler */
|
||||
wc.cbClsExtra = 0; /* no extra class data */
|
||||
wc.cbWndExtra = 0; /* no extra window data */
|
||||
wc.hInstance = hInstance; /* instance */
|
||||
wc.hIcon = vlc_icon; /* load the vlc icon */
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* load a default cursor */
|
||||
wc.hbrBackground = p_vout->p_sys->hbrush; /* background color */
|
||||
wc.lpszMenuName = NULL; /* no menu */
|
||||
wc.lpszClassName = "VLC DirectX"; /* use a special class */
|
||||
wc.hIconSm = vlc_icon; /* load the vlc icon */
|
||||
|
||||
/* register the window class */
|
||||
if (!RegisterClassEx(&wc))
|
||||
{
|
||||
WNDCLASS wndclass;
|
||||
|
||||
/* free window background brush */
|
||||
if( p_vout->p_sys->hbrush )
|
||||
{
|
||||
DeleteObject( p_vout->p_sys->hbrush );
|
||||
p_vout->p_sys->hbrush = NULL;
|
||||
}
|
||||
|
||||
if( vlc_icon )
|
||||
DestroyIcon( vlc_icon );
|
||||
|
||||
/* Check why it failed. If it's because one already exists then fine */
|
||||
if( !GetClassInfo( hInstance, "VLC DirectX", &wndclass ) )
|
||||
{
|
||||
msg_Err( p_vout, "DirectXCreateWindow RegisterClass FAILED" );
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* when you create a window you give the dimensions you wish it to have.
|
||||
* Unfortunatly these dimensions will include the borders and title bar.
|
||||
* We use the following function to find out the size of the window
|
||||
* corresponding to the useable surface we want */
|
||||
rect_window.top = 10;
|
||||
rect_window.left = 10;
|
||||
rect_window.right = rect_window.left + p_vout->p_sys->i_window_width;
|
||||
rect_window.bottom = rect_window.top + p_vout->p_sys->i_window_height;
|
||||
AdjustWindowRect( &rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0 );
|
||||
|
||||
/* create the window */
|
||||
p_vout->p_sys->hwnd = CreateWindow("VLC DirectX",/* name of window class */
|
||||
VOUT_TITLE " (DirectX Output)", /* window title bar text */
|
||||
WS_OVERLAPPEDWINDOW
|
||||
| WS_SIZEBOX, /* window style */
|
||||
CW_USEDEFAULT, /* default X coordinate */
|
||||
0, /* default Y coordinate */
|
||||
rect_window.right - rect_window.left, /* window width */
|
||||
rect_window.bottom - rect_window.top, /* window height */
|
||||
NULL, /* no parent window */
|
||||
NULL, /* no menu in this window */
|
||||
hInstance, /* handle of this program instance */
|
||||
NULL); /* no additional arguments */
|
||||
|
||||
if (p_vout->p_sys->hwnd == NULL) {
|
||||
msg_Warn( p_vout, "DirectXCreateWindow create window FAILED" );
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* store a p_vout pointer into the window local storage (for later use
|
||||
* in DirectXEventProc).
|
||||
* We need to use SetWindowLongPtr when it is available in mingw */
|
||||
SetWindowLong( p_vout->p_sys->hwnd, GWL_USERDATA, (LONG)p_vout );
|
||||
|
||||
/* now display the window */
|
||||
ShowWindow(p_vout->p_sys->hwnd, SW_SHOW);
|
||||
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* DirectXCloseWindow: close the window created by DirectXCreateWindow
|
||||
*****************************************************************************
|
||||
* This function returns all resources allocated by DirectXCreateWindow.
|
||||
*****************************************************************************/
|
||||
static void DirectXCloseWindow( vout_thread_t *p_vout )
|
||||
{
|
||||
msg_Dbg( p_vout, "DirectXCloseWindow" );
|
||||
|
||||
if( p_vout->p_sys->hwnd != NULL )
|
||||
{
|
||||
DestroyWindow( p_vout->p_sys->hwnd );
|
||||
p_vout->p_sys->hwnd = NULL;
|
||||
}
|
||||
|
||||
/* We don't unregister the Window Class because it could lead to race
|
||||
* conditions and it will be done anyway by the system when the app will
|
||||
* exit */
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* DirectXUpdateRects:
|
||||
*****************************************************************************
|
||||
* This function is called when the window position and size is changed, and
|
||||
* its job is to update the source and destination RECTs used to display the
|
||||
* picture.
|
||||
*****************************************************************************/
|
||||
static void DirectXUpdateRects( vout_thread_t *p_vout )
|
||||
{
|
||||
int i_width, i_height, i_x, i_y;
|
||||
|
||||
#define rect_src p_vout->p_sys->rect_src
|
||||
#define rect_src_clipped p_vout->p_sys->rect_src_clipped
|
||||
#define rect_dest p_vout->p_sys->rect_dest
|
||||
#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
|
||||
#define rect_display p_vout->p_sys->rect_display
|
||||
|
||||
vout_PlacePicture( p_vout, p_vout->p_sys->i_window_width,
|
||||
p_vout->p_sys->i_window_height,
|
||||
&i_x, &i_y, &i_width, &i_height );
|
||||
|
||||
/* Destination image position and dimensions */
|
||||
rect_dest.left = i_x + p_vout->p_sys->i_window_x;
|
||||
rect_dest.top = i_y + p_vout->p_sys->i_window_y;
|
||||
rect_dest.right = rect_dest.left + i_width;
|
||||
rect_dest.bottom = rect_dest.top + i_height;
|
||||
|
||||
|
||||
/* UpdateOverlay directdraw function doesn't automatically clip to the
|
||||
* display size so we need to do it otherwise it will fails */
|
||||
|
||||
/* Clip the destination window */
|
||||
IntersectRect( &rect_dest_clipped, &rect_dest, &rect_display );
|
||||
|
||||
#if 0
|
||||
msg_Dbg( p_vout, "DirectXUpdateRects image_dst_clipped coords:"
|
||||
" %i,%i,%i,%i",
|
||||
rect_dest_clipped.left, rect_dest_clipped.top,
|
||||
rect_dest_clipped.right, rect_dest_clipped.bottom );
|
||||
#endif
|
||||
|
||||
/* the 2 following lines are to fix a bug when clicking on the desktop */
|
||||
if( (rect_dest_clipped.right - rect_dest_clipped.left)==0 ||
|
||||
(rect_dest_clipped.bottom - rect_dest_clipped.top)==0 )
|
||||
{
|
||||
SetRectEmpty( &rect_src_clipped );
|
||||
return;
|
||||
}
|
||||
|
||||
/* src image dimensions */
|
||||
rect_src.left = 0;
|
||||
rect_src.top = 0;
|
||||
rect_src.right = p_vout->render.i_width;
|
||||
rect_src.bottom = p_vout->render.i_height;
|
||||
|
||||
/* Clip the source image */
|
||||
rect_src_clipped.left = (rect_dest_clipped.left - rect_dest.left) *
|
||||
p_vout->render.i_width / (rect_dest.right - rect_dest.left);
|
||||
rect_src_clipped.right = p_vout->render.i_width -
|
||||
(rect_dest.right - rect_dest_clipped.right) * p_vout->render.i_width /
|
||||
(rect_dest.right - rect_dest.left);
|
||||
rect_src_clipped.top = (rect_dest_clipped.top - rect_dest.top) *
|
||||
p_vout->render.i_height / (rect_dest.bottom - rect_dest.top);
|
||||
rect_src_clipped.bottom = p_vout->render.i_height -
|
||||
(rect_dest.bottom - rect_dest_clipped.bottom) * p_vout->render.i_height /
|
||||
(rect_dest.bottom - rect_dest.top);
|
||||
|
||||
#if 0
|
||||
msg_Dbg( p_vout, "DirectXUpdateRects image_src_clipped"
|
||||
" coords: %i,%i,%i,%i",
|
||||
rect_src_clipped.left, rect_src_clipped.top,
|
||||
rect_src_clipped.right, rect_src_clipped.bottom );
|
||||
#endif
|
||||
|
||||
#undef rect_src
|
||||
#undef rect_src_clipped
|
||||
#undef rect_dest
|
||||
#undef rect_dest_clipped
|
||||
#undef rect_display
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* DirectXEventProc: This is the window event processing function.
|
||||
*****************************************************************************
|
||||
* On Windows, when you create a window you have to attach an event processing
|
||||
* function to it. The aim of this function is to manage "Queued Messages" and
|
||||
* "Nonqueued Messages".
|
||||
* Queued Messages are those picked up and retransmitted by vout_Manage
|
||||
* (using the GetMessage and DispatchMessage functions).
|
||||
* Nonqueued Messages are those that Windows will send directly to this
|
||||
* procedure (like WM_DESTROY, WM_WINDOWPOSCHANGED...)
|
||||
*****************************************************************************/
|
||||
static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
vout_thread_t *p_vout =
|
||||
(vout_thread_t *)GetWindowLong( hwnd, GWL_USERDATA );
|
||||
|
||||
switch( message )
|
||||
{
|
||||
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
{
|
||||
RECT rect_window;
|
||||
POINT point_window;
|
||||
|
||||
/* update the window position */
|
||||
point_window.x = 0;
|
||||
point_window.y = 0;
|
||||
ClientToScreen( hwnd, &point_window );
|
||||
p_vout->p_sys->i_window_x = point_window.x;
|
||||
p_vout->p_sys->i_window_y = point_window.y;
|
||||
|
||||
/* update the window size */
|
||||
GetClientRect( hwnd, &rect_window );
|
||||
p_vout->p_sys->i_window_width = rect_window.right;
|
||||
p_vout->p_sys->i_window_height = rect_window.bottom;
|
||||
|
||||
DirectXUpdateRects( p_vout );
|
||||
if( p_vout->p_sys->b_using_overlay &&
|
||||
!p_vout->p_sys->p_event->b_die )
|
||||
DirectXUpdateOverlay( p_vout );
|
||||
|
||||
/* signal the size change */
|
||||
if( !p_vout->p_sys->b_using_overlay &&
|
||||
!p_vout->p_sys->p_event->b_die )
|
||||
p_vout->p_sys->i_changes |= VOUT_SIZE_CHANGE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
/* the user wants to close the window */
|
||||
case WM_CLOSE:
|
||||
msg_Dbg( p_vout, "WinProc WM_CLOSE" );
|
||||
/* exit application */
|
||||
p_vout->p_vlc->b_die = 1;
|
||||
return 0;
|
||||
break;
|
||||
|
||||
/* the window has been closed so shut down everything now */
|
||||
case WM_DESTROY:
|
||||
msg_Dbg( p_vout, "WinProc WM_DESTROY" );
|
||||
/* just destroy the window */
|
||||
PostQuitMessage( 0 );
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
switch (wParam)
|
||||
{
|
||||
case SC_SCREENSAVE: /* catch the screensaver */
|
||||
case SC_MONITORPOWER: /* catch the monitor turn-off */
|
||||
msg_Dbg( p_vout, "WinProc WM_SYSCOMMAND" );
|
||||
return 0; /* this stops them from happening */
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_ERASEBKGND:
|
||||
if( !p_vout->p_sys->b_using_overlay )
|
||||
{
|
||||
/* We want to eliminate unnecessary background redraws which create
|
||||
* an annoying flickering */
|
||||
int i_width, i_height, i_x, i_y;
|
||||
RECT rect_temp;
|
||||
GetClipBox( (HDC)wParam, &rect_temp );
|
||||
#if 0
|
||||
msg_Dbg( p_vout, "WinProc WM_ERASEBKGND %i,%i,%i,%i",
|
||||
rect_temp.left, rect_temp.top,
|
||||
rect_temp.right, rect_temp.bottom );
|
||||
#endif
|
||||
vout_PlacePicture( p_vout, p_vout->p_sys->i_window_width,
|
||||
p_vout->p_sys->i_window_height,
|
||||
&i_x, &i_y, &i_width, &i_height );
|
||||
ExcludeClipRect( (HDC)wParam, i_x, i_y,
|
||||
i_x + i_width, i_y + i_height );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//msg_Dbg( p_vout, "WinProc WM Default %i", message );
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, message, wParam, lParam);
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
|
@ -1,3 +0,0 @@
|
|||
downmix_SOURCES = downmix.c ac3_downmix_c.c
|
||||
downmixsse_SOURCES = downmix.c ac3_downmix_sse.c
|
||||
downmix3dn_SOURCES = downmix.c ac3_downmix_3dn.c
|
|
@ -1,307 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_downmix_3dn.c: accelerated 3D Now! ac3 downmix functions
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: ac3_downmix_3dn.c,v 1.12 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Renaud Dartus <reno@videolan.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
#include "ac3_downmix.h"
|
||||
|
||||
static const float sqrt2_3dn __asm__ ("sqrt2_3dn") = 0.7071068;
|
||||
|
||||
void E_( downmix_3f_2r_to_2ch ) (float * samples, dm_par_t * dm_par)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"movl $128, %%ebx\n" /* loop counter */
|
||||
|
||||
"movd (%%ecx), %%mm5\n" /* unit */
|
||||
"punpckldq %%mm5, %%mm5\n" /* unit | unit */
|
||||
|
||||
"movd 4(%%ecx), %%mm6\n" /* clev */
|
||||
"punpckldq %%mm6, %%mm6\n" /* clev | clev */
|
||||
|
||||
"movd 8(%%ecx), %%mm7\n" /* slev */
|
||||
"punpckldq %%mm7, %%mm7\n" /* slev | slev */
|
||||
|
||||
".align 16\n"
|
||||
".loop:\n"
|
||||
"movq (%%eax), %%mm0\n" /* left */
|
||||
"movq 2048(%%eax), %%mm1\n" /* right */
|
||||
"movq 1024(%%eax), %%mm2\n" /* center */
|
||||
"movq 3072(%%eax), %%mm3\n" /* leftsur */
|
||||
"movq 4096(%%eax), %%mm4\n" /* rightsur */
|
||||
"pfmul %%mm5, %%mm0\n"
|
||||
"pfmul %%mm5, %%mm1\n"
|
||||
"pfmul %%mm6, %%mm2\n"
|
||||
"pfadd %%mm2, %%mm0\n"
|
||||
"pfadd %%mm2, %%mm1\n"
|
||||
"pfmul %%mm7, %%mm3\n"
|
||||
"pfmul %%mm7, %%mm4\n"
|
||||
"pfadd %%mm3, %%mm0\n"
|
||||
"pfadd %%mm4, %%mm1\n"
|
||||
|
||||
"movq %%mm0, (%%eax)\n"
|
||||
"movq %%mm1, 1024(%%eax)\n"
|
||||
|
||||
"addl $8, %%eax\n"
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop\n"
|
||||
|
||||
"popl %%ebx\n"
|
||||
"femms\n"
|
||||
: "=a" (samples)
|
||||
: "a" (samples), "c" (dm_par));
|
||||
}
|
||||
|
||||
void E_( downmix_2f_2r_to_2ch ) (float *samples, dm_par_t * dm_par)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"movl $128, %%ebx\n" /* loop counter */
|
||||
|
||||
"movd (%%ecx), %%mm5\n" /* unit */
|
||||
"punpckldq %%mm5, %%mm5\n" /* unit | unit */
|
||||
|
||||
"movd 8(%%ecx), %%mm7\n" /* slev */
|
||||
"punpckldq %%mm7, %%mm7\n" /* slev | slev */
|
||||
|
||||
".align 16\n"
|
||||
".loop3:\n"
|
||||
"movq (%%eax), %%mm0\n" /* left */
|
||||
"movq 1024(%%eax), %%mm1\n" /* right */
|
||||
"movq 2048(%%eax), %%mm3\n" /* leftsur */
|
||||
"movq 3072(%%eax), %%mm4\n" /* rightsur */
|
||||
"pfmul %%mm5, %%mm0\n"
|
||||
"pfmul %%mm5, %%mm1\n"
|
||||
"pfmul %%mm7, %%mm3\n"
|
||||
"pfmul %%mm7, %%mm4\n"
|
||||
"pfadd %%mm3, %%mm0\n"
|
||||
"pfadd %%mm4, %%mm1\n"
|
||||
|
||||
"movq %%mm0, (%%eax)\n"
|
||||
"movq %%mm1, 1024(%%eax)\n"
|
||||
|
||||
"addl $8, %%eax\n"
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop3\n"
|
||||
|
||||
"popl %%ebx\n"
|
||||
"femms\n"
|
||||
: "=a" (samples)
|
||||
: "a" (samples), "c" (dm_par));
|
||||
}
|
||||
|
||||
void E_( downmix_3f_1r_to_2ch ) (float *samples, dm_par_t * dm_par)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"movl $128, %%ebx\n" /* loop counter */
|
||||
|
||||
"movd (%%ecx), %%mm5\n" /* unit */
|
||||
"punpckldq %%mm5, %%mm5\n" /* unit | unit */
|
||||
|
||||
"movd 4(%%ecx), %%mm6\n" /* clev */
|
||||
"punpckldq %%mm6, %%mm6\n" /* clev | clev */
|
||||
|
||||
"movd 8(%%ecx), %%mm7\n" /* slev */
|
||||
"punpckldq %%mm7, %%mm7\n" /* slev | slev */
|
||||
|
||||
".align 16\n"
|
||||
".loop4:\n"
|
||||
"movq (%%eax), %%mm0\n" /* left */
|
||||
"movq 2048(%%eax), %%mm1\n" /* right */
|
||||
"movq 1024(%%eax), %%mm2\n" /* center */
|
||||
"movq 3072(%%eax), %%mm3\n" /* sur */
|
||||
"pfmul %%mm5, %%mm0\n"
|
||||
"pfmul %%mm5, %%mm1\n"
|
||||
"pfmul %%mm6, %%mm2\n"
|
||||
"pfadd %%mm2, %%mm0\n"
|
||||
"pfmul %%mm7, %%mm3\n"
|
||||
"pfadd %%mm2, %%mm1\n"
|
||||
"pfsub %%mm3, %%mm0\n"
|
||||
"pfadd %%mm3, %%mm1\n"
|
||||
|
||||
"movq %%mm0, (%%eax)\n"
|
||||
"movq %%mm1, 1024(%%eax)\n"
|
||||
|
||||
"addl $8, %%eax\n"
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop4\n"
|
||||
|
||||
"popl %%ebx\n"
|
||||
"femms\n"
|
||||
: "=a" (samples)
|
||||
: "a" (samples), "c" (dm_par));
|
||||
}
|
||||
|
||||
void E_( downmix_2f_1r_to_2ch ) (float *samples, dm_par_t * dm_par)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"movl $128, %%ebx\n" /* loop counter */
|
||||
|
||||
"movd (%%ecx), %%mm5\n" /* unit */
|
||||
"punpckldq %%mm5, %%mm5\n" /* unit | unit */
|
||||
|
||||
"movd 8(%%ecx), %%mm7\n" /* slev */
|
||||
"punpckldq %%mm7, %%mm7\n" /* slev | slev */
|
||||
|
||||
".align 16\n"
|
||||
".loop5:\n"
|
||||
"movq (%%eax), %%mm0\n" /* left */
|
||||
"movq 1024(%%eax), %%mm1\n" /* right */
|
||||
"movq 2048(%%eax), %%mm3\n" /* sur */
|
||||
"pfmul %%mm5, %%mm0\n"
|
||||
"pfmul %%mm5, %%mm1\n"
|
||||
"pfmul %%mm7, %%mm3\n"
|
||||
"pfsub %%mm3, %%mm0\n"
|
||||
"pfadd %%mm3, %%mm1\n"
|
||||
|
||||
"movq %%mm0, (%%eax)\n"
|
||||
"movq %%mm1, 1024(%%eax)\n"
|
||||
|
||||
"addl $8, %%eax\n"
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop5\n"
|
||||
|
||||
"popl %%ebx\n"
|
||||
"femms\n"
|
||||
: "=a" (samples)
|
||||
: "a" (samples), "c" (dm_par));
|
||||
}
|
||||
|
||||
void E_( downmix_3f_0r_to_2ch ) (float *samples, dm_par_t * dm_par)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"movl $128, %%ebx\n" /* loop counter */
|
||||
|
||||
"movd (%%ecx), %%mm5\n" /* unit */
|
||||
"punpckldq %%mm5, %%mm5\n" /* unit | unit */
|
||||
|
||||
"movd 4(%%ecx), %%mm6\n" /* clev */
|
||||
"punpckldq %%mm6, %%mm6\n" /* clev | clev */
|
||||
|
||||
".align 16\n"
|
||||
".loop6:\n"
|
||||
"movq (%%eax), %%mm0\n" /*left */
|
||||
"movq 2048(%%eax), %%mm1\n" /* right */
|
||||
"movq 1024(%%eax), %%mm2\n" /* center */
|
||||
"pfmul %%mm5, %%mm0\n"
|
||||
"pfmul %%mm5, %%mm1\n"
|
||||
"pfmul %%mm6, %%mm2\n"
|
||||
"pfadd %%mm2, %%mm0\n"
|
||||
"pfadd %%mm2, %%mm1\n"
|
||||
|
||||
"movq %%mm0, (%%eax)\n"
|
||||
"movq %%mm1, 1024(%%eax)\n"
|
||||
|
||||
"addl $8, %%eax\n"
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop6\n"
|
||||
|
||||
"popl %%ebx\n"
|
||||
"femms\n"
|
||||
: "=a" (samples)
|
||||
: "a" (samples), "c" (dm_par));
|
||||
}
|
||||
|
||||
void E_( stream_sample_1ch_to_s16 ) (s16 *s16_samples, float *left)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"pushl %%edx\n"
|
||||
|
||||
"movl $sqrt2_3dn, %%edx\n"
|
||||
"movd (%%edx), %%mm7\n"
|
||||
"punpckldq %%mm7, %%mm7\n" /* sqrt2 | sqrt2 */
|
||||
"movl $128, %%ebx\n"
|
||||
|
||||
".align 16\n"
|
||||
".loop2:\n"
|
||||
"movq (%%ecx), %%mm0\n" /* c1 | c0 */
|
||||
"pfmul %%mm7, %%mm0\n"
|
||||
|
||||
"pf2id %%mm0, %%mm0\n" /* c1 c0 --> mm0, int_32 */
|
||||
|
||||
"packssdw %%mm0, %%mm0\n" /* c1 c1 c0 c0 --> mm0, int_16 */
|
||||
|
||||
"movq %%mm0, (%%eax)\n"
|
||||
"addl $8, %%eax\n"
|
||||
"addl $8, %%ecx\n"
|
||||
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop2\n"
|
||||
|
||||
"popl %%edx\n"
|
||||
"popl %%ebx\n"
|
||||
"femms\n"
|
||||
: "=a" (s16_samples), "=c" (left)
|
||||
: "a" (s16_samples), "c" (left));
|
||||
}
|
||||
|
||||
void E_( stream_sample_2ch_to_s16 ) (s16 *s16_samples, float *left, float *right)
|
||||
{
|
||||
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"movl $128, %%ebx\n"
|
||||
|
||||
".align 16\n"
|
||||
".loop1:\n"
|
||||
"movq (%%ecx), %%mm0\n" /* l1 | l0 */
|
||||
"movq (%%edx), %%mm1\n" /* r1 | r0 */
|
||||
"movq %%mm0, %%mm2\n" /* l1 | l0 */
|
||||
"punpckldq %%mm1, %%mm0\n" /* r0 | l0 */
|
||||
"punpckhdq %%mm1, %%mm2\n" /* r1 | l1 */
|
||||
|
||||
"pf2id %%mm0, %%mm0\n" /* r0 l0 --> mm0, int_32 */
|
||||
"pf2id %%mm2, %%mm2\n" /* r0 l0 --> mm0, int_32 */
|
||||
|
||||
"packssdw %%mm2, %%mm0\n" /* r1 l1 r0 l0 --> mm0, int_16 */
|
||||
|
||||
"movq %%mm0, (%%eax)\n"
|
||||
"movq %%mm2, 8(%%eax)\n"
|
||||
"addl $8, %%eax\n"
|
||||
"addl $8, %%ecx\n"
|
||||
"addl $8, %%edx\n"
|
||||
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop1\n"
|
||||
|
||||
"popl %%ebx\n"
|
||||
"femms\n"
|
||||
: "=a" (s16_samples), "=c" (left), "=d" (right)
|
||||
: "a" (s16_samples), "c" (left), "d" (right));
|
||||
|
||||
}
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_downmix_c.c: ac3 downmix functions in C
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: ac3_downmix_c.c,v 1.6 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Renaud Dartus <reno@videolan.org>
|
||||
* Aaron Holtzman <aholtzma@engr.uvic.ca>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <string.h> /* memcpy() */
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
#include "ac3_downmix.h"
|
||||
|
||||
void E_( downmix_3f_2r_to_2ch ) (float *samples, dm_par_t *dm_par)
|
||||
{
|
||||
int i;
|
||||
float *left, *right, *center, *left_sur, *right_sur;
|
||||
float left_tmp, right_tmp;
|
||||
|
||||
left = samples;
|
||||
center = samples + 256;
|
||||
right = samples + 256*2;
|
||||
left_sur = samples + 256*3;
|
||||
right_sur = samples + 256*4;
|
||||
|
||||
for (i=0; i < 256; i++) {
|
||||
left_tmp = dm_par->unit * *left + dm_par->clev * *center + dm_par->slev * *left_sur++;
|
||||
right_tmp = dm_par->unit * *right++ + dm_par->clev * *center + dm_par->slev * *right_sur++;
|
||||
*left++ = left_tmp;
|
||||
*center++ = right_tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void E_( downmix_2f_2r_to_2ch ) (float *samples, dm_par_t *dm_par)
|
||||
{
|
||||
int i;
|
||||
float *left, *right, *left_sur, *right_sur;
|
||||
float left_tmp, right_tmp;
|
||||
|
||||
left = &samples[0];
|
||||
right = &samples[256];
|
||||
left_sur = &samples[512];
|
||||
right_sur = &samples[768];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
left_tmp = dm_par->unit * *left + dm_par->slev * *left_sur++;
|
||||
right_tmp= dm_par->unit * *right + dm_par->slev * *right_sur++;
|
||||
*left++ = left_tmp;
|
||||
*right++ = right_tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void E_( downmix_3f_1r_to_2ch ) (float *samples, dm_par_t *dm_par)
|
||||
{
|
||||
int i;
|
||||
float *left, *right, *center, *right_sur;
|
||||
float left_tmp, right_tmp;
|
||||
|
||||
left = &samples[0];
|
||||
right = &samples[512];
|
||||
center = &samples[256];
|
||||
right_sur = &samples[768];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
left_tmp = dm_par->unit * *left + dm_par->clev * *center - dm_par->slev * *right_sur;
|
||||
right_tmp= dm_par->unit * *right++ + dm_par->clev * *center + dm_par->slev * *right_sur++;
|
||||
*left++ = left_tmp;
|
||||
*center++ = right_tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void E_( downmix_2f_1r_to_2ch ) (float *samples, dm_par_t *dm_par)
|
||||
{
|
||||
int i;
|
||||
float *left, *right, *right_sur;
|
||||
float left_tmp, right_tmp;
|
||||
|
||||
left = &samples[0];
|
||||
right = &samples[256];
|
||||
right_sur = &samples[512];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
left_tmp = dm_par->unit * *left - dm_par->slev * *right_sur;
|
||||
right_tmp= dm_par->unit * *right + dm_par->slev * *right_sur++;
|
||||
*left++ = left_tmp;
|
||||
*right++ = right_tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void E_( downmix_3f_0r_to_2ch ) (float *samples, dm_par_t *dm_par)
|
||||
{
|
||||
int i;
|
||||
float *left, *right, *center;
|
||||
float left_tmp, right_tmp;
|
||||
|
||||
left = &samples[0];
|
||||
center = &samples[256];
|
||||
right = &samples[512];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
left_tmp = dm_par->unit * *left + dm_par->clev * *center;
|
||||
right_tmp= dm_par->unit * *right++ + dm_par->clev * *center;
|
||||
*left++ = left_tmp;
|
||||
*center++ = right_tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void E_( stream_sample_2ch_to_s16 ) (s16 *out_buf, float *left, float *right)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < 256; i++) {
|
||||
*out_buf++ = (s16) (*left++);
|
||||
*out_buf++ = (s16) (*right++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void E_( stream_sample_1ch_to_s16 ) (s16 *out_buf, float *center)
|
||||
{
|
||||
int i;
|
||||
float tmp;
|
||||
|
||||
for (i=0; i < 256; i++) {
|
||||
*out_buf++ = tmp = (s16) (0.7071f * *center++);
|
||||
*out_buf++ = tmp;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_downmix_common.h: ac3 downmix functions headers
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: ac3_downmix_common.h,v 1.2 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Renaud Dartus <reno@videolan.org>
|
||||
* Aaron Holtzman <aholtzma@engr.uvic.ca>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
void E_( downmix_3f_2r_to_2ch ) ( float *, dm_par_t * );
|
||||
void E_( downmix_2f_2r_to_2ch ) ( float *, dm_par_t * );
|
||||
void E_( downmix_3f_1r_to_2ch ) ( float *, dm_par_t * );
|
||||
void E_( downmix_2f_1r_to_2ch ) ( float *, dm_par_t * );
|
||||
void E_( downmix_3f_0r_to_2ch ) ( float *, dm_par_t * );
|
||||
void E_( stream_sample_2ch_to_s16 ) ( s16 *, float *, float * );
|
||||
void E_( stream_sample_1ch_to_s16 ) ( s16 *, float * );
|
||||
|
|
@ -1,312 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* ac3_downmix_sse.c: accelerated SSE ac3 downmix functions
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999, 2000, 2001 VideoLAN
|
||||
* $Id: ac3_downmix_sse.c,v 1.12 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Renaud Dartus <reno@videolan.org>
|
||||
* Aaron Holtzman <aholtzma@engr.uvic.ca>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
#include "ac3_downmix.h"
|
||||
|
||||
static const float sqrt2_sse __asm__ ("sqrt2_sse") __attribute__ ((aligned (16))) = 0.7071068;
|
||||
|
||||
void E_( downmix_3f_2r_to_2ch ) (float * samples, dm_par_t * dm_par)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"movl $64, %%ebx\n" /* loop counter */
|
||||
|
||||
"movss (%%ecx), %%xmm5\n" /* unit */
|
||||
"shufps $0, %%xmm5, %%xmm5\n" /* unit | unit | unit | unit */
|
||||
|
||||
"movss 4(%%ecx), %%xmm6\n" /* clev */
|
||||
"shufps $0, %%xmm6, %%xmm6\n" /* clev | clev | clev | clev */
|
||||
|
||||
"movss 8(%%ecx), %%xmm7\n" /* slev */
|
||||
"shufps $0, %%xmm7, %%xmm7\n" /* slev | slev | slev | slev */
|
||||
|
||||
".align 16\n"
|
||||
".loop:\n"
|
||||
"movaps (%%eax), %%xmm0\n" /* left */
|
||||
"movaps 2048(%%eax), %%xmm1\n" /* right */
|
||||
"movaps 1024(%%eax), %%xmm2\n" /* center */
|
||||
"movaps 3072(%%eax), %%xmm3\n" /* leftsur */
|
||||
"movaps 4096(%%eax), %%xmm4\n" /* rithgsur */
|
||||
"mulps %%xmm5, %%xmm0\n"
|
||||
"mulps %%xmm5, %%xmm1\n"
|
||||
"mulps %%xmm6, %%xmm2\n"
|
||||
"addps %%xmm2, %%xmm0\n"
|
||||
"addps %%xmm2, %%xmm1\n"
|
||||
"mulps %%xmm7, %%xmm3\n"
|
||||
"mulps %%xmm7, %%xmm4\n"
|
||||
"addps %%xmm3, %%xmm0\n"
|
||||
"addps %%xmm4, %%xmm1\n"
|
||||
|
||||
"movaps %%xmm0, (%%eax)\n"
|
||||
"movaps %%xmm1, 1024(%%eax)\n"
|
||||
|
||||
"addl $16, %%eax\n"
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop\n"
|
||||
|
||||
"popl %%ebx\n"
|
||||
: "=a" (samples)
|
||||
: "a" (samples), "c" (dm_par));
|
||||
}
|
||||
|
||||
void E_( downmix_2f_2r_to_2ch ) (float *samples, dm_par_t * dm_par)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"movl $64, %%ebx\n" /* loop counter */
|
||||
|
||||
"movss (%%ecx), %%xmm5\n" /* unit */
|
||||
"shufps $0, %%xmm5, %%xmm5\n" /* unit | unit | unit | unit */
|
||||
|
||||
"movss 8(%%ecx), %%xmm7\n" /* slev */
|
||||
"shufps $0, %%xmm7, %%xmm7\n" /* slev | slev | slev | slev */
|
||||
|
||||
".align 16\n"
|
||||
".loop3:\n"
|
||||
"movaps (%%eax), %%xmm0\n" /* left */
|
||||
"movaps 1024(%%eax), %%xmm1\n" /* right */
|
||||
"movaps 2048(%%eax), %%xmm3\n" /* leftsur */
|
||||
"movaps 3072(%%eax), %%xmm4\n" /* rightsur */
|
||||
"mulps %%xmm5, %%xmm0\n"
|
||||
"mulps %%xmm5, %%xmm1\n"
|
||||
"mulps %%xmm7, %%xmm3\n"
|
||||
"mulps %%xmm7, %%xmm4\n"
|
||||
"addps %%xmm3, %%xmm0\n"
|
||||
"addps %%xmm4, %%xmm1\n"
|
||||
|
||||
"movaps %%xmm0, (%%eax)\n"
|
||||
"movaps %%xmm1, 1024(%%eax)\n"
|
||||
|
||||
"addl $16, %%eax\n"
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop3\n"
|
||||
|
||||
"popl %%ebx\n"
|
||||
: "=a" (samples)
|
||||
: "a" (samples), "c" (dm_par));
|
||||
}
|
||||
|
||||
void E_( downmix_3f_1r_to_2ch ) (float *samples, dm_par_t * dm_par)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"movl $64, %%ebx\n" /* loop counter */
|
||||
|
||||
"movss (%%ecx), %%xmm5\n" /* unit */
|
||||
"shufps $0, %%xmm5, %%xmm5\n" /* unit | unit | unit | unit */
|
||||
|
||||
"movss 4(%%ecx), %%xmm6\n" /* clev */
|
||||
"shufps $0, %%xmm6, %%xmm6\n" /* clev | clev | clev | clev */
|
||||
|
||||
"movss 8(%%ecx), %%xmm7\n" /* slev */
|
||||
"shufps $0, %%xmm7, %%xmm7\n" /* slev | slev | slev | slev */
|
||||
|
||||
".align 16\n"
|
||||
".loop4:\n"
|
||||
"movaps (%%eax), %%xmm0\n" /* left */
|
||||
"movaps 2048(%%eax), %%xmm1\n" /* right */
|
||||
"movaps 1024(%%eax), %%xmm2\n" /* center */
|
||||
"movaps 3072(%%eax), %%xmm3\n" /* sur */
|
||||
"mulps %%xmm5, %%xmm0\n"
|
||||
"mulps %%xmm5, %%xmm1\n"
|
||||
"mulps %%xmm6, %%xmm2\n"
|
||||
"addps %%xmm2, %%xmm0\n"
|
||||
"mulps %%xmm7, %%xmm3\n"
|
||||
"addps %%xmm2, %%xmm1\n"
|
||||
"subps %%xmm3, %%xmm0\n"
|
||||
"addps %%xmm3, %%xmm1\n"
|
||||
|
||||
"movaps %%xmm0, (%%eax)\n"
|
||||
"movaps %%xmm1, 1024(%%eax)\n"
|
||||
|
||||
"addl $16, %%eax\n"
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop4\n"
|
||||
|
||||
"popl %%ebx\n"
|
||||
: "=a" (samples)
|
||||
: "a" (samples), "c" (dm_par));
|
||||
}
|
||||
|
||||
void E_( downmix_2f_1r_to_2ch ) (float *samples, dm_par_t * dm_par)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"movl $64, %%ebx\n" /* loop counter */
|
||||
|
||||
"movss (%%ecx), %%xmm5\n" /* unit */
|
||||
"shufps $0, %%xmm5, %%xmm5\n" /* unit | unit | unit | unit */
|
||||
|
||||
"movss 8(%%ecx), %%xmm7\n" /* slev */
|
||||
"shufps $0, %%xmm7, %%xmm7\n" /* slev | slev | slev | slev */
|
||||
|
||||
".align 16\n"
|
||||
".loop5:\n"
|
||||
"movaps (%%eax), %%xmm0\n" /* left */
|
||||
"movaps 1024(%%eax), %%xmm1\n" /* right */
|
||||
"movaps 2048(%%eax), %%xmm3\n" /* sur */
|
||||
"mulps %%xmm5, %%xmm0\n"
|
||||
"mulps %%xmm5, %%xmm1\n"
|
||||
"mulps %%xmm7, %%xmm3\n"
|
||||
"subps %%xmm3, %%xmm0\n"
|
||||
"addps %%xmm3, %%xmm1\n"
|
||||
|
||||
"movaps %%xmm0, (%%eax)\n"
|
||||
"movaps %%xmm1, 1024(%%eax)\n"
|
||||
|
||||
"addl $16, %%eax\n"
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop5\n"
|
||||
|
||||
"popl %%ebx\n"
|
||||
: "=a" (samples)
|
||||
: "a" (samples), "c" (dm_par));
|
||||
}
|
||||
|
||||
void E_( downmix_3f_0r_to_2ch ) (float *samples, dm_par_t * dm_par)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"movl $64, %%ebx\n" /* loop counter */
|
||||
|
||||
"movss (%%ecx), %%xmm5\n" /* unit */
|
||||
"shufps $0, %%xmm5, %%xmm5\n" /* unit | unit | unit | unit */
|
||||
|
||||
"movss 4(%%ecx), %%xmm6\n" /* clev */
|
||||
"shufps $0, %%xmm6, %%xmm6\n" /* clev | clev | clev | clev */
|
||||
|
||||
".align 16\n"
|
||||
".loop6:\n"
|
||||
"movaps (%%eax), %%xmm0\n" /*left */
|
||||
"movaps 2048(%%eax), %%xmm1\n" /* right */
|
||||
"movaps 1024(%%eax), %%xmm2\n" /* center */
|
||||
"mulps %%xmm5, %%xmm0\n"
|
||||
"mulps %%xmm5, %%xmm1\n"
|
||||
"mulps %%xmm6, %%xmm2\n"
|
||||
"addps %%xmm2, %%xmm0\n"
|
||||
"addps %%xmm2, %%xmm1\n"
|
||||
|
||||
"movaps %%xmm0, (%%eax)\n"
|
||||
"movaps %%xmm1, 1024(%%eax)\n"
|
||||
|
||||
"addl $16, %%eax\n"
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop6\n"
|
||||
|
||||
"popl %%ebx\n"
|
||||
: "=a" (samples)
|
||||
: "a" (samples), "c" (dm_par));
|
||||
}
|
||||
|
||||
void E_( stream_sample_1ch_to_s16 ) (s16 *s16_samples, float *left)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"pushl %%edx\n"
|
||||
|
||||
"movl $sqrt2_sse, %%edx\n"
|
||||
"movss (%%edx), %%xmm7\n"
|
||||
"shufps $0, %%xmm7, %%xmm7\n" /* sqrt2 | sqrt2 | sqrt2 | sqrt2 */
|
||||
"movl $64, %%ebx\n"
|
||||
|
||||
".align 16\n"
|
||||
".loop2:\n"
|
||||
"movaps (%%ecx), %%xmm0\n" /* c3 | c2 | c1 | c0 */
|
||||
"mulps %%xmm7, %%xmm0\n"
|
||||
"movhlps %%xmm0, %%xmm2\n" /* c3 | c2 */
|
||||
|
||||
"cvtps2pi %%xmm0, %%mm0\n" /* c1 c0 --> mm0, int_32 */
|
||||
"cvtps2pi %%xmm2, %%mm1\n" /* c3 c2 --> mm1, int_32 */
|
||||
|
||||
"packssdw %%mm0, %%mm0\n" /* c1 c1 c0 c0 --> mm0, int_16 */
|
||||
"packssdw %%mm1, %%mm1\n" /* c3 c3 c2 c2 --> mm1, int_16 */
|
||||
|
||||
"movq %%mm0, (%%eax)\n"
|
||||
"movq %%mm1, 8(%%eax)\n"
|
||||
"addl $16, %%eax\n"
|
||||
"addl $16, %%ecx\n"
|
||||
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop2\n"
|
||||
|
||||
"popl %%edx\n"
|
||||
"popl %%ebx\n"
|
||||
"emms\n"
|
||||
: "=a" (s16_samples), "=c" (left)
|
||||
: "a" (s16_samples), "c" (left));
|
||||
}
|
||||
|
||||
void E_( stream_sample_2ch_to_s16 ) (s16 *s16_samples, float *left, float *right)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
".align 16\n"
|
||||
"pushl %%ebx\n"
|
||||
"movl $64, %%ebx\n"
|
||||
|
||||
".align 16\n"
|
||||
".loop1:\n"
|
||||
"movaps (%%ecx), %%xmm0\n" /* l3 | l2 | l1 | l0 */
|
||||
"movaps (%%edx), %%xmm1\n" /* r3 | r2 | r1 | r0 */
|
||||
"movhlps %%xmm0, %%xmm2\n" /* l3 | l2 */
|
||||
"movhlps %%xmm1, %%xmm3\n" /* r3 | r2 */
|
||||
"unpcklps %%xmm1, %%xmm0\n" /* r1 | l1 | r0 | l0 */
|
||||
"unpcklps %%xmm3, %%xmm2\n" /* r3 | l3 | r2 | l2 */
|
||||
|
||||
"cvtps2pi %%xmm0, %%mm0\n" /* r0 l0 --> mm0, int_32 */
|
||||
"movhlps %%xmm0, %%xmm0\n"
|
||||
"cvtps2pi %%xmm0, %%mm1\n" /* r1 l1 --> mm1, int_32 */
|
||||
"cvtps2pi %%xmm2, %%mm2\n" /* r2 l2 --> mm2, int_32 */
|
||||
"movhlps %%xmm2, %%xmm2\n"
|
||||
"cvtps2pi %%xmm2, %%mm3\n" /* r3 l3 --> mm3, int_32 */
|
||||
|
||||
"packssdw %%mm1, %%mm0\n" /* r1 l1 r0 l0 --> mm0, int_16 */
|
||||
"packssdw %%mm3, %%mm2\n" /* r3 l3 r2 l2 --> mm2, int_16 */
|
||||
|
||||
"movq %%mm0, (%%eax)\n"
|
||||
"movq %%mm2, 8(%%eax)\n"
|
||||
"addl $16, %%eax\n"
|
||||
"addl $16, %%ecx\n"
|
||||
"addl $16, %%edx\n"
|
||||
|
||||
"decl %%ebx\n"
|
||||
"jnz .loop1\n"
|
||||
|
||||
"popl %%ebx\n"
|
||||
"emms\n"
|
||||
: "=a" (s16_samples), "=c" (left), "=d" (right)
|
||||
: "a" (s16_samples), "c" (left), "d" (right));
|
||||
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* downmix.c : AC3 downmix module
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: downmix.c,v 1.10 2002/07/31 20:56:51 sam Exp $
|
||||
*
|
||||
* Authors: Renaud Dartus <reno@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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
#include "ac3_downmix.h"
|
||||
#include "ac3_downmix_common.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Module initializer
|
||||
*****************************************************************************/
|
||||
static int Open ( vlc_object_t *p_this )
|
||||
{
|
||||
downmix_t *p_downmix = (downmix_t *)p_this;
|
||||
|
||||
p_downmix->pf_downmix_3f_2r_to_2ch = E_( downmix_3f_2r_to_2ch );
|
||||
p_downmix->pf_downmix_3f_1r_to_2ch = E_( downmix_3f_1r_to_2ch );
|
||||
p_downmix->pf_downmix_2f_2r_to_2ch = E_( downmix_2f_2r_to_2ch );
|
||||
p_downmix->pf_downmix_2f_1r_to_2ch = E_( downmix_2f_1r_to_2ch );
|
||||
p_downmix->pf_downmix_3f_0r_to_2ch = E_( downmix_3f_0r_to_2ch );
|
||||
p_downmix->pf_stream_sample_2ch_to_s16 = E_( stream_sample_2ch_to_s16 );
|
||||
p_downmix->pf_stream_sample_1ch_to_s16 = E_( stream_sample_1ch_to_s16 );
|
||||
|
||||
return VLC_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Module descriptor
|
||||
*****************************************************************************/
|
||||
vlc_module_begin();
|
||||
#ifdef MODULE_NAME_IS_downmix
|
||||
set_description( _("AC3 downmix module") );
|
||||
set_capability( "downmix", 50 );
|
||||
add_shortcut( "c" );
|
||||
#elif defined( MODULE_NAME_IS_downmixsse )
|
||||
set_description( _("SSE AC3 downmix module") );
|
||||
set_capability( "downmix", 200 );
|
||||
add_shortcut( "sse" );
|
||||
#elif defined( MODULE_NAME_IS_downmix3dn )
|
||||
set_description( _("3D Now! AC3 downmix module") );
|
||||
set_capability( "downmix", 200 );
|
||||
add_shortcut( "3dn" );
|
||||
add_shortcut( "3dnow" );
|
||||
#endif
|
||||
set_callbacks( Open, NULL );
|
||||
vlc_module_end();
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
.dep
|
||||
*.lo
|
||||
*.o.*
|
||||
*.lo.*
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue