Commit 3ea1b0e9 authored by Gildas Bazin's avatar Gildas Bazin

* ALL: Major rework of the subpictures architecture.

  (expect some breakage).
* modules/video_filter/blend.c: new alpha-blending module.
parent 327a8a92
......@@ -98,6 +98,7 @@ HEADERS_include = \
include/vlc_error.h \
include/vlc_es.h \
include/vlc_es_out.h \
include/vlc_filter.h \
include/vlc_help.h \
include/vlc_httpd.h \
include/vlc_input.h \
......
......@@ -952,7 +952,7 @@ VLC_ADD_PLUGINS([trivial_mixer spdif_mixer float32_mixer])
VLC_ADD_PLUGINS([aout_file equalizer])
VLC_ADD_PLUGINS([i420_rgb i420_yuy2 i422_yuy2 i420_ymga])
VLC_ADD_PLUGINS([m3u id3 playlist export sgimb])
VLC_ADD_PLUGINS([rawvideo])
VLC_ADD_PLUGINS([rawvideo blend])
VLC_ADD_PLUGINS([wav araw subtitle adpcm a52sys dtssys au])
VLC_ADD_PLUGINS([access_file access_udp access_tcp access_http ipv4 access_mms])
VLC_ADD_PLUGINS([access_ftp access_directory sap http])
......
......@@ -53,7 +53,7 @@ struct text_style_t
};
static const text_style_t default_text_style = { 22, 0xffffff, VLC_FALSE, VLC_FALSE, VLC_FALSE };
VLC_EXPORT( subpicture_t *, vout_ShowTextRelative, ( vout_thread_t *, int, char *, text_style_t *, int, int, int, mtime_t ) );
VLC_EXPORT( int, vout_ShowTextRelative, ( vout_thread_t *, int, char *, text_style_t *, int, int, int, mtime_t ) );
VLC_EXPORT( int, vout_ShowTextAbsolute, ( vout_thread_t *, int, char *, text_style_t *, int, int, int, mtime_t, mtime_t ) );
VLC_EXPORT( void, __vout_OSDMessage, ( vlc_object_t *, int, char *, ... ) );
/**
......
......@@ -123,14 +123,26 @@ struct vout_thread_t
vout_chroma_t chroma; /**< translation tables */
/**@}*/
/* Picture and subpicture heaps */
/* Picture heap */
picture_t p_picture[2*VOUT_MAX_PICTURES+1]; /**< pictures */
/* Subpicture properties */
subpicture_t p_subpicture[VOUT_MAX_PICTURES]; /**< subpictures */
subpicture_t *p_default_channel; /**< subpicture in the default
channel */
int i_channel_count; /**< index of last subpicture
channel registered */
filter_t *p_blend; /**< alpha blending module */
filter_t *p_text; /**< text renderer module */
vlc_bool_t b_force_crop; /**< force cropping of subpicture */
int i_crop_x, i_crop_y, i_crop_width, i_crop_height; /**< cropping */
vlc_bool_t b_force_alpha; /**< force alpha palette of subpicture */
uint8_t pi_alpha[4]; /**< forced alpha palette */
/* Statistics */
count_t c_loops;
count_t c_pictures, c_late_pictures;
......@@ -144,15 +156,6 @@ struct vout_thread_t
/* Filter chain */
char *psz_filter_chain;
vlc_bool_t b_filter_change;
/* text renderer data */
text_renderer_sys_t * p_text_renderer_data; /**< private data for
the text renderer */
module_t * p_text_renderer_module; /**< text renderer module */
/** callback used when a new string needs to be shown on the vout */
subpicture_t * ( *pf_add_string ) ( vout_thread_t *, int, char *,
text_style_t *, int, int, int, mtime_t,
mtime_t );
};
#define I_OUTPUTPICTURES p_vout->output.i_pictures
......@@ -268,10 +271,16 @@ VLC_EXPORT( void, vout_DestroySubPicture, ( vout_thread_t *, subpict
VLC_EXPORT( void, vout_DisplaySubPicture, ( vout_thread_t *, subpicture_t * ) );
VLC_EXPORT( int, vout_RegisterOSDChannel, ( vout_thread_t * ) );
VLC_EXPORT( void, vout_ClearOSDChannel, ( vout_thread_t *, int ) );
subpicture_t * vout_SortSubPictures ( vout_thread_t *, mtime_t );
void vout_RenderSubPictures ( vout_thread_t *, picture_t *,
subpicture_t * );
#define spu_CreateRegion(a,b) __spu_CreateRegion(VLC_OBJECT(a),b)
VLC_EXPORT( subpicture_region_t *,__spu_CreateRegion, ( vlc_object_t *, video_format_t * ) );
#define spu_DestroyRegion(a,b) __spu_DestroyRegion(VLC_OBJECT(a),b)
VLC_EXPORT( void, __spu_DestroyRegion, ( vlc_object_t *, subpicture_region_t * ) );
void vout_InitSPU( vout_thread_t * );
void vout_DestroySPU( vout_thread_t * );
subpicture_t * vout_SortSubPictures ( vout_thread_t *, mtime_t );
void vout_RenderSubPictures( vout_thread_t *, picture_t *,
subpicture_t * );
/** @}*/
/**
* @}
......
......@@ -48,7 +48,7 @@ struct decoder_t
picture_t * ( * pf_decode_video )( decoder_t *, block_t ** );
aout_buffer_t * ( * pf_decode_audio )( decoder_t *, block_t ** );
void ( * pf_decode_sub) ( decoder_t *, block_t ** );
subpicture_t * ( * pf_decode_sub) ( decoder_t *, block_t ** );
block_t * ( * pf_packetize ) ( decoder_t *, block_t ** );
/* Some decoders only accept packetized data (ie. not truncated) */
......@@ -74,6 +74,9 @@ struct decoder_t
void ( * pf_picture_link) ( decoder_t *, picture_t * );
void ( * pf_picture_unlink) ( decoder_t *, picture_t * );
/* SPU output callbacks */
subpicture_t * ( * pf_spu_buffer_new) ( decoder_t * );
void ( * pf_spu_buffer_del) ( decoder_t *, subpicture_t * );
/* Private structure for the owner of the decoder */
decoder_owner_sys_t *p_owner;
......
......@@ -277,6 +277,7 @@ typedef struct picture_sys_t picture_sys_t;
typedef struct picture_heap_t picture_heap_t;
typedef struct subpicture_t subpicture_t;
typedef struct subpicture_sys_t subpicture_sys_t;
typedef struct subpicture_region_t subpicture_region_t;
typedef struct vout_synchro_t vout_synchro_t;
typedef struct text_renderer_sys_t text_renderer_sys_t;
typedef struct text_style_t text_style_t;
......@@ -314,6 +315,10 @@ typedef struct decoder_sys_t decoder_sys_t;
typedef struct encoder_t encoder_t;
typedef struct encoder_sys_t encoder_sys_t;
/* Filters */
typedef struct filter_t filter_t;
typedef struct filter_sys_t filter_sys_t;
/* Misc */
typedef struct data_packet_t data_packet_t;
typedef struct data_buffer_t data_buffer_t;
......
......@@ -36,10 +36,8 @@
*/
struct video_palette_t
{
int i_dummy; /**< to keep the compatibility with ffmpeg's palette */
uint32_t palette[256]; /**< 4-byte ARGB palette entries, stored in native
* byte order */
int i_dummy; /**< to keep the compatibility with ffmpeg's palette */
uint8_t palette[256][4]; /**< 4-byte RGBA/YUVA palette */
};
/**
......@@ -96,6 +94,7 @@ struct video_format_t
unsigned int i_frame_rate; /**< frame rate numerator */
unsigned int i_frame_rate_base; /**< frame rate denominator */
int i_rmask, i_rgmask, i_bmask; /**< color masks for RGB chroma */
video_palette_t *p_palette; /**< video palette from demuxer */
};
......
/*****************************************************************************
* vlc_codec.h: codec related structures
*****************************************************************************
* Copyright (C) 1999-2003 VideoLAN
* $Id$
*
* Authors: Gildas Bazin <gbazin@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.
*****************************************************************************/
#ifndef _VLC_FILTER_H
#define _VLC_FILTER_H 1
/**
* \file
* This file defines the structure and types used by video and audio filters
*/
typedef struct filter_owner_sys_t filter_owner_sys_t;
/**
* \defgroup filter Filter
*
* The structure describing a filter
*
* @{
*/
struct filter_t
{
VLC_COMMON_MEMBERS
/* Module properties */
module_t * p_module;
filter_sys_t * p_sys;
void ( * pf_video_blend ) ( filter_t *, picture_t *,
picture_t *, picture_t *,
int, int );
picture_t * ( * pf_video_filter ) ( filter_t *, picture_t * );
subpicture_t * ( *pf_render_string ) ( filter_t *, block_t * );
/* Input format */
es_format_t fmt_in;
/* Output format of filter */
es_format_t fmt_out;
/*
* Buffers allocation
*/
/* Audio output callbacks */
aout_buffer_t * ( * pf_aout_buffer_new) ( filter_t *, int );
void ( * pf_aout_buffer_del) ( filter_t *, aout_buffer_t * );
/* Video output callbacks */
picture_t * ( * pf_vout_buffer_new) ( filter_t * );
void ( * pf_vout_buffer_del) ( filter_t *, picture_t * );
void ( * pf_picture_link) ( filter_t *, picture_t * );
void ( * pf_picture_unlink) ( filter_t *, picture_t * );
/* SPU output callbacks */
subpicture_t * ( * pf_spu_buffer_new) ( filter_t * );
void ( * pf_spu_buffer_del) ( filter_t *, subpicture_t * );
/* Private structure for the owner of the decoder */
filter_owner_sys_t *p_owner;
};
/**
* @}
*/
#endif /* _VLC_FILTER_H */
......@@ -175,6 +175,8 @@ struct picture_heap_t
#define U_PITCH p[U_PLANE].i_pitch
#define V_PIXELS p[V_PLANE].p_pixels
#define V_PITCH p[V_PLANE].i_pitch
#define A_PIXELS p[A_PLANE].p_pixels
#define A_PITCH p[A_PLANE].i_pitch
/**
* \defgroup subpicture Video Subpictures
......@@ -184,6 +186,28 @@ struct picture_heap_t
* @{
*/
/**
* Video subtitle region
*
* A subtitle region is defined by a picture (graphic) and its rendering
* coordinates.
* Subtitles contain a list of regions.
*/
struct subpicture_region_t
{
/** \name Region properties */
/**@{*/
video_format_t fmt; /**< format of the picture */
picture_t picture; /**< picture comprising this region */
int i_x; /**< position of region */
int i_y; /**< position of region */
subpicture_region_t *p_next; /**< next region in the list */
/**@}*/
};
/**
* Video subtitle
*
......@@ -216,6 +240,8 @@ struct subpicture_t
untill the next one appear */
/**@}*/
subpicture_region_t *p_region; /**< region list composing this subtitle */
/** \name Display properties
* These properties are only indicative and may be
* changed by the video output thread, or simply ignored depending of the
......@@ -225,13 +251,20 @@ struct subpicture_t
int i_y; /**< offset from alignment position */
int i_width; /**< picture width */
int i_height; /**< picture height */
/**@}*/
int b_absolute; /**< position is absolute */
int i_flags; /**< position flags */
/**@}*/
/** Pointer to function that renders this subtitle in a picture */
void ( *pf_render ) ( vout_thread_t *, picture_t *, const subpicture_t * );
/** Pointer to function that cleans up the private data of this subtitle */
void ( *pf_destroy ) ( subpicture_t * );
/** Pointer to functions for region management */
subpicture_region_t * ( *pf_create_region ) ( vlc_object_t *,
video_format_t * );
void ( *pf_destroy_region ) ( vlc_object_t *, subpicture_region_t * );
/** Private data - the subtitle plugin might want to put stuff here to
* keep track of the subpicture */
subpicture_sys_t *p_sys; /* subpicture data */
......
......@@ -37,8 +37,10 @@
/*****************************************************************************
* Module descriptor.
*****************************************************************************/
static int Open ( vlc_object_t *p_this );
static void Close( vlc_object_t *p_this );
static int Open ( vlc_object_t * );
static void Close( vlc_object_t * );
static subpicture_t *Decode( decoder_t *, block_t ** );
vlc_module_begin();
set_description( _("DVB subtitles decoder") );
......@@ -173,33 +175,14 @@ typedef struct
} dvbsub_clut_t;
typedef struct dvbsub_render_s
{
uint16_t i_x;
uint16_t i_y;
dvbsub_image_t *p_rle_top;
dvbsub_image_t *p_rle_bot;
struct dvbsub_render_s *p_next;
} dvbsub_render_t;
struct subpicture_sys_t
{
dvbsub_render_t *p_objects; /* Linked list of objects to render */
};
struct decoder_sys_t
{
vout_thread_t *p_vout;
bs_t bs;
/* Decoder internal data */
int i_id;
int i_ancillary_id;
mtime_t i_pts;
int i_id;
int i_ancillary_id;
mtime_t i_pts;
dvbsub_page_t *p_page;
dvbsub_region_t *p_regions;
......@@ -207,9 +190,6 @@ struct decoder_sys_t
dvbsub_clut_t *p_clut[256];
dvbsub_clut_t default_clut;
subpicture_t *p_spu;
int i_subpic_channel;
};
......@@ -243,8 +223,6 @@ struct decoder_sys_t
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static void Decode( decoder_t *, block_t ** );
static void decode_segment( decoder_t *, bs_t * );
static void decode_page_composition( decoder_t *, bs_t * );
static void decode_region_composition( decoder_t *, bs_t * );
......@@ -254,7 +232,8 @@ static void decode_clut( decoder_t *, bs_t * );
static void free_objects( decoder_t * );
static void free_all( decoder_t * );
static void render( decoder_t *, vout_thread_t * );
static subpicture_t *render( decoder_t * );
static void default_clut_init( decoder_t * );
/*****************************************************************************
......@@ -283,8 +262,6 @@ static int Open( vlc_object_t *p_this )
p_sys->p_page = NULL;
p_sys->p_regions = NULL;
p_sys->p_objects = NULL;
p_sys->p_vout = NULL;
p_sys->p_spu = NULL;
for( i = 0; i < 256; i++ ) p_sys->p_clut[i] = NULL;
es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'd','v','b','s' ) );
......@@ -302,22 +279,6 @@ static void Close( vlc_object_t *p_this )
decoder_t *p_dec = (decoder_t*) p_this;
decoder_sys_t *p_sys = p_dec->p_sys;
if( p_sys->p_vout && p_sys->p_vout->p_subpicture != NULL )
{
subpicture_t *p_subpic;
int i_subpic;
for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
{
p_subpic = &p_sys->p_vout->p_subpicture[i_subpic];
if( p_subpic != NULL &&
( p_subpic->i_status == RESERVED_SUBPICTURE ||
p_subpic->i_status == READY_SUBPICTURE ) )
{
vout_DestroySubPicture( p_sys->p_vout, p_subpic );
}
}
}
free_all( p_dec );
free( p_sys );
}
......@@ -325,16 +286,13 @@ static void Close( vlc_object_t *p_this )
/*****************************************************************************
* Decode:
*****************************************************************************/
static void Decode( decoder_t *p_dec, block_t **pp_block )
static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
{
decoder_sys_t *p_sys = p_dec->p_sys;
block_t *p_block;
vout_thread_t *p_last_vout;
subpicture_t *p_spu = NULL;
if( pp_block == NULL || *pp_block == NULL )
{
return;
}
if( pp_block == NULL || *pp_block == NULL ) return NULL;
p_block = *pp_block;
*pp_block = NULL;
......@@ -343,7 +301,7 @@ static void Decode( decoder_t *p_dec, block_t **pp_block )
{
msg_Warn( p_dec, "non dated subtitle" );
block_Release( p_block );
return;
return NULL;
}
bs_init( &p_sys->bs, p_block->p_buffer, p_block->i_buffer );
......@@ -352,14 +310,14 @@ static void Decode( decoder_t *p_dec, block_t **pp_block )
{
msg_Dbg( p_dec, "invalid data identifier" );
block_Release( p_block );
return;
return NULL;
}
if( bs_read( &p_sys->bs, 8 ) != 0x20 && 0 ) /* Subtitle stream id */
{
msg_Dbg( p_dec, "invalid subtitle stream id" );
block_Release( p_block );
return;
return NULL;
}
while( bs_show( &p_sys->bs, 8 ) == 0x0f ) /* Sync byte */
......@@ -371,29 +329,15 @@ static void Decode( decoder_t *p_dec, block_t **pp_block )
{
msg_Warn( p_dec, "end marker not found (corrupted subtitle ?)" );
block_Release( p_block );
return;
return NULL;
}
p_last_vout = p_sys->p_vout;
if( ( p_sys->p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT,
FIND_ANYWHERE ) ) )
{
if( p_last_vout != p_sys->p_vout )
{
p_sys->i_subpic_channel =
vout_RegisterOSDChannel( p_sys->p_vout );
}
/* Check if the page is to be displayed */
if( p_sys->p_page ) render( p_dec, p_sys->p_vout );
vlc_object_release( p_sys->p_vout );
}
#ifdef DEBUG_DVBSUB
else if( p_sys->p_page ) render( p_dec, NULL );
#endif
/* Check if the page is to be displayed */
if( p_sys->p_page ) p_spu = render( p_dec );
block_Release( p_block );
return p_spu;
}
/* following functions are local */
......@@ -1174,27 +1118,6 @@ static uint16_t dvbsub_pdata8bpp( bs_t *s, uint16_t* p,
return ( i_processed + 7 ) / 8 ;
}
static dvbsub_image_t *dup_image( dvbsub_image_t *p_i )
{
dvbsub_image_t *p_image = malloc( sizeof(dvbsub_image_t) );
dvbsub_rle_t *p_rle = p_i->p_codes;
*p_image = *p_i;
p_image->p_last = NULL;
while( p_rle )
{
dvbsub_rle_t *p_last = p_image->p_last;
p_image->p_last = malloc( sizeof(dvbsub_rle_t) );
if( !p_last ) p_image->p_codes = p_image->p_last;
if( p_last ) p_last->p_next = p_image->p_last;
*p_image->p_last = *p_rle;
p_rle = p_rle->p_next;
}
return p_image;
}
static void free_image( dvbsub_image_t *p_i )
{
dvbsub_rle_t *p1;
......@@ -1210,21 +1133,6 @@ static void free_image( dvbsub_image_t *p_i )
free( p_i );
}
static void free_spu( subpicture_t *p_spu )
{
dvbsub_render_t *p_obj, *p_obj_next;
for( p_obj = p_spu->p_sys->p_objects; p_obj != NULL; p_obj = p_obj_next )
{
p_obj_next = p_obj->p_next;
free_image( p_obj->p_rle_top );
free_image( p_obj->p_rle_bot );
free( p_obj );
}
free( p_spu->p_sys );
p_spu->p_sys = NULL;
}
static void free_objects( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
......@@ -1271,201 +1179,20 @@ static void free_all( decoder_t *p_dec )
free_objects( p_dec );
}
static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
dvbsub_render_t *p_r )
{
/* Common variables */
uint8_t *p_desty;
uint16_t i,j;
uint16_t i_cnt;
uint16_t x, y;
dvbsub_rle_t* p_c;
dvbsub_image_t* p_im = p_r->p_rle_top;
i=0;
j=0;
p_desty = p_pic->Y_PIXELS;
//let's render the 1st frame
for(p_c = p_im->p_codes; p_c->p_next != NULL; p_c=p_c->p_next)
{
//if( p_c->y != 0 && p_c->t < 0x20)
if( p_c->y != 0 && p_c->t < 0x20)
{
x = j+ p_r->i_x;
y = 2*i+p_r->i_y;
//memset(p_desty+ y*p_pic->Y_PITCH + x, p_c->y, p_c->i_num);
// In YUY2 we have to set pixel per pixel
for( i_cnt = 0; i_cnt < p_c->i_num; i_cnt+=2 )
{
memset(p_desty+ y*p_pic->Y_PITCH + 2*x + i_cnt, p_c->y, 1);
//memset(p_desty+ y*p_pic->Y_PITCH + 2*x + i_cnt+1, p_c->cr, 1);
//memset(p_desty+ y*p_pic->Y_PITCH + 2*x + i_cnt+2, p_c->y, 1);
//memset(p_desty+ y*p_pic->Y_PITCH + 2*x + i_cnt+3, p_c->cb, 1);
}
}
j += p_c->i_num;
if(j >= p_im->i_cols[i])
{
i++; j=0;
}
if( i>= p_im->i_rows) break;
}
//idem for the second frame
p_im = p_r->p_rle_bot; i=0; j=0;
for(p_c = p_im->p_codes; p_c->p_next != NULL; p_c=p_c->p_next)
{
if( p_c->y != 0 && p_c->t < 0x20)
{
x = j+ p_r->i_x;
y = 2*i+1+p_r->i_y;
//memset(p_desty+ y*p_pic->Y_PITCH + x, p_c->y, p_c->i_num);
// In YUY2 we have to set pixel per pixel
for( i_cnt = 0; i_cnt < p_c->i_num; i_cnt+=2 )
{
memset(p_desty+ y*p_pic->Y_PITCH + 2*x + i_cnt, p_c->y, 1);
//memset(p_desty+ y*p_pic->Y_PITCH + 2*x + i_cnt+1, p_c->cr, 1);
//memset(p_desty+ y*p_pic->Y_PITCH + 2*x + i_cnt+2, p_c->y, 1);
//memset(p_desty+ y*p_pic->Y_PITCH + 2*x + i_cnt+3, p_c->cb, 1);
}
}
j += p_c->i_num;
if(j >= p_im->i_cols[i])
{
i++; j=0;
}
if( i>= p_im->i_rows) break;
}
}
static void RenderI42x( vout_thread_t *p_vout, picture_t *p_pic,
dvbsub_render_t *p_r )
{
/* Common variables */
uint8_t *p_desty = p_pic->Y_PIXELS;
uint8_t *p_destu = p_pic->U_PIXELS;
uint8_t *p_destv = p_pic->V_PIXELS;
dvbsub_image_t* p_im = p_r->p_rle_top;
dvbsub_rle_t* p_c;
uint16_t i, j, x, y;
int i_x_subsampling =
p_vout->output.i_chroma == VLC_FOURCC('I','4','2','2') ? 1 : 2;
/* Let's render the top field */
p_im = p_r->p_rle_bot; i = 0; j = 0;
for( p_c = p_im->p_codes; p_c->p_next != NULL; p_c = p_c->p_next )
{
if( p_c->y != 0 && p_c->t != 0xFF )
{
x = j + p_r->i_x;
y = 2 * i + p_r->i_y;
memset( p_desty + y * p_pic->Y_PITCH + x, p_c->y, p_c->i_num );
memset( p_destu + y/2 * p_pic->U_PITCH + x/i_x_subsampling,
p_c->cr, p_c->i_num/i_x_subsampling );
memset( p_destv + y/2 * p_pic->V_PITCH + x/i_x_subsampling,
p_c->cb, p_c->i_num/i_x_subsampling );
}
j += p_c->i_num;
if( j >= p_im->i_cols[i] )
{
i++; j=0;
}
if( i >= p_im->i_rows) break;
}
/* Idem for the bottom field */
p_im = p_r->p_rle_bot; i = 0; j = 0;
for( p_c = p_im->p_codes; p_c->p_next != NULL; p_c = p_c->p_next )
{
if( p_c->y != 0 && p_c->t != 0xFF )
{
x = j + p_r->i_x;
y = 2*i + 1 + p_r->i_y;
memset(p_desty+ y*p_pic->Y_PITCH + x, p_c->y, p_c->i_num);
/* No U or V (decimation) */
}
j += p_c->i_num;
if( j >= p_im->i_cols[i] )
{
i++; j=0;
}
if( i >= p_im->i_rows ) break;
}
}
static void RenderDVBSUB( vout_thread_t *p_vout, picture_t *p_pic,
const subpicture_t *p_spu )
{
dvbsub_render_t* p_render;
if( p_spu->p_sys == NULL ) return;
p_render = p_spu->p_sys->p_objects;
while( p_render )
{
switch( p_vout->output.i_chroma )
{
/* I420 target, no scaling */
case VLC_FOURCC('I','4','2','2'):
case VLC_FOURCC('I','4','2','0'):
case VLC_FOURCC('I','Y','U','V'):
case VLC_FOURCC('Y','V','1','2'):
/* As long as we just use Y info, I422 and YV12 are just equivalent
* to I420. Remember to change it the day we'll take into account
* U and V info. */
RenderI42x( p_vout, p_pic, p_render );
break;
/* RV16 target, scaling */
case VLC_FOURCC('R','V','1','6'):
msg_Err(p_vout, "unimplemented chroma: RV16");
/* RenderRV16( p_vout, p_pic, p_spu ); */
break;
/* RV32 target, scaling */
case VLC_FOURCC('R','V','2','4'):
case VLC_FOURCC('R','V','3','2'):
msg_Err(p_vout, "unimplemented chroma: RV32");
/* RenderRV32( p_vout, p_pic, p_spu ); */
break;
/* NVidia overlay, no scaling */
case VLC_FOURCC('Y','U','Y','2'):
RenderYUY2( p_vout, p_pic, p_render );
break;
default:
msg_Err( p_vout, "unknown chroma, can't render SPU" );
break;
}
p_render = p_render->p_next;
}
}
static void render( decoder_t *p_dec, vout_thread_t *p_vout )
static subpicture_t *render( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
dvbsub_render_t *p_render = NULL, *p_current, *p_last = NULL;
dvbsub_clut_t *p_clut;
dvbsub_rle_t *p_c;
subpicture_t *p_spu;
subpicture_region_t **