Commit 3482c341 authored by Sam Hocevar's avatar Sam Hocevar

NEWS:

 . encore un peu de parsage de sous-titres
 . affichage des sous-titres.

BUGS:
 . �a segfaulte toujours au moment o� on quitte, mais c'est le probl�me
  habituel, �a sera r�gl�.
 . pour le moment ils sont en noir et blanc, parce qu'il faut aller
  chercher cette putain de palette dans les .IFO du dvd et que pour
  l'instant j'ai la flemme
 . les sous-titres ne sont pas affich�s comme il faut si la largeur
  de l'�cran n'est pas 720.
 . dimensions par d�faut mises � 720x576 (format DVD) au lieu de 640x480
  pour la raison �voqu�e ci-dessus. mais �a sera r�gl� bient�t.
 . pas de gestion de transparence, coordonn�es, fade in/fade out
 . pas de gestion de date : le sous-titre est affich� d�s qu'il est re�u
  et n'est pas effac� tant qu'on en a pas re�u un nouveau.
parent 3b8adcbd
......@@ -222,6 +222,7 @@ audio_output_obj = audio_output/audio_output.o
video_output_obj = video_output/video_output.o \
video_output/video_text.o \
video_output/video_spu.o \
video_output/video_yuv.o
ac3_decoder_obj = ac3_decoder/ac3_decoder_thread.o \
......
......@@ -109,7 +109,7 @@
* Decoders FIFO configuration
*/
/* Size of the FIFO. FIFO_SIZE+1 must be a multiple of 2 */
/* Size of the FIFO. FIFO_SIZE+1 must be a power of 2 */
#define FIFO_SIZE 1023
......@@ -266,8 +266,8 @@
* standard width and height broadcasted MPEG-2 streams */
#define VOUT_WIDTH_VAR "vlc_width"
#define VOUT_HEIGHT_VAR "vlc_height"
#define VOUT_WIDTH_DEFAULT 640
#define VOUT_HEIGHT_DEFAULT 480
#define VOUT_WIDTH_DEFAULT 720
#define VOUT_HEIGHT_DEFAULT 576
/* Maximum width of a scaled source picture - this should be relatively high,
* since higher stream values will result in no display at all. */
......
......@@ -147,6 +147,11 @@ typedef struct subpicture_s
u32 i_border_color; /* border color */
u32 i_bg_color; /* background color */
} text;
/* DVD subpicture units properties */
struct
{
int i_offset[2]; /* byte offsets to data */
} spu;
} type;
/* Subpicture data, format depends of type - data can always be freely
......
......@@ -57,7 +57,7 @@ typedef struct vout_yuv_s
vout_yuv_convert_t * p_Convert422; /* YUV 4:2:2 converter */
vout_yuv_convert_t * p_Convert444; /* YUV 4:4:4 converter */
/* Pre-calculated convertion tables */
/* Pre-calculated conversion tables */
void * p_base; /* base for all conversion tables */
union
{
......@@ -69,7 +69,7 @@ typedef struct vout_yuv_s
u32 * p_rgb32; /* RGB 32 bits table */
} yuv;
/* Temporary convertion buffer and offset array */
/* Temporary conversion buffer and offset array */
void * p_buffer; /* convertion buffer */
int * p_offset; /* offset array */
} vout_yuv_t;
......
......@@ -1226,8 +1226,9 @@ static __inline__ void input_ParsePES( input_thread_t *p_input,
break;
case DVD_SPU_ES:
/* we skip 4 bytes at the beginning of the subpicture payload */
//p_ts->i_payload_start += 4;
/* we skip the first byte at the beginning of the
* subpicture payload, it only contains the SPU ID. */
p_ts->i_payload_start++;
p_fifo = &(((spudec_thread_t *)(p_es_descriptor->p_dec))->fifo);
break;
......
......@@ -202,141 +202,143 @@ static void RunThread( spudec_thread_t *p_spudec )
*/
while( (!p_spudec->b_die) && (!p_spudec->b_error) )
{
int i_spu_id;
int i_packet_size;
int i_rle_size;
int i_index;
int i_pes_size;
boolean_t b_finished;
int i_pes_size;
int i_pes_count;
boolean_t b_finished;
unsigned char * p_spu_data;
subpicture_t * p_spu;
subpicture_t * p_spu = NULL;
while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
{
printf( "*** tracking next SPU PES\n" );
/* wait for the next SPU ID.
* FIXME: We trash 0xff bytes since they come from
* an incomplete previous packet */
do
{
i_spu_id = GetByte( &p_spudec->bit_stream );
i_packet_size = GetByte( &p_spudec->bit_stream );
}
while( (i_spu_id & 0xe0) != 0x20 );
i_pes_size = DECODER_FIFO_START(p_spudec->fifo)->i_pes_size;
printf( "got it. size = 0x%.4x\n", i_pes_size );
while( i_packet_size == 0xff );
printf( "SPU id: 0x%.2x\n", i_spu_id );
/* the total size - should equal the sum of the
* PES packet size that form the SPU packet */
i_packet_size = ( i_packet_size << 8 )
+ GetByte( &p_spudec->bit_stream );
i_index = 2;
i_index = 0;
GetWord( i_packet_size );
printf( "total size: 0x%.4x\n", i_packet_size );
/* get the useful PES size (real size - 10) */
i_pes_size = DECODER_FIFO_START(p_spudec->fifo)->i_pes_size - 9;
i_pes_count = 1;
/* the RLE stuff size */
GetWord( i_rle_size );
printf( "RLE size: 0x%.4x\n", i_rle_size );
/* we already read 4 bytes for the total size and the RLE size */
/* if the values we got aren't too strange, decode the data */
if( i_rle_size < i_packet_size )
{
/* destroy the previous one */
if( p_spu ) vout_DestroySubPicture( p_spudec->p_vout, p_spu );
p_spu = vout_CreateSubPicture( p_spudec->p_vout,
/* allocate the subpicture.
* FIXME: we should check if the allocation failed */
p_spu = vout_CreateSubPicture( p_spudec->p_vout,
DVD_SUBPICTURE, i_rle_size );
p_spu_data = p_spu->p_data;
p_spu_data = p_spu->p_data;
if( (i_rle_size < i_packet_size)
&& ((i_spu_id & 0xe0) == 0x20) )
{
printf( "doing RLE stuff (%i bytes)\n", i_rle_size );
printf( "index/size %i/%i\n", i_index, i_pes_size );
while( i_index++ <i_rle_size )
/* getting the RLE part */
while( i_index++ < i_rle_size )
{
//*p_spu_data++ = GetByte( &p_spudec->bit_stream );
if (i_index == i_pes_size) printf ("\n **** \n");
/* kludge ??? */
if (i_index == i_pes_size) printf( "%.2x", *p_spu_data++ = GetByte( &p_spudec->bit_stream ) );
printf( "%.2x", *p_spu_data++ = GetByte( &p_spudec->bit_stream ) );
/* skip the leading byte of a PES */
if ( !((i_index + 3) % i_pes_size) )
{
i_pes_count++;
}
*p_spu_data++ = GetByte( &p_spudec->bit_stream );
}
printf( "\nindex/size %i/%i\n", i_index, i_pes_size );
//printf( "\n" );
b_finished = 0;
printf( "control stuff\n" );
do
/* getting the control part */
b_finished = 0;
do
{
unsigned char i_cmd;
unsigned int i_word;
/* the date */
GetWord( i_word );
printf( "date: 0x%.4x\n", i_word );
/* next offset, no next offset if == i_index-5 */
GetWord( i_word );
printf( " next: 0x%.4x (i-5: %.4x)\n", i_word, i_index-5 );
b_finished = (i_index - 5 >= i_word );
b_finished = ( i_index - 5 >= i_word );
do
{
do
{
i_cmd = GetByte( &p_spudec->bit_stream );
i_index++;
i_index++;
switch(i_cmd)
{
switch( i_cmd )
{
case 0x00:
printf( " 00 (display now)\n" );
/* 00 (display now) */
break;
case 0x01:
printf( " 01 (start displaying)\n" );
/* 01 (start displaying) */
break;
case 0x02:
printf( " 02 (stop displaying)\n" );
/* 02 (stop displaying) */
break;
case 0x03:
GetWord( i_word );
printf( " 03 (palette) - %.4x\n", i_word );
/* 03xxxx (palette) */
GetWord( i_word );
break;
case 0x04:
GetWord( i_word );
printf( " 04 (alpha channel) - %.4x\n", i_word );
/* 04xxxx (alpha channel) */
GetWord( i_word );
break;
case 0x05:
GetWord( i_word );
printf( " 05 (coordinates) - %.4x", i_word );
GetWord( i_word );
printf( "%.4x", i_word );
GetWord( i_word );
printf( "%.4x\n", i_word );
/* 05xxxyyyxxxyyy (coordinates) */
GetWord( i_word );
GetWord( i_word );
GetWord( i_word );
break;
case 0x06:
GetWord( i_word );
printf( " 06 (byte offsets) - %.4x", i_word );
GetWord( i_word );
printf( "%.4x\n", i_word );
/* 06xxxxyyyy (byte offsets) */
GetWord( i_word );
p_spu->type.spu.i_offset[0] = i_word - 4;
GetWord( i_word );
p_spu->type.spu.i_offset[1] = i_word - 4;
break;
case 0xff:
printf( " ff (end)\n" );
/* ff (end) */
break;
default:
printf( " %.2x (unknown command)\n", i_cmd );
default:
/* ?? (unknown command) */
break;
}
}
while( i_cmd != 0xff );
}
}
while( i_cmd != 0xff );
}
while( !b_finished );
}
while( !b_finished );
printf( "control stuff finished\n" );
printf( "*** end of PES !\n\n" );
/* SPU is finished - we can display it */
vout_DisplaySubPicture( p_spudec->p_vout, p_spu );
}
else
{
printf( "*** invalid PES !\n\n" );
/* trash the PES packet */
/*vlc_mutex_lock( &p_spudec->fifo.data_lock );
/* Unexpected PES packet - trash it */
vlc_mutex_lock( &p_spudec->fifo.data_lock );
input_NetlistFreePES( p_spudec->bit_stream.p_input,
DECODER_FIFO_START(p_spudec->fifo) );
DECODER_FIFO_INCSTART( p_spudec->fifo );
vlc_mutex_unlock( &p_spudec->fifo.data_lock );*/
vlc_mutex_unlock( &p_spudec->fifo.data_lock );
}
}
/* Waiting for the input thread to put new PES packets in the fifo */
printf( "decoder fifo is empty\n" );
vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
if( p_spu ) vout_DestroySubPicture( p_spudec->p_vout, p_spu );
}
/*
......
......@@ -42,6 +42,7 @@
#include "video.h"
#include "video_output.h"
#include "video_text.h"
#include "video_spu.h"
#include "video_yuv.h"
#include "intf_msg.h"
......@@ -360,9 +361,10 @@ subpicture_t *vout_CreateSubPicture( vout_thread_t *p_vout, int i_type,
if( (p_vout->p_subpicture[i_subpic].i_type == i_type) &&
(p_vout->p_subpicture[i_subpic].i_size >= i_size) )
{
/* Memory size do match or is smaller : memory will not be reallocated,
* and function can end immediately - this is the best possible case,
* since no memory allocation needs to be done */
/* Memory size do match or is smaller : memory will not be
* reallocated, and function can end immediately - this is
* the best possible case, since no memory allocation needs
* to be done */
p_vout->p_subpicture[i_subpic].i_status = RESERVED_SUBPICTURE;
#ifdef DEBUG_VIDEO
intf_DbgMsg("subpicture %p (in destroyed subpicture slot)\n",
......@@ -389,8 +391,8 @@ subpicture_t *vout_CreateSubPicture( vout_thread_t *p_vout, int i_type,
/* If no free subpicture is available, use a destroyed subpicture */
if( (p_free_subpic == NULL) && (p_destroyed_subpic != NULL ) )
{
/* No free subpicture or matching destroyed subpicture has been found, but
* a destroyed subpicture is still avalaible */
/* No free subpicture or matching destroyed subpicture has been
* found, but a destroyed subpicture is still avalaible */
free( p_destroyed_subpic->p_data );
p_free_subpic = p_destroyed_subpic;
}
......@@ -1021,11 +1023,20 @@ last_display_date = display_date;
}
}
/*
* Find the subpicture to display - this operation does not need lock, since
* only READY_SUBPICTURES are handled. If no picture has been selected,
* display_date will depend on the subpicture
* Find the subpictures to display - this operation does not need
* lock, since only READY_SUBPICTURE are handled. If no picture
* has been selected, display_date will depend on the subpicture
*/
/* XXX?? */
/* FIXME: we should find *all* subpictures to display, and
* check their displaying date as well */
for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ )
{
if( p_vout->p_subpicture[i_index].i_status == READY_SUBPICTURE )
{
p_subpic = &p_vout->p_subpicture[i_index];
break;
}
}
/*
* Perform rendering, sleep and display rendered picture
......@@ -1075,9 +1086,9 @@ last_display_date = display_date;
}
/* Remove subpicture from heap */
vlc_mutex_lock( &p_vout->subpicture_lock );
/*vlc_mutex_lock( &p_vout->subpicture_lock );
p_subpic->i_status = DESTROYED_SUBPICTURE;
vlc_mutex_unlock( &p_vout->subpicture_lock );
vlc_mutex_unlock( &p_vout->subpicture_lock );*/
}
}
......@@ -1104,9 +1115,9 @@ last_display_date = display_date;
}
/* Remove subpicture from heap */
vlc_mutex_lock( &p_vout->subpicture_lock );
/*vlc_mutex_lock( &p_vout->subpicture_lock );
p_subpic->i_status = DESTROYED_SUBPICTURE;
vlc_mutex_unlock( &p_vout->subpicture_lock );
vlc_mutex_unlock( &p_vout->subpicture_lock );*/
}
else if( p_vout->b_active ) /* idle or interface screen alone */
{
......@@ -1816,6 +1827,11 @@ static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
switch( p_subpic->i_type )
{
case DVD_SUBPICTURE: /* DVD subpicture unit */
vout_RenderSPU( p_subpic->p_data, p_subpic->type.spu.i_offset,
p_vout->p_buffer[ p_vout->i_buffer_index ].p_data,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line );
break;
case TEXT_SUBPICTURE: /* single line text */
/* Select default font if not specified */
p_font = p_subpic->type.text.p_font;
......@@ -1824,7 +1840,8 @@ static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
p_font = p_vout->p_default_font;
}
/* Computes text size (width and height fields are ignored) and print it */
/* Compute text size (width and height fields are ignored)
* and print it */
vout_TextSize( p_font, p_subpic->type.text.i_style, p_subpic->p_data, &i_width, &i_height );
if( !Align( p_vout, &p_subpic->i_x, &p_subpic->i_y, i_width, i_height,
p_subpic->i_horizontal_align, p_subpic->i_vertical_align ) )
......
/*****************************************************************************
* video_spu.h : DVD subpicture units functions
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
*
* 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.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <stdio.h>
#include "config.h"
#include "common.h"
#include "video_spu.h"
#include "intf_msg.h"
typedef struct spu_s
{
int i_id;
byte_t *p_data;
int x;
int y;
int width;
int height;
} spu_t;
static int NewLine ( spu_t *p_spu, int *i_id );
static int PutPixel ( spu_t *p_spu, int len, u8 color );
/* i = get_nibble(); */
#define GET_NIBBLE( i ) \
if( b_aligned ) \
{ \
i_next = *p_dest[i_id]; \
/*printf("%.1x", i_next >> 4);*/ \
p_dest[ i_id ]++; \
b_aligned = 0; \
i = i_next >> 4; \
} \
else \
{ \
b_aligned = 1; \
/*printf("%.1x", i_next & 0xf);*/ \
i = i_next & 0xf; \
}
/* i = j + get_nibble(); */
#define ADD_NIBBLE( i, j ) \
if( b_aligned ) \
{ \
i_next = *p_dest[i_id]; \
/*printf("%.1x", i_next >> 4);*/ \
p_dest[ i_id ]++; \
b_aligned = 0; \
i = (j) + (i_next >> 4); \
} \
else \
{ \
b_aligned = 1; \
/*printf("%.1x", i_next & 0xf);*/ \
i = (j) + (i_next & 0xf); \
}
/*****************************************************************************
* vout_RenderSPU: draws an SPU on a picture
*****************************************************************************
*
*****************************************************************************/
void vout_RenderSPU( byte_t *p_data, int p_offset[2], byte_t *p_pic,
int i_bytes_per_pixel, int i_bytes_per_line )
{
int i_code = 0x00;
int i_next = 0;
int i_id = 0;
boolean_t b_aligned = 1;
byte_t *p_dest[2];
spu_t spu;
p_dest[0] = p_data + p_offset[0];
p_dest[1] = p_data + p_offset[1];
spu.x = 0;
spu.y = 0;
spu.width = 720;
spu.height = 576;
spu.p_data = p_pic;
while( p_dest[0] < p_data + p_offset[1] + 2 )
{
GET_NIBBLE( i_code );
if( i_code >= 0x04 )
{
found_code:
if( PutPixel( &spu, i_code >> 2, i_code & 3 ) < 0 )
return;
if( spu.x >= spu.width )
{
/* byte-align the stream */
b_aligned = 1;
/* finish the line */
NewLine( &spu, &i_id );
}
continue;
}
ADD_NIBBLE( i_code, (i_code << 4) );
if( i_code >= 0x10 ) /* 1x .. 3x */
goto found_code;
ADD_NIBBLE( i_code, (i_code << 4) );
if( i_code >= 0x40 ) /* 04x .. 0fx */
goto found_code;
ADD_NIBBLE( i_code, (i_code << 4) );
if( i_code >= 0x100 ) /* 01xx .. 03xx */
goto found_code;
/* 00xx - should only happen for 00 00 */
if( !b_aligned )
{
ADD_NIBBLE( i_code, (i_code << 4) );
}
if( i_code )
{
intf_DbgMsg( "video_spu: unknown code 0x%x "
"(dest %x side %x, x=%d, y=%d)\n",
i_code, p_dest[i_id], i_id, spu.x, spu.y );
if( NewLine( &spu, &i_id ) < 0 )
return;
continue;
}
/* aligned 00 00 */
if( NewLine( &spu, &i_id ) < 0 )
return;
}
}
static int NewLine( spu_t *p_spu, int *i_id )
{
int i_ret = PutPixel( p_spu, p_spu->width - p_spu->x, 0 );
p_spu->x = 0;
p_spu->y++;
*i_id = 1 - *i_id;
return i_ret;
}
static int PutPixel ( spu_t *p_spu, int i_len, u8 i_color )
{
//static int p_palette[4] = { 0x0000, 0xfef8, 0x7777, 0xffff };
static int p_palette[4] = { 0x0000, 0xffff, 0x0000, 0xffff };
if( (i_len + p_spu->x + p_spu->y * p_spu->width)
> p_spu->height * p_spu->width )
{
intf_DbgMsg ( "video_spu: trying to draw beyond memory area! %d %d\n",
i_len, p_spu->height * p_spu->width
- ( i_len + p_spu->x + p_spu->y * p_spu->width) );
p_spu->x += i_len;
return -1;
}
else
{
if( i_color > 0x0f )
intf_DbgMsg( "video_spu: invalid color\n" );
if( i_color )
{
u8 *p_target
= &p_spu->p_data[2 * ( p_spu->x + p_spu->y * p_spu->width ) ];
memset( p_target, p_palette[i_color], 2 * i_len );
}
p_spu->x += i_len;
}
return 0;
}
/*****************************************************************************
* video_spu.h : DVD subpicture units functions
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
*
* 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.
*****************************************************************************/
/*****************************************************************************
* Prototypes
*****************************************************************************/
void vout_RenderSPU ( byte_t *p_data, int p_offset[2], byte_t *p_pic,
int i_bytes_per_pixel, int i_bytes_per_line );
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment