/*****************************************************************************
- * Common SVCD and VCD subtitle routines.
+ * Common SVCD and CVD subtitle routines.
*****************************************************************************
* Copyright (C) 2003, 2004 VideoLAN
- * $Id: common.c,v 1.6 2004/01/14 11:47:19 rocky Exp $
+ * $Id$
*
- * Author: Rocky Bernstein
+ * Author: Rocky Bernstein <rocky@panix.com>
* based on code from:
* Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
* Samuel Hocevar <sam@zoy.org>
#include <vlc/decoder.h>
#include "subtitle.h"
+#include "pixmap.h"
#include "common.h"
#ifdef HAVE_LIBPNG
#include "write_png.h"
dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
- if( !p_sys->b_packetizer )
+ if( !p_sys->b_packetizer && p_sys->p_vout )
{
/* FIXME check if it's ok to not lock vout */
- if( p_sys->p_vout != NULL && 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 );
- }
- }
- }
+ spu_Control( p_sys->p_vout->p_spu, SPU_CHANNEL_CLEAR,
+ p_sys->i_subpic_channel );
}
if( p_sys->p_block )
block_ChainRelease( p_sys->p_block );
}
+ free(p_sys->subtitle_data);
free( p_sys );
}
palette values. We work from the free space at the end to the
beginning so we can expand inline.
*/
-void
-VCDInlinePalette ( /*inout*/ uint8_t *p_dest, decoder_sys_t *p_sys,
- unsigned int i_height, unsigned int i_width )
+static void
+InlinePalette ( /*inout*/ uint8_t *p_dest, decoder_sys_t *p_sys )
{
+ const unsigned int i_width = p_sys->i_width;
+ const unsigned int i_height = p_sys->i_height;
int n = (i_height * i_width) - 1;
uint8_t *p_from = p_dest;
ogt_yuvt_t *p_to = (ogt_yuvt_t *) p_dest;
unsigned int
VCDSubGetAROverride(vlc_object_t * p_input, vout_thread_t *p_vout)
{
- char *psz_string = config_GetPsz( p_input, "sub-aspect-ratio" );
+ char *psz_string = config_GetPsz( p_input, MODULE_STRING "-aspect-ratio" );
/* Check whether the user tried to override aspect ratio */
if( !psz_string ) return 0;
}
-/* The video may be scaled. However subtitle bitmaps assume an 1:1
+/**
+ The video may be scaled. However subtitle bitmaps assume an 1:1
aspect ratio. So unless the user has specified otherwise, we
need to scale to compensate for or undo the effects of video
output scaling.
Perhaps this should go in the Render routine? The advantage would
be that it will deal with a dynamically changing aspect ratio.
The downside is having to scale many times for each render call.
+
+ We also expand palette entries here, unless we are dealing with a
+ palettized chroma (e.g. RGB2).
*/
void
vlc_object_t * p_input = p_spu->p_sys->p_input;
vout_thread_t *p_vout = vlc_object_find( p_input, VLC_OBJECT_VOUT,
FIND_CHILD );
- unsigned int i_aspect_x, i_aspect_y;
+ int i_aspect_x, i_aspect_y;
+ uint8_t *p_dest = (uint8_t *)p_spu->p_sys->p_data;
+
if (p_vout) {
/* Check for user-configuration override. */
- unsigned int i_new_aspect = VCDSubGetAROverride( p_input, p_vout );
- if (i_new_aspect == VOUT_ASPECT_FACTOR) {
- /* For scaling 1:1, nothing needs to be done. Note this means
- subtitles will get scaled the same way the video does.
- */
- ;
- } else {
- if (0 == i_new_aspect) {
- /* Counteract the effects of background video scaling when
- there is scaling. That's why x and y are reversed from
- the else branch in the call below.
- */
- switch( p_vout->output.i_chroma )
- {
- /* chromas which are not scaled: */
- case VLC_FOURCC('I','4','2','0'):
- case VLC_FOURCC('I','Y','U','V'):
- case VLC_FOURCC('Y','V','1','2'):
- case VLC_FOURCC('Y','U','Y','2'):
- return;
- break;
-
- /* chromas which are scaled: */
- case VLC_FOURCC('R','V','1','6'):
- case VLC_FOURCC('R','V','2','4'):
- case VLC_FOURCC('R','V','3','2'):
- case VLC_FOURCC('R','G','B','2'):
- break;
-
- default:
- msg_Err( p_vout, "unknown chroma %x",
- p_vout->output.i_chroma );
- return;
- break;
- }
- /* We get here only for scaled chromas. */
- vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y,
- &i_aspect_x );
- } else {
- /* User knows best? */
- vout_AspectRatio( i_new_aspect, &i_aspect_x, &i_aspect_y );
+ unsigned int i_new_aspect;
+
+ if ( p_vout->output.i_chroma == VLC_FOURCC('R','G','B','2') ) {
+ /* This is an unscaled palettized format. We don't allow
+ user scaling here. And to make the render process faster,
+ we don't expand the palette entries into a color value.
+ */
+ return;
+ }
+
+ InlinePalette( p_dest, p_dec->p_sys );
+ i_new_aspect = VCDSubGetAROverride( p_input, p_vout );
+
+ if (i_new_aspect == VOUT_ASPECT_FACTOR) {
+ /* For scaling 1:1, nothing needs to be done. Note this means
+ subtitles will get scaled the same way the video does.
+ */
+ ;
+ } else {
+ if (0 == i_new_aspect) {
+ /* Counteract the effects of background video scaling when
+ there is scaling. That's why x and y are reversed from
+ the else branch in the call below.
+ */
+ switch( p_vout->output.i_chroma )
+ {
+ /* chromas in which scaling is done outside of our
+ blending routine, so we need to compensate for those
+ effects before blending gets called: */
+ case VLC_FOURCC('I','4','2','0'):
+ case VLC_FOURCC('I','Y','U','V'):
+ case VLC_FOURCC('Y','V','1','2'):
+ case VLC_FOURCC('Y','U','Y','2'):
+ break;
+
+ /* chromas in which scaling is done in our blending
+ routine and thus we don't do it here: */
+ case VLC_FOURCC('R','V','1','6'):
+ case VLC_FOURCC('R','V','2','4'):
+ case VLC_FOURCC('R','V','3','2'):
+ case VLC_FOURCC('R','G','B','2'):
+ return;
+ break;
+
+ default:
+ msg_Err( p_vout, "unknown chroma %x",
+ p_vout->output.i_chroma );
+ return;
+ break;
}
- VCDSubScaleX( p_dec, p_spu, i_aspect_x, i_aspect_y );
- }
+ /* We get here only for scaled chromas. */
+ vlc_reduce( &i_aspect_x, &i_aspect_y, p_vout->render.i_aspect,
+ VOUT_ASPECT_FACTOR, 0 );
+ } else {
+ /* User knows best? */
+ vlc_reduce( &i_aspect_x, &i_aspect_y, p_vout->render.i_aspect,
+ VOUT_ASPECT_FACTOR, 0 );
+ }
+ VCDSubScaleX( p_dec, p_spu, i_aspect_x, i_aspect_y );
+ }
}
}
printf("\n-------------------------------------\n");
}
-/*
- FIXME:
- MOVE clip_8_bit and uuv2rgb TO A MORE GENERIC PLACE.
- */
-
-/* Force v in the range 0.255 */
-static inline uint8_t
-clip_8_bit(int v)
-{
- if (v<0) return 0;
- if (v>255) return 255;
- return (uint8_t) v;
-}
-
-/***************************************************
- Color conversion from
- http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC30
- http://people.ee.ethz.ch/~buc/brechbuehler/mirror/color/ColorFAQ.html
-
- Thanks to Billy Biggs <vektor@dumbterm.net> for the pointer and
- the following conversion.
-
- R' = [ 1.1644 0 1.5960 ] ([ Y' ] [ 16 ])
- G' = [ 1.1644 -0.3918 -0.8130 ] * ([ Cb ] - [ 128 ])
- B' = [ 1.1644 2.0172 0 ] ([ Cr ] [ 128 ])
-
- See also vlc/modules/video_chroma/i420_rgb.h and
- vlc/modules/video_chroma/i420_rgb_c.h for a way to do this in a way
- more optimized for integer arithmetic. Would be nice to merge the
- two routines.
-
-***************************************************/
-
-static inline void
-yuv2rgb(ogt_yuvt_t *p_yuv, uint8_t *p_rgb_out )
-{
-
- int i_Y = p_yuv->s.y - 16;
- int i_Cb = p_yuv->s.v - 128;
- int i_Cr = p_yuv->s.u - 128;
-
- int i_red = (1.1644 * i_Y) + (1.5960 * i_Cr);
- int i_green = (1.1644 * i_Y) - (0.3918 * i_Cb) - (0.8130 * i_Cr);
- int i_blue = (1.1644 * i_Y) + (2.0172 * i_Cb);
-
- i_red = clip_8_bit( i_red );
- i_green = clip_8_bit( i_green );
- i_blue = clip_8_bit( i_blue );
-
- *p_rgb_out++ = i_red;
- *p_rgb_out++ = i_green;
- *p_rgb_out++ = i_blue;
-
-}
-
#ifdef HAVE_LIBPNG
-#define BYTES_PER_RGB 3
#define PALETTE_SIZE 4
/* Note the below assumes the above is a power of 2 */
#define PALETTE_SIZE_MASK (PALETTE_SIZE-1)
{
decoder_sys_t *p_sys = p_dec->p_sys;
uint8_t *p = p_image;
- uint8_t *image_data = malloc(BYTES_PER_RGB * i_height * i_width );
+ uint8_t *image_data = malloc(RGB_SIZE * i_height * i_width );
uint8_t *q = image_data;
unsigned int i_row; /* scanline row number */
unsigned int i_column; /* scanline column number */
- uint8_t rgb_palette[PALETTE_SIZE * BYTES_PER_RGB];
+ uint8_t rgb_palette[PALETTE_SIZE * RGB_SIZE];
int i;
dbg_print( (DECODE_DBG_CALL), "%s", filename);
/* Convert palette YUV into RGB. */
for (i=0; i<PALETTE_SIZE; i++) {
ogt_yuvt_t *p_yuv = &(p_sys->p_palette[i]);
- uint8_t *p_rgb_out = &(rgb_palette[i*BYTES_PER_RGB]);
+ uint8_t *p_rgb_out = &(rgb_palette[i*RGB_SIZE]);
yuv2rgb( p_yuv, p_rgb_out );
}
/* Convert palette entries into linear RGB array. */
for ( i_row=0; i_row < i_height; i_row ++ ) {
for ( i_column=0; i_column<i_width; i_column++ ) {
- uint8_t *p_rgb = &rgb_palette[ ((*p)&PALETTE_SIZE_MASK)*BYTES_PER_RGB ];
+ uint8_t *p_rgb = &rgb_palette[ ((*p)&PALETTE_SIZE_MASK)*RGB_SIZE ];
*q++ = p_rgb[0];
*q++ = p_rgb[1];
*q++ = p_rgb[2];